Number | Details | Instances |
---|---|---|
[High-1] | Interation uses 'msg.value' within. This msg.value value is compared against a dynamic variable per iteration which fails to protect the function for using more ether than intended as it falsely assume that msg.value is not static when in reality it is. |
1 |
Number | Details | Instances |
---|---|---|
[Medium-1] | Public or external initialize functions should be protected with the initializer modifier | 1 |
[Medium-2] | Use of msg.value inside for loop causes reverts | 2 |
[Medium-3] | Contract contains payable functions but no withdraw/sweep function | 1 |
Number | Details | Instances |
---|---|---|
[Low-1] | Potential division by zero should have zero checks in place | 20 |
[Low-2] | Division operations should always be performed after multiplication operations | 1 |
[Low-3] | Subtraction may underflow if multiplication is too large | 12 |
[Low-4] | Incorrect comparison against a max value | 2 |
[Low-5] | Incorrect comparison against a min value | 1 |
[Low-6] | Function call without checking or using it's return values | 1 |
[Low-7] | The function decimals() is not part of the ERC20 standard | 1 |
[Low-8] | Loss of precision | 24 |
[Low-9] | Using zero as a parameter | 15 |
[Low-10] | Price should round up | 2 |
[Low-11] | Remaining eth may not be refunded to users | 2 |
[Low-12] | Constant decimal values | 43 |
[Low-13] | Avoid using msg.sig for validation | 1 |
[Low-14] | Don't assume specific ETH balance | 2 |
[Low-15] | Avoid mutating function parameters | 11 |
[Low-16] | Vulnerable version of openzeppelin contracts used | 1 |
[Low-17] | Try catch statement without human readable error | 1 |
[Low-18] | Division in comparison | 14 |
[Low-19] | Low decimals can introduce more rounding related issues | 1 |
[Low-20] | Missing events in functions that are either setters, privileged or voting related | 2 |
[Low-21] | Read only reentrancy risk detected | 4 |
[Low-22] | Common tokens such as WETH9 work differently on chains such a Blast which isn't taken into account during transfer calls. |
1 |
[Low-23] | Consider a uptime feed on L2 deployments to prevent issues caused by downtime | 10 |
[Low-24] | Custom implementation of a roundUp operation, consider using mulDivUp instead |
9 |
Number | Details | Instances |
---|---|---|
[NonCritical-1] | Unchecked blocks with subtractions may underflow | 2 |
[NonCritical-2] | Addresses shouldn't be hard-coded | 1 |
[NonCritical-3] | Consider using time variables when defining time related variables | 6 |
[NonCritical-4] | Users can manipulate mapping values for other users | 2 |
[NonCritical-5] | Address function parameter is compared against a state variable. This check can be bypassed for tokens with multiple addresses (proxy tokens) | 1 |
[NonCritical-6] | Interfaces should be declared in a separate file | 1 |
[NonCritical-7] | Events regarding state variable changes should emit the previous state variable value | 8 |
[NonCritical-8] | In functions which accept an address as a parameter, there should be a zero address check to prevent bugs | 10 |
[NonCritical-9] | Enum values should be used in place of constant array indexes | 1 |
[NonCritical-10] | Default int values are manually set | 1 |
[NonCritical-11] | Revert statements within external and public functions can be used to perform DOS attacks | 32 |
[NonCritical-12] | Private and internal state variables should have a preceding _ in their name unless they are constants | 20 |
[NonCritical-13] | Contract lines should not be longer than 120 characters for readability | 214 |
[NonCritical-14] | Not all event definitions are utilizing indexed variables. | 26 |
[NonCritical-15] | Contracts should have all public/external functions exposed by interfaces | 36 |
[NonCritical-16] | uint/int variables should have the bit size defined explicitly | 258 |
[NonCritical-17] | Functions within contracts are not ordered according to the solidity style guide | 4 |
[NonCritical-18] | Emits without msg.sender parameter | 10 |
[NonCritical-19] | Unused state variables present | 4 |
[NonCritical-20] | Constants should be on the left side of the comparison | 102 |
[NonCritical-21] | Overly complicated arithmetic | 55 |
[NonCritical-22] | Use of non-named numeric constants | 114 |
[NonCritical-23] | Inconsistent usage of int/uint with int256/uint256 in contract/abstract/library/interface | 8 |
[NonCritical-24] | Use immutable not constant for keccak state variables | 1 |
[NonCritical-25] | Event emit should emit a parameter | 2 |
[NonCritical-26] | Empty bytes check is missing | 3 |
[NonCritical-27] | Assembly block creates dirty bits | 1 |
[NonCritical-28] | Cyclomatic complexity in functions | 22 |
[NonCritical-29] | Don't only depend on Solidity's arithmetic ordering. | 44 |
[NonCritical-30] | Empty revert statement | 1 |
[NonCritical-31] | Use 'using' keyword when using specific imports rather than calling the specific import directly | 13 |
[NonCritical-32] | Simplify complex revert statements | 1 |
[NonCritical-33] | Constructors should emit an event | 2 |
[NonCritical-34] | Events should have parameters | 2 |
[NonCritical-35] | Avoid arithmetic directly within array indices | 2 |
[NonCritical-36] | Unnecessary struct attribute prefix | 5 |
Number | Details | Instances | Gas |
---|---|---|---|
[Gas-1] | State variable can be updated more than once in a function | 3 | 9600 |
[Gas-2] | Multiple accesses of the same mapping/array key/index should be cached | 3 | 378 |
[Gas-3] | Public functions not used internally can be marked as external to save gas | 22 | 0.0 |
[Gas-4] | Usage of smaller uint/int types causes overhead | 4 | 880 |
[Gas-5] | Use != 0 instead of > 0 | 51 | 7803 |
[Gas-6] | Integer increments by one can be unchecked to save on gas fees | 1 | 120 |
[Gas-7] | Default int values are manually reset | 12 | 0.0 |
[Gas-8] | Function calls within for loops | 4 | 0.0 |
[Gas-9] | For loops in public or external functions should be avoided due to high gas costs and possible DOS | 2 | 0.0 |
[Gas-10] | Use assembly to check for the zero address | 2 | 0.0 |
[Gas-11] | Divisions which do not divide by -X cannot overflow or underflow so such operations can be unchecked to save gas | 4 | 0.0 |
[Gas-12] | Divisions of powers of 2 can be replaced by a right shift operation to save gas | 3 | 0.0 |
[Gas-13] | Structs can be packed into fewer storage slots | 7 | 122500 |
[Gas-14] | Expression ("") is cheaper than new bytes(0) | 14 | 50764 |
[Gas-15] | Private functions used once can be inlined | 1 | 0.0 |
[Gas-16] | Use assembly to emit events | 31 | 36518 |
[Gas-17] | Use assembly in place of abi.decode to extract calldata values more efficiently | 2 | 0.0 |
[Gas-18] | Lack of unchecked in loops | 2 | 240 |
[Gas-19] | Where a value is casted more than once, consider caching the result to save gas | 2 | 0.0 |
[Gas-20] | Assembly let var only used on once | 1 | 0.0 |
[Gas-21] | Use assembly to validate msg.sender | 1 | 0.0 |
[Gas-22] | Using nested if to save gas | 44 | 11616 |
[Gas-23] | Using delete instead of setting mapping to 0 saves gas | 1 | 5 |
[Gas-24] | Calling .length in a for loop wastes gas | 4 | 1552 |
[Gas-25] | Internal functions only used once can be inlined to save gas | 4 | 480 |
[Gas-26] | Constructors can be marked as payable to save deployment gas | 4 | 0.0 |
[Gas-27] | Internal functions never used once can be removed | 1 | 0.0 |
[Gas-28] | Only emit event in setter function if the state variable was changed | 1 | 0.0 |
[Gas-29] | Use OZ Array.unsafeAccess() to avoid repeated array length checks | 17 | 606900 |
[Gas-30] | Use uint256(1)/uint256(2) instead of true/false to save gas for changes | 3 | 153000 |
[Gas-31] | Consider pre-calculating the address of address(this) to save gas | 10 | 0.0 |
[Gas-32] | Use constants instead of type(uint).max | 2 | 0.0 |
[Gas-33] | Using named returns for pure and view functions is cheaper than using regular returns | 5 | 650 |
[High-1] Interation uses 'msg.value' within. This msg.value
value is compared against a dynamic variable per iteration which fails to protect the function for using more ether than intended as it falsely assume that msg.value is not static when in reality it is.
Using msg.value within interation on itself is highly risky due to the threat vectors it opens as msg.value doesn't decrease even if the value was used in ether/payable operations on past iterations of the for/while loop, it remains static. This runs the risk of msg.value being used repeatedly as the 'value' parameter of payable operations when this may not have been intended. Simply comparing msg.value to a dynamic amount variable does not protect against this, rather the msg.value value should be cached outside of the loop and this cached value should be used in msg.value's place. This value should also be decreased '-=' by the 'amount' value used every iteration to ensure only the intended amount of ether is spent/used. These for loops are especially dangerous when used in delegate calls as such patterns open a direct risk of contract drainage by a threat actor.
Num of instances: 1
Click to show findings
['93']
93: for (uint i = 0; i < 2; i++) { // <= FOUND
94: if (i == 0) {
95: token_ = c_.token0;
96: amt_ = token0Amt_;
97: } else {
98: token_ = c_.token1;
99: amt_ = token1Amt_;
100: }
101: if (token_ == NATIVE_TOKEN) {
102: if (msg.value > amt_) { // <= FOUND
103: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_);
104: } else if (msg.value < amt_) {
105: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
106: }
107:
108: liquidity_.operate{ value: amt_ }(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
109: } else {
110:
111: liquidity_.operate(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
112: }
113: }
[Medium-1] Public or external initialize functions should be protected with the initializer modifier
The initializer modifiers ensures two key aspects. A) Only an authorised account can initialize B) initialization can only be done once. Consider using such a modifier and in instances where initialization can be done more than once, the function name should be changed to reflect that.
Num of instances: 1
Click to show findings
['626']
626: function initialize(InitializeVariables memory i_) public payable _onlyDelegateCall { // <= FOUND
627: _checkIsContract(TEAM_MULTISIG);
628:
629: if (!(i_.smartCol || i_.smartDebt)) {
630:
631: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
632: }
633:
634:
635: if(i_.revenueCut != 0 && i_.revenueCut < FOUR_DECIMALS){
636:
637: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
638: }
639:
641:
642: i_.revenueCut = i_.revenueCut / FOUR_DECIMALS;
643: i_.upperShiftThreshold = i_.upperShiftThreshold / THREE_DECIMALS;
644: i_.lowerShiftThreshold = i_.lowerShiftThreshold / THREE_DECIMALS;
645:
646: if (
647: (i_.fee > FIVE_DECIMALS) ||
648: (i_.revenueCut > TWO_DECIMALS) ||
649: (i_.upperPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
650: (i_.lowerPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
651: (i_.upperPercent == 0) ||
652: (i_.lowerPercent == 0) ||
653: (i_.upperShiftThreshold > THREE_DECIMALS) ||
654: (i_.lowerShiftThreshold > THREE_DECIMALS) ||
655: (i_.upperShiftThreshold == 0) ||
656: (i_.lowerShiftThreshold == 0) ||
657: (i_.thresholdShiftTime == 0) ||
658: (i_.thresholdShiftTime > X24) ||
659: (i_.centerPriceAddress > X30) ||
660: (i_.hookAddress > X30) ||
661: (i_.centerPrice <= i_.minCenterPrice) ||
662: (i_.centerPrice >= i_.maxCenterPrice) ||
663: (i_.minCenterPrice == 0)
664: ) {
665: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
666: }
667:
668: uint dexVariables2_;
669:
670: if (i_.smartCol) {
671: _turnOnSmartCol(i_.token0ColAmt, i_.centerPrice);
672: dexVariables2_ = dexVariables2_ | 1;
673: }
674:
675: if (i_.smartDebt) {
676: _turnOnSmartDebt(i_.token0DebtAmt, i_.centerPrice);
677: dexVariables2_ = dexVariables2_ | 2;
678: }
679:
680: i_.centerPrice = i_.centerPrice.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN);
681:
682: dexVariables = (i_.centerPrice << 1) |
683: (i_.centerPrice << 41) |
684: (i_.centerPrice << 81) |
685: (block.timestamp << 121) |
686: (60 << 154) |
687: (7 << 176);
688:
689: dexVariables2 = dexVariables2_ |
690: (i_.fee << 2) |
691: (i_.revenueCut << 19) |
692: (i_.upperPercent << 27) |
693: (i_.lowerPercent << 47) |
694: (i_.upperShiftThreshold << 68) |
695: (i_.lowerShiftThreshold << 78) |
696: (i_.thresholdShiftTime << 88) |
697: (i_.centerPriceAddress << 112) |
698: (i_.hookAddress << 142) |
699: (i_.maxCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_UP) << 172) |
700: (i_.minCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_DOWN) << 200) |
701: (THREE_DECIMALS << 228) |
702: (THREE_DECIMALS << 238);
703:
704: emit LogInitializePoolConfig(
705: i_.smartCol,
706: i_.smartDebt,
707: i_.token0ColAmt,
708: i_.token0DebtAmt,
709: i_.fee,
710: i_.revenueCut * FOUR_DECIMALS,
711: i_.centerPriceAddress,
712: i_.hookAddress
713: );
714:
715: emit LogInitializePriceParams(
716: i_.upperPercent,
717: i_.lowerPercent,
718: i_.upperShiftThreshold * THREE_DECIMALS,
719: i_.lowerShiftThreshold * THREE_DECIMALS,
720: i_.thresholdShiftTime,
721: i_.maxCenterPrice,
722: i_.minCenterPrice
723: );
724: }
Using msg.value
in a for loop can potentially lead to problems if that loop is making external contract calls. Ethereum contracts are stateful, and msg.value
represents the amount of Ether sent in the transaction initiating the current contract execution. If you have a loop where each iteration triggers a payable external function call, msg.value
would stay constant through all iterations, which might not be the expected behavior. This could cause incorrect amounts of Ether being sent or could drain more funds than expected.
For example, consider a case where you're iterating over an array of addresses, and for each address, you want to send a specific amount of Ether. If you're not carefully managing msg.value
in each iteration, you could unintentionally send the total transaction value to each address, quickly depleting the contract's funds.
The resolution would be to carefully manage the Ether sent in each iteration of the loop. This could be done by dividing msg.value
by the number of iterations beforehand, and sending that amount in each external call. Or, depending on your use-case, you could create separate transactions for each operation to explicitly control the amount of Ether sent. Additionally, you should also include proper checks and balance updates within each iteration to ensure the contract's funds are handled securely and correctly.
Num of instances: 2
Click to show findings
['93']
93: for (uint i = 0; i < 2; i++) {
94: if (i == 0) {
95: token_ = c_.token0;
96: amt_ = token0Amt_;
97: } else {
98: token_ = c_.token1;
99: amt_ = token1Amt_;
100: }
101: if (token_ == NATIVE_TOKEN) {
102: if (msg.value > amt_) { // <= FOUND
103: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_); // <= FOUND
104: } else if (msg.value < amt_) { // <= FOUND
105: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
106: }
107:
108: liquidity_.operate{ value: amt_ }(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
109: } else {
110:
111: liquidity_.operate(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
112: }
113: }
['93']
93: for (uint i = 0; i < 2; i++) {
94: if (i == 0) {
95: token_ = c_.token0;
96: amt_ = token0Amt_;
97: } else {
98: token_ = c_.token1;
99: amt_ = token1Amt_;
100: }
101: if (token_ == NATIVE_TOKEN) {
102: if (msg.value > amt_) { // <= FOUND
103: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_); // <= FOUND
104: } else if (msg.value < amt_) { // <= FOUND
105: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
106: }
107:
108: liquidity_.operate{ value: amt_ }(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
109: } else {
110:
111: liquidity_.operate(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
112: }
113: }
In smart contract development, particularly for Ethereum, having payable functions without a corresponding withdraw or sweep function can lead to potential issues. Payable functions allow the contract to receive Ether, but without a mechanism to withdraw these funds, the Ether can become locked within the contract indefinitely. This situation might be intentional in some cases (like a burn function), but generally, it’s a design oversight. A withdraw or sweep function is necessary to transfer Ether out of the contract to a specific address, typically the owner's or a designated recipient. Without this, the contract lacks flexibility in managing its funds, potentially leading to lost or inaccessible Ether.
Num of instances: 1
Click to show findings
['21']
21: contract FluidDexT1Admin is ConstantVariables, Variables, Structs, Events, Error
Implement a zero address check for found instances
Num of instances: 20
Click to show findings
['26']
26: function _verifyToken0Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
27: if (((token0Reserves_) < (token1Reserves_ * 1e27 / (centerPrice_ * minLiquidity_)))) { // <= FOUND
28: revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);
29: }
30: }
['33']
33: function _verifyToken1Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
34: if (((token1Reserves_) < (token0Reserves_ * centerPrice_ / (1e27 * minLiquidity_)))) { // <= FOUND
35: revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);
36: }
37: }
['26']
26: function _getAmountOut( // <= FOUND
27: uint256 amountIn_,
28: uint iReserveIn_,
29: uint iReserveOut_
30: ) internal pure returns (uint256 amountOut_) {
31:
32: uint256 numerator_ = amountIn_ * iReserveOut_;
33: uint256 denominator_ = iReserveIn_ + amountIn_;
34:
35:
36: amountOut_ = numerator_ / denominator_; // <= FOUND
37: }
['43']
43: function _getAmountIn( // <= FOUND
44: uint256 amountOut_,
45: uint iReserveIn_,
46: uint iReserveOut_
47: ) internal pure returns (uint256 amountIn_) {
48:
49: uint256 numerator_ = amountOut_ * iReserveIn_;
50: uint256 denominator_ = iReserveOut_ - amountOut_;
51:
52:
53: amountIn_ = numerator_ / denominator_; // <= FOUND
54: }
['62']
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
63: if (current_ > old_) {
64: uint diff_ = current_ - old_;
65: current_ = old_ + (diff_ * timePassed_ / shiftDuration_); // <= FOUND
66: } else {
67: uint diff_ = old_ - current_;
68: current_ = old_ - (diff_ * timePassed_ / shiftDuration_);
69: }
70: return current_;
71: }
['147']
147: function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) { // <= FOUND
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40;
149: oldCenterPrice_ = (oldCenterPrice_ >> DEFAULT_EXPONENT_SIZE) << (oldCenterPrice_ & DEFAULT_EXPONENT_MASK);
150: uint centerPriceShift_ = _centerPriceShift;
151: uint startTimeStamp_ = centerPriceShift_ & X33;
152: uint percent_ = (centerPriceShift_ >> 33) & X20;
153: uint time_ = (centerPriceShift_ >> 53) & X20;
154:
155: uint fromTimeStamp_ = (dexVariables_ >> 121) & X33;
156: fromTimeStamp_ = fromTimeStamp_ > startTimeStamp_ ? fromTimeStamp_ : startTimeStamp_;
157:
158: newCenterPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, ((dexVariables2_ >> 112) & X30))).centerPrice();
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS); // <= FOUND
160:
161: if (newCenterPrice_ > oldCenterPrice_) {
162:
163: oldCenterPrice_ += priceShift_;
164: if (newCenterPrice_ > oldCenterPrice_) {
165: newCenterPrice_ = oldCenterPrice_;
166: } else {
167:
168: delete _centerPriceShift;
169:
170:
171: dexVariables2 = dexVariables2 & ~uint(1 << 248);
172: }
173: } else {
174: unchecked {
175: oldCenterPrice_ = oldCenterPrice_ > priceShift_ ? oldCenterPrice_ - priceShift_ : 0;
176:
177:
178:
179:
180: }
181: if (newCenterPrice_ < oldCenterPrice_) {
182: newCenterPrice_ = oldCenterPrice_;
183: } else {
184:
185: delete _centerPriceShift;
186:
187:
188: dexVariables2 = dexVariables2 & ~uint(1 << 248);
189: }
190: }
191: }
['350']
350: function _calculateReservesOutsideRange( // <= FOUND
351: uint gp_,
352: uint pa_,
353: uint rx_,
354: uint ry_
355: ) internal pure returns (
356: uint xa_,
357: uint yb_
358: ) {
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383: uint p1_ = pa_ - gp_;
384: uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);
385: uint p3_ = rx_ * ry_;
386:
387: p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27; // <= FOUND
388:
389:
390:
391: xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));
392: yb_ = (xa_ * gp_) / 1e27;
393: }
['433']
433: function getCollateralReserves( // <= FOUND
434: uint geometricMean_,
435: uint upperRange_,
436: uint lowerRange_,
437: uint token0SupplyExchangePrice_,
438: uint token1SupplyExchangePrice_
439: ) public view returns (CollateralReserves memory c_) {
440: uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);
441: uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);
442:
443: if (geometricMean_ < 1e27) {
444: (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(geometricMean_, upperRange_, token0Supply_, token1Supply_);
445: } else {
446:
447:
448:
449:
450: (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange((1e54 / geometricMean_), (1e54 / lowerRange_), token1Supply_, token0Supply_); // <= FOUND
451: }
452:
453: c_.token0RealReserves = token0Supply_;
454: c_.token1RealReserves = token1Supply_;
455: c_.token0ImaginaryReserves += token0Supply_;
456: c_.token1ImaginaryReserves += token1Supply_;
457: }
['470']
470: function _calculateDebtReserves( // <= FOUND
471: uint gp_,
472: uint pb_,
473: uint dx_,
474: uint dy_
475: ) internal pure returns (
476: uint rx_,
477: uint ry_,
478: uint irx_,
479: uint iry_
480: ) {
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534: int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);
535: uint p2_ = (dx_ * dy_);
536: p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;
537: ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));
538:
539:
540:
541:
542:
543:
544:
545:
546:
547: iry_ = ((ry_ * 1e27) - (dx_ * pb_));
548: if (iry_ < SIX_DECIMALS) {
549:
550: revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);
551: }
552: if (ry_ < 1e25) {
553: iry_ = (ry_ * ry_ * 1e27) / iry_; // <= FOUND
554: } else {
555:
556: iry_ = (ry_ * ry_) / (iry_ / 1e27);
557: }
558:
559:
560:
561:
562:
563:
564: irx_ = ((iry_ * dx_) / ry_) - dx_;
565:
566:
567:
568:
569: rx_ = (irx_ * dy_) / (iry_ + dy_);
570: }
['610']
610: function getDebtReserves( // <= FOUND
611: uint geometricMean_,
612: uint upperRange_,
613: uint lowerRange_,
614: uint token0BorrowExchangePrice_,
615: uint token1BorrowExchangePrice_
616: ) public view returns (DebtReserves memory d_) {
617: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);
618: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);
619:
620: d_.token0Debt = token0Debt_;
621: d_.token1Debt = token1Debt_;
622:
623: if (geometricMean_ < 1e27) {
624: (d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);
625: } else {
626:
627:
628:
629:
630: (d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_); // <= FOUND
631: }
632:
633: }
['644']
644: function _swapRoutingIn( // <= FOUND
645: uint t,
646: uint x,
647: uint y,
648: uint x2,
649: uint y2
650: ) internal pure returns (
651: int a_
652: ) {
653:
654:
655:
656:
657:
658:
659:
660:
661: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
663:
664: a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
665: }
['676']
676: function _swapRoutingOut( // <= FOUND
677: uint t,
678: uint x,
679: uint y,
680: uint x2,
681: uint y2
682: ) internal pure returns (
683: int a_
684: ) {
685:
686:
687:
688:
689:
690:
691:
692:
693: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
694: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
695:
696:
697: a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
698: }
['705']
705: function _getSwapAndDeposit( // <= FOUND
706: uint c_,
707: uint d_,
708: uint e_,
709: uint f_,
710: uint i_
711: ) internal pure returns (
712: uint shares_
713: ) {
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_; // <= FOUND
737: uint temp2_ = 4 * c_ * e_;
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
739:
740:
741:
742:
743:
744: if (
745: (amtToSwap_ > ((c_ * SIX_DECIMALS - 1) / SIX_DECIMALS)) ||
746: (amtToSwap_ < (c_ / SIX_DECIMALS))
747: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndDepositTooLowOrTooHigh);
748:
749:
750: temp_ = c_ - amtToSwap_;
751:
752:
753: temp2_ = (d_ * amtToSwap_) / (e_ + amtToSwap_);
754:
755:
756: temp_ = temp_ * 1e18 / (f_ + amtToSwap_);
757:
758: temp2_ = temp2_ * 1e18 / (i_ - temp2_);
759:
760: shares_ = temp_ > temp2_ ? temp2_ : temp_;
761: }
['769']
769: function _getUpdatedColReserves( // <= FOUND
770: uint newShares_,
771: uint totalOldShares_,
772: CollateralReserves memory c_,
773: bool mintOrBurn_
774: ) internal pure returns (
775: CollateralReserves memory c2_
776: ) {
777: if (mintOrBurn_) {
778:
779: c2_.token0RealReserves = c_.token0RealReserves + c_.token0RealReserves * newShares_ / totalOldShares_; // <= FOUND
780: c2_.token1RealReserves = c_.token1RealReserves + c_.token1RealReserves * newShares_ / totalOldShares_;
781: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves + c_.token0ImaginaryReserves * newShares_ / totalOldShares_;
782: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves + c_.token1ImaginaryReserves * newShares_ / totalOldShares_;
783: } else {
784:
785: c2_.token0RealReserves = c_.token0RealReserves - (c_.token0RealReserves * newShares_ / totalOldShares_);
786: c2_.token1RealReserves = c_.token1RealReserves - (c_.token1RealReserves * newShares_ / totalOldShares_);
787: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves - (c_.token0ImaginaryReserves * newShares_ / totalOldShares_);
788: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves - (c_.token1ImaginaryReserves * newShares_ / totalOldShares_);
789: }
790: return c2_;
791: }
['798']
798: function _getWithdrawAndSwap( // <= FOUND
799: uint c_,
800: uint d_,
801: uint e_,
802: uint f_,
803: uint g_
804: ) internal pure returns (
805: uint shares_
806: ) {
807:
808:
809:
810:
811:
812:
813:
814:
815:
816:
817:
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
830:
831:
832:
833:
834:
835:
836:
837:
838:
839:
840:
841:
842:
843:
844:
845:
846:
847: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_);
848:
849:
850: uint temp2_ = (((c_ * f_) / d_) + c_) * g_;
851:
852:
853: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_);
854:
855:
856:
857:
858:
859: if (
860: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
861: tokenAxa_ < (g_ / SIX_DECIMALS)
862: ) revert FluidDexError(ErrorTypes.DexT1__WithdrawAndSwapTooLowOrTooHigh);
863:
864: shares_ = tokenAxa_ * 1e18 / c_; // <= FOUND
865: }
['872']
872: function _getBorrowAndSwap( // <= FOUND
873: uint c_,
874: uint d_,
875: uint e_,
876: uint f_,
877: uint g_
878: ) internal pure returns (
879: uint shares_
880: ) {
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915:
916:
917:
918:
919:
920: uint temp_ = (c_ * f_ + d_ * e_ + d_ * g_) / (2 * d_);
921:
922:
923:
924: uint temp2_ = (c_ * f_ * g_) / d_;
925:
926:
927: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_);
928:
929:
930:
931:
932:
933: if (
934: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
935: tokenAxa_ < (g_ / SIX_DECIMALS)
936: ) revert FluidDexError(ErrorTypes.DexT1__BorrowAndSwapTooLowOrTooHigh);
937:
938: shares_ = tokenAxa_ * 1e18 / c_; // <= FOUND
939: }
['955']
955: function _getUpdateDebtReserves( // <= FOUND
956: uint shares_,
957: uint totalShares_,
958: DebtReserves memory d_,
959: bool mintOrBurn_
960: ) internal pure returns (
961: DebtReserves memory d2_
962: ) {
963: if (mintOrBurn_) {
964: d2_.token0Debt = d_.token0Debt + d_.token0Debt * shares_ / totalShares_; // <= FOUND
965: d2_.token1Debt = d_.token1Debt + d_.token1Debt * shares_ / totalShares_;
966: d2_.token0RealReserves = d_.token0RealReserves + d_.token0RealReserves * shares_ / totalShares_;
967: d2_.token1RealReserves = d_.token1RealReserves + d_.token1RealReserves * shares_ / totalShares_;
968: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves + d_.token0ImaginaryReserves * shares_ / totalShares_;
969: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves + d_.token1ImaginaryReserves * shares_ / totalShares_;
970: } else {
971: d2_.token0Debt = d_.token0Debt - d_.token0Debt * shares_ / totalShares_;
972: d2_.token1Debt = d_.token1Debt - d_.token1Debt * shares_ / totalShares_;
973: d2_.token0RealReserves = d_.token0RealReserves - d_.token0RealReserves * shares_ / totalShares_;
974: d2_.token1RealReserves = d_.token1RealReserves - d_.token1RealReserves * shares_ / totalShares_;
975: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves - d_.token0ImaginaryReserves * shares_ / totalShares_;
976: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves - d_.token1ImaginaryReserves * shares_ / totalShares_;
977: }
978:
979: return d2_;
980: }
['988']
988: function _getSwapAndPaybackOneTokenPerfectShares( // <= FOUND
989: uint a_,
990: uint b_,
991: uint c_,
992: uint d_,
993: uint i_,
994: uint j_
995: ) internal pure returns (uint tokenAmt_) {
996:
997: uint l_ = a_ - i_;
998:
999: uint m_ = b_ - j_;
1000:
1001: uint w_ = a_ * b_;
1002:
1003: uint z_ = w_ / l_; // <= FOUND
1004:
1005: uint y_ = w_ / m_;
1006:
1007: uint v_ = z_ - m_ - d_;
1008:
1009: uint x_ = (v_ * y_) / (m_ + v_);
1010:
1011:
1012: tokenAmt_ = c_ - x_;
1013:
1014:
1015:
1016:
1017:
1018: if (
1019: (tokenAmt_ > (c_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS)
1020: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
1021: }
['1028']
1028: function _getSwapAndPayback( // <= FOUND
1029: uint c_,
1030: uint d_,
1031: uint e_,
1032: uint f_,
1033: uint g_
1034: ) internal pure returns (
1035: uint shares_
1036: ) {
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059:
1060:
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_; // <= FOUND
1092:
1093:
1094: uint temp2_ = 4 * e_ * g_;
1095:
1096: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
1097:
1098:
1099:
1100:
1101:
1102: if (
1103: (amtToSwap_ > (g_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS) ||
1104: (amtToSwap_ < (g_ / SIX_DECIMALS))
1105: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
1106:
1107:
1108: temp_ = g_ - amtToSwap_;
1109:
1110:
1111: temp2_ = (f_ * amtToSwap_) / (e_ + amtToSwap_);
1112:
1113:
1114: temp_ = temp_ * 1e18 / (c_ - amtToSwap_);
1115:
1116: temp2_ = temp2_ * 1e18 / (d_ + temp2_);
1117:
1118: shares_ = temp_ > temp2_ ? temp2_ : temp_;
1119: }
['145']
145: function _turnOnSmartDebt( // <= FOUND
146: uint token0Amt_,
147: uint centerPrice_
148: ) internal {
149: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
150: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
151:
152: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision; // <= FOUND
153:
154: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
155:
156: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
157:
158: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
159:
160: liquidity_.operate(c_.token0, 0, int(token0Amt_), address(0), TEAM_MULTISIG, new bytes(0));
161: liquidity_.operate(c_.token1, 0, int(token1Amt_), address(0), TEAM_MULTISIG, new bytes(0));
162:
163:
164:
165:
166: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
167:
168: if (_totalBorrowShares < NINE_DECIMALS) {
169: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
170: }
171: }
Perform multiplication operations first
Num of instances: 1
Click to show findings
['214']
214: function _getPricesAndExchangePrices( // <= FOUND
215: uint dexVariables_,
216: uint dexVariables2_
217: ) internal returns (
218: PricesAndExchangePrice memory pex_
219: ) {
220: uint centerPrice_;
221:
222: if (((dexVariables2_ >> 248) & 1) == 0) {
223:
224: centerPrice_ = (dexVariables2_ >> 112) & X30;
225: if (centerPrice_ == 0) {
226: centerPrice_ = (dexVariables_ >> 81) & X40;
227: centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);
228: } else {
229:
230:
231: centerPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, centerPrice_)).centerPrice();
232: }
233: } else {
234:
235: centerPrice_ = _calcCenterPrice(dexVariables_, dexVariables2_);
236: }
237:
238: uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;
239: lastStoredPrice_ = (lastStoredPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastStoredPrice_ & DEFAULT_EXPONENT_MASK);
240:
241: uint upperRange_ = ((dexVariables2_ >> 27) & X20);
242: uint lowerRange_ = ((dexVariables2_ >> 47) & X20);
243: if (((dexVariables2_ >> 26) & 1) == 1) {
244:
245: (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);
246: }
247:
248: upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);
249:
250: lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;
251:
252: bool changed_;
253: {
254:
255:
256: if (((dexVariables2_ >> 68) & X20) > 0) {
257: uint upperThreshold_ = (dexVariables2_ >> 68) & X10;
258: uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;
259: uint shiftingTime_ = (dexVariables2_ >> 88) & X24;
260: if (((dexVariables2_ >> 67) & 1) == 1) {
261:
262: (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(upperThreshold_, lowerThreshold_, shiftingTime_);
263: }
264:
265: if (lastStoredPrice_ > (centerPrice_ + (upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_) / THREE_DECIMALS)) {
266: uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);
267:
268: if (timeElapsed_ < shiftingTime_) {
269: centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_;
270: } else {
271:
272: centerPrice_ = upperRange_;
273: }
274:
275: changed_ = true;
276: } else if (lastStoredPrice_ < (centerPrice_ - (centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_) / THREE_DECIMALS)) {
277: uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);
278:
279: if (timeElapsed_ < shiftingTime_) {
280: centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_;
281: } else {
282:
283: centerPrice_ = lowerRange_;
284: }
285: changed_ = true;
286: }
287: }
288: }
289:
290:
291: uint temp_ = (dexVariables2 >> 172) & X28;
292: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
293: if (centerPrice_ > temp_) {
294:
295: centerPrice_ = temp_;
296: changed_ = true;
297: } else {
298:
299:
300: temp_ = (dexVariables2 >> 200) & X28;
301: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
302: if (centerPrice_ < temp_) {
303: centerPrice_ = temp_;
304: changed_ = true;
305: }
306: }
307:
308:
309: if (changed_) {
310: upperRange_ = ((dexVariables2_ >> 27) & X20);
311: lowerRange_ = ((dexVariables2_ >> 47) & X20);
312: if (((dexVariables2_ >> 26) & 1) == 1) {
313: (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);
314: }
315:
316: upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);
317:
318: lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;
319: }
320:
321: pex_.lastStoredPrice = lastStoredPrice_;
322: pex_.centerPrice = centerPrice_;
323: pex_.upperRange = upperRange_;
324: pex_.lowerRange = lowerRange_;
325:
326: if (upperRange_ < 1e38) {
327:
328: pex_.geometricMean = FixedPointMathLib.sqrt(upperRange_ * lowerRange_);
329: } else {
330:
331: pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18; // <= FOUND
332: }
333:
334:
335:
336: (pex_.supplyToken0ExchangePrice, pex_.borrowToken0ExchangePrice) = LiquidityCalcs.calcExchangePrices(
337: LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_0_SLOT)
338: );
339:
340: (pex_.supplyToken1ExchangePrice, pex_.borrowToken1ExchangePrice) = LiquidityCalcs.calcExchangePrices(
341: LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_1_SLOT)
342: );
343: }
In arithmetic operations involving subtraction and multiplication, an underflow may occur if a subtraction result is negative, or if a multiplication result exceeds the maximum value representable in the data type. For instance, if a large multiplication precedes a subtraction, it may create a value too large to subtract from, causing an underflow. This could lead to unexpected and incorrect results in the calculation.
Num of instances: 12
Click to show findings
['286']
286: function swapOut( // <= FOUND
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100); // <= FOUND
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
['1878']
1878: function oraclePrice( // <= FOUND
1879: uint[] memory secondsAgos_
1880: ) external view returns (
1881: Oracle[] memory twaps_,
1882: uint currentPrice_
1883: ) {
1884: OraclePriceMemory memory o_;
1885:
1886: uint dexVariables_ = dexVariables;
1887: twaps_ = new Oracle[](secondsAgos_.length);
1888:
1889: uint totalTime_;
1890: uint time_;
1891:
1892: uint i;
1893: uint secondsAgo_ = secondsAgos_[0];
1894:
1895: currentPrice_ = (dexVariables_ >> 41) & X40;
1896: currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);
1897: uint price_ = currentPrice_;
1898: o_.lowestPrice1by0 = currentPrice_;
1899: o_.highestPrice1by0 = currentPrice_;
1900:
1901: uint twap1by0_;
1902: uint twap0by1_;
1903:
1904: uint j;
1905:
1906: o_.oracleSlot = (dexVariables_ >> 176) & X3;
1907: o_.oracleMap = (dexVariables_ >> 179) & X16;
1908:
1909: o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;
1910:
1911: uint slotData_;
1912: uint percentDiff_;
1913:
1914: if (((dexVariables_ >> 121) & X33) < block.timestamp) {
1915:
1916:
1917: time_ = block.timestamp - ((dexVariables_ >> 121) & X33);
1918: } else {
1919:
1920: ++j;
1921: }
1922:
1923: while (true) {
1924: if (j == 2) {
1925: if (++o_.oracleSlot == 8) {
1926: o_.oracleSlot = 0;
1927: if (o_.oracleMap == 0) {
1928: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1929: }
1930: o_.oracle = _oracle[--o_.oracleMap];
1931: }
1932:
1933: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1934: if (slotData_ > 0) {
1935: time_ = slotData_ & X9;
1936: if (time_ == 0) {
1937:
1938: time_ = slotData_ >> 9;
1939:
1940: if (o_.oracleSlot == 7) {
1941: o_.oracleSlot = 0;
1942: if (o_.oracleMap == 0) {
1943: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1944: }
1945: o_.oracle = _oracle[--o_.oracleMap];
1946: slotData_ = o_.oracle & X32;
1947: } else {
1948: ++o_.oracleSlot;
1949: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1950: }
1951: }
1952: percentDiff_ = slotData_ >> 10;
1953: percentDiff_ = ORACLE_LIMIT * percentDiff_ / X22;
1954: if (((slotData_ >> 9) & 1 == 1)) {
1955:
1956: price_ = price_ - price_ * percentDiff_ / ORACLE_PRECISION; // <= FOUND
1957: } else {
1958:
1959: price_ = price_ + price_ * percentDiff_ / ORACLE_PRECISION;
1960: }
1961: } else {
1962:
1963: revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);
1964: }
1965: } else if (j == 1) {
1966:
1967: price_ = (dexVariables_ >> 1) & X40;
1968: price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);
1969: time_ = (dexVariables_ >> 154) & X22;
1970: ++j;
1971: } else if (j == 0) {
1972: ++j;
1973: }
1974:
1975: totalTime_ += time_;
1976: if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;
1977: if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;
1978: if (totalTime_ < secondsAgo_) {
1979: twap1by0_ += price_ * time_;
1980: twap0by1_ += (1e54 / price_) * time_;
1981: } else {
1982: time_ = time_ + secondsAgo_ - totalTime_;
1983: twap1by0_ += price_ * time_;
1984: twap0by1_ += (1e54 / price_) * time_;
1985:
1986: twap1by0_ = twap1by0_ / secondsAgo_;
1987: twap0by1_ = twap0by1_ / secondsAgo_;
1988:
1989: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
1990:
1991:
1992: o_.lowestPrice1by0 = price_;
1993: o_.highestPrice1by0 = price_;
1994:
1995: while (++i < secondsAgos_.length) {
1996:
1997: time_ = totalTime_ - secondsAgo_;
1998:
1999: totalTime_ = time_;
2000:
2001: secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];
2002: if (totalTime_ < secondsAgo_) {
2003: twap1by0_ = price_ * time_;
2004: twap0by1_ = (1e54 / price_) * time_;
2005:
2006: if (time_ == 0) {
2007: o_.lowestPrice1by0 = type(uint).max;
2008: o_.highestPrice1by0 = 0;
2009: }
2010: break;
2011: } else {
2012: time_ = time_ + secondsAgo_ - totalTime_;
2013:
2014: twap1by0_ = price_ * time_;
2015:
2016: twap0by1_ = (1e54 / price_) * time_;
2017: twap1by0_ = twap1by0_ / secondsAgo_;
2018: twap0by1_ = twap0by1_ / secondsAgo_;
2019: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
2020: }
2021: }
2022: if (i == secondsAgos_.length) return (twaps_, currentPrice_);
2023: }
2024: }
2025:
2026: }
['62']
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
63: if (current_ > old_) {
64: uint diff_ = current_ - old_;
65: current_ = old_ + (diff_ * timePassed_ / shiftDuration_);
66: } else {
67: uint diff_ = old_ - current_;
68: current_ = old_ - (diff_ * timePassed_ / shiftDuration_); // <= FOUND
69: }
70: return current_;
71: }
['470']
470: function _calculateDebtReserves( // <= FOUND
471: uint gp_,
472: uint pb_,
473: uint dx_,
474: uint dy_
475: ) internal pure returns (
476: uint rx_,
477: uint ry_,
478: uint irx_,
479: uint iry_
480: ) {
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534: int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27); // <= FOUND
535: uint p2_ = (dx_ * dy_);
536: p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;
537: ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));
538:
539:
540:
541:
542:
543:
544:
545:
546:
547: iry_ = ((ry_ * 1e27) - (dx_ * pb_));
548: if (iry_ < SIX_DECIMALS) {
549:
550: revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);
551: }
552: if (ry_ < 1e25) {
553: iry_ = (ry_ * ry_ * 1e27) / iry_;
554: } else {
555:
556: iry_ = (ry_ * ry_) / (iry_ / 1e27);
557: }
558:
559:
560:
561:
562:
563:
564: irx_ = ((iry_ * dx_) / ry_) - dx_;
565:
566:
567:
568:
569: rx_ = (irx_ * dy_) / (iry_ + dy_);
570: }
['644']
644: function _swapRoutingIn( // <= FOUND
645: uint t,
646: uint x,
647: uint y,
648: uint x2,
649: uint y2
650: ) internal pure returns (
651: int a_
652: ) {
653:
654:
655:
656:
657:
658:
659:
660:
661: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
663:
664: a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
665: }
['676']
676: function _swapRoutingOut( // <= FOUND
677: uint t,
678: uint x,
679: uint y,
680: uint x2,
681: uint y2
682: ) internal pure returns (
683: int a_
684: ) {
685:
686:
687:
688:
689:
690:
691:
692:
693: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
694: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
695:
696:
697: a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
698: }
['705']
705: function _getSwapAndDeposit( // <= FOUND
706: uint c_,
707: uint d_,
708: uint e_,
709: uint f_,
710: uint i_
711: ) internal pure returns (
712: uint shares_
713: ) {
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_; // <= FOUND
737: uint temp2_ = 4 * c_ * e_;
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
739:
740:
741:
742:
743:
744: if (
745: (amtToSwap_ > ((c_ * SIX_DECIMALS - 1) / SIX_DECIMALS)) ||
746: (amtToSwap_ < (c_ / SIX_DECIMALS))
747: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndDepositTooLowOrTooHigh);
748:
749:
750: temp_ = c_ - amtToSwap_;
751:
752:
753: temp2_ = (d_ * amtToSwap_) / (e_ + amtToSwap_);
754:
755:
756: temp_ = temp_ * 1e18 / (f_ + amtToSwap_);
757:
758: temp2_ = temp2_ * 1e18 / (i_ - temp2_);
759:
760: shares_ = temp_ > temp2_ ? temp2_ : temp_;
761: }
['769']
769: function _getUpdatedColReserves( // <= FOUND
770: uint newShares_,
771: uint totalOldShares_,
772: CollateralReserves memory c_,
773: bool mintOrBurn_
774: ) internal pure returns (
775: CollateralReserves memory c2_
776: ) {
777: if (mintOrBurn_) {
778:
779: c2_.token0RealReserves = c_.token0RealReserves + c_.token0RealReserves * newShares_ / totalOldShares_;
780: c2_.token1RealReserves = c_.token1RealReserves + c_.token1RealReserves * newShares_ / totalOldShares_;
781: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves + c_.token0ImaginaryReserves * newShares_ / totalOldShares_;
782: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves + c_.token1ImaginaryReserves * newShares_ / totalOldShares_;
783: } else {
784:
785: c2_.token0RealReserves = c_.token0RealReserves - (c_.token0RealReserves * newShares_ / totalOldShares_); // <= FOUND
786: c2_.token1RealReserves = c_.token1RealReserves - (c_.token1RealReserves * newShares_ / totalOldShares_);
787: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves - (c_.token0ImaginaryReserves * newShares_ / totalOldShares_);
788: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves - (c_.token1ImaginaryReserves * newShares_ / totalOldShares_);
789: }
790: return c2_;
791: }
['955']
955: function _getUpdateDebtReserves( // <= FOUND
956: uint shares_,
957: uint totalShares_,
958: DebtReserves memory d_,
959: bool mintOrBurn_
960: ) internal pure returns (
961: DebtReserves memory d2_
962: ) {
963: if (mintOrBurn_) {
964: d2_.token0Debt = d_.token0Debt + d_.token0Debt * shares_ / totalShares_;
965: d2_.token1Debt = d_.token1Debt + d_.token1Debt * shares_ / totalShares_;
966: d2_.token0RealReserves = d_.token0RealReserves + d_.token0RealReserves * shares_ / totalShares_;
967: d2_.token1RealReserves = d_.token1RealReserves + d_.token1RealReserves * shares_ / totalShares_;
968: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves + d_.token0ImaginaryReserves * shares_ / totalShares_;
969: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves + d_.token1ImaginaryReserves * shares_ / totalShares_;
970: } else {
971: d2_.token0Debt = d_.token0Debt - d_.token0Debt * shares_ / totalShares_; // <= FOUND
972: d2_.token1Debt = d_.token1Debt - d_.token1Debt * shares_ / totalShares_;
973: d2_.token0RealReserves = d_.token0RealReserves - d_.token0RealReserves * shares_ / totalShares_;
974: d2_.token1RealReserves = d_.token1RealReserves - d_.token1RealReserves * shares_ / totalShares_;
975: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves - d_.token0ImaginaryReserves * shares_ / totalShares_;
976: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves - d_.token1ImaginaryReserves * shares_ / totalShares_;
977: }
978:
979: return d2_;
980: }
['1028']
1028: function _getSwapAndPayback( // <= FOUND
1029: uint c_,
1030: uint d_,
1031: uint e_,
1032: uint f_,
1033: uint g_
1034: ) internal pure returns (
1035: uint shares_
1036: ) {
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059:
1060:
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_; // <= FOUND
1092:
1093:
1094: uint temp2_ = 4 * e_ * g_;
1095:
1096: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
1097:
1098:
1099:
1100:
1101:
1102: if (
1103: (amtToSwap_ > (g_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS) ||
1104: (amtToSwap_ < (g_ / SIX_DECIMALS))
1105: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
1106:
1107:
1108: temp_ = g_ - amtToSwap_;
1109:
1110:
1111: temp2_ = (f_ * amtToSwap_) / (e_ + amtToSwap_);
1112:
1113:
1114: temp_ = temp_ * 1e18 / (c_ - amtToSwap_);
1115:
1116: temp2_ = temp2_ * 1e18 / (d_ + temp2_);
1117:
1118: shares_ = temp_ > temp2_ ? temp2_ : temp_;
1119: }
['1145']
1145: function _updateOracle( // <= FOUND
1146: uint newPrice_,
1147: uint centerPrice_,
1148: uint dexVariables_
1149: ) internal returns (uint) {
1150:
1151: uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);
1152:
1153: uint temp_;
1154: uint temp2_;
1155: uint temp3_;
1156:
1157: if (timeDiff_ > 0) {
1158:
1159:
1160:
1161: temp_ = (dexVariables_ >> 1) & X40;
1162: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1163:
1164:
1165: temp2_ = (dexVariables_ >> 41) & X40;
1166: temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);
1167:
1168:
1169:
1170: int priceDiff_ = int(ORACLE_PRECISION) - int((temp2_ * ORACLE_PRECISION) / newPrice_); // <= FOUND
1171:
1172: if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {
1173:
1174:
1175:
1176:
1177: revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);
1178: }
1179:
1180:
1181: priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);
1182:
1183:
1184:
1185: if (priceDiff_ < 0) {
1186: temp3_ = (uint(-priceDiff_) * X22 / ORACLE_LIMIT) << 1;
1187: } else {
1188:
1189: temp3_ = ((uint(priceDiff_) * X22 / ORACLE_LIMIT) << 1) | 1;
1190: }
1191:
1192: if (timeDiff_ > X22) {
1193:
1194:
1195: timeDiff_ = X22;
1196: }
1197:
1198:
1199: temp_ = (dexVariables_ >> 154) & X22;
1200: uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);
1201: uint oracleMap_ = (dexVariables_ >> 179) & X16;
1202: if (temp_ > X9) {
1203: if (nextOracleSlot_ > 0) {
1204:
1205:
1206: temp3_ = (temp3_ << 41) | (temp_ << 9);
1207: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));
1208: if (nextOracleSlot_ > 0) {
1209: --nextOracleSlot_;
1210: } else {
1211:
1212: nextOracleSlot_ = 7;
1213: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1214: _oracle[oracleMap_] = 0;
1215: }
1216: } else {
1217:
1218:
1219:
1220:
1221: temp3_ = temp3_ << 9;
1222: _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;
1223: nextOracleSlot_ = 6;
1224: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1225:
1226: _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);
1227: }
1228: } else {
1229: temp3_ = (temp3_ << 9) | temp_;
1230: if (nextOracleSlot_ < 7) {
1231: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));
1232: } else {
1233: _oracle[oracleMap_] = temp3_ << ((7 * 32));
1234: }
1235: if (nextOracleSlot_ > 0) {
1236: --nextOracleSlot_;
1237: } else {
1238: nextOracleSlot_ = 7;
1239: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1240: }
1241: }
1242:
1243:
1244: temp_ = newPrice_;
1245: temp2_ = centerPrice_;
1246: temp3_ = dexVariables_;
1247:
1248:
1249: temp3_ = (temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |
1250: (((temp3_ >> 41) & X40) << 1) |
1251: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |
1252: (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |
1253: (block.timestamp << 121) |
1254: (timeDiff_ << 154) |
1255: (nextOracleSlot_ << 176) |
1256: (oracleMap_ << 179);
1257: } else {
1258:
1259: temp_ = (dexVariables_ >> 81) & X40;
1260: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1261:
1262:
1263: if (
1264: (centerPrice_ < ((EIGHT_DECIMALS - 1) * temp_ / EIGHT_DECIMALS)) ||
1265: (centerPrice_ > ((EIGHT_DECIMALS + 1) * temp_ / EIGHT_DECIMALS))
1266: ) {
1267: revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);
1268: }
1269:
1270:
1271: temp_ = (dexVariables_ >> 1) & X40;
1272: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1273:
1274:
1275:
1276: int priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / newPrice_);
1277:
1278: if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {
1279:
1280:
1281:
1282:
1283: revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);
1284: }
1285:
1286:
1287: temp_ = newPrice_;
1288: temp3_ = dexVariables_;
1289:
1290: temp3_ = (temp3_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |
1291: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41);
1292: }
1293:
1294: return temp3_;
1295: }
['431']
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall { // <= FOUND
432: _checkIsContract(user_);
433:
434:
435: uint256 userSupplyData_ = _userSupplyData[user_];
436: if (userSupplyData_ == 0) {
437: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
438: }
439:
440:
441: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
442: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
443:
444:
445: uint256 maxExpansionLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;
446: maxExpansionLimit_ = userSupply_ - ((userSupply_ * maxExpansionLimit_) / FOUR_DECIMALS); // <= FOUND
447:
448: if (newLimit_ == 0 || newLimit_ < maxExpansionLimit_) {
449:
450:
451:
452:
453:
454: newLimit_ = maxExpansionLimit_;
455: } else if (newLimit_ == type(uint256).max || newLimit_ > userSupply_) {
456:
457: newLimit_ = userSupply_;
458: }
459:
460:
461:
462:
463: uint256 baseLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;
464: baseLimit_ = (baseLimit_ >> DEFAULT_EXPONENT_SIZE) << (baseLimit_ & DEFAULT_EXPONENT_MASK);
465: if (userSupply_ < baseLimit_) {
466: newLimit_ = 0;
467:
468:
469:
470: }
471:
472:
473: _userSupplyData[user_] =
474:
475: (userSupplyData_ & 0xFFFFFFFFFFFFFFFFFFFFFFFC000000000000000000000001FFFFFFFFFFFFFFFF) |
476: (newLimit_.toBigNumber(DEFAULT_COEFFICIENT_SIZE, DEFAULT_EXPONENT_SIZE, BigMathMinified.ROUND_DOWN) <<
477: DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) |
478: (block.timestamp << DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP);
479:
480: emit LogUpdateUserWithdrawalLimit(user_, newLimit_);
481: }
Comparing a value using >= MAX_VALUE
is conceptually incorrect when MAX_VALUE
is defined as the upper limit that a variable can take. According to the definition of a maximum value, the condition should only revert if the variable is greater than MAX_VALUE
, not equal to it. Using >=
can introduce unintended behavior, as the condition will trigger a revert even when the variable reaches its legitimate upper bound. This can lead to bugs and vulnerabilities, as well as hamper the contract's intended functionality. The resolution is to strictly use >
when making comparisons against a defined MAX_VALUE
to align with its conceptual definition and to prevent unintended reverts or vulnerabilities.
Num of instances: 2
Click to show findings
['336']
336: if ( // <= FOUND
337: (maxCenterPrice_ <= minCenterPrice_) ||
338: (centerPrice_ <= minCenterPrice_) ||
339: (centerPrice_ >= maxCenterPrice_) || // <= FOUND
340: (minCenterPrice_ == 0)
341: ) {
['336']
336: if (
337: (maxCenterPrice_ <= minCenterPrice_) ||
338: (centerPrice_ <= minCenterPrice_) ||
339: (centerPrice_ >= maxCenterPrice_) || // <= FOUND
340: (minCenterPrice_ == 0)
341: ) {
342: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
343: }
When working with a defined MIN_VALUE
as the lower limit that a variable can take, using <= MIN_VALUE
for comparisons is conceptually incorrect. According to the definition of a minimum value, the condition should only revert if the variable is less than MIN_VALUE
, not equal to it. Using <=
can introduce unintended behavior, as it will trigger a revert even when the variable reaches its legitimate lower bound. This can lead to bugs and vulnerabilities, as well as impede the contract's intended functionality. The resolution is to strictly use <
when making comparisons against a defined MIN_VALUE
to align with its conceptual definition and to prevent unintended reverts or vulnerabilities.
Num of instances: 1
Click to show findings
['336']
336: if (
337: (maxCenterPrice_ <= minCenterPrice_) || // <= FOUND
338: (centerPrice_ <= minCenterPrice_) || // <= FOUND
339: (centerPrice_ >= maxCenterPrice_) ||
340: (minCenterPrice_ == 0)
341: ) {
Num of instances: 1
Click to show findings
['2046']
2046: function _fallback() private { // <= FOUND
2047: if (!(DEX_FACTORY.isGlobalAuth(msg.sender) || DEX_FACTORY.isDexAuth(address(this), msg.sender))) {
2048: revert FluidDexError(ErrorTypes.DexT1__NotAnAuth);
2049: }
2050:
2051: uint dexVariables_ = dexVariables;
2052: if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);
2053:
2054: dexVariables = dexVariables_ | 1;
2055:
2056:
2057: _spell(ADMIN_IMPLEMENTATION, msg.data); // <= FOUND
2058:
2059:
2060:
2061: dexVariables = dexVariables & ~uint(1);
2062: }
The decimals()
function in an ERC20 token contract is used to specify how many decimal places the token can be divided into. However, it should be used with caution because not all ERC20 token contracts implement decimals()
, and the function isn't required by the ERC20 standard. Calling decimals()
on a contract that doesn't implement it will result in a runtime error. Moreover, even when implemented, the returned value can be manipulated or artificially set, which may cause unexpected behavior. Therefore, always verify the decimal count independently if precision is crucial for your contract logic. When interacting with other ERC20 tokens, consider implementing safeguards or checks to handle potential errors from calling decimals()
.
Num of instances: 1
Click to show findings
['79']
79: return (token_ == NATIVE_TOKEN) ? NATIVE_TOKEN_DECIMALS : ITokenDecimals(token_).decimals(); // <= FOUND
Dividing by large numbers in Solidity can cause a loss of precision due to the language's inherent integer division behavior. Solidity does not support floating-point arithmetic, and as a result, division between integers yields an integer result, truncating any fractional part. When dividing by a large number, the resulting value may become significantly smaller, leading to a loss of precision, as the fractional part is discarded.
Num of instances: 24
Click to show findings
['26']
26: function _verifyToken0Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
27: if (((token0Reserves_) < (token1Reserves_ * 1e27 / (centerPrice_ * minLiquidity_)))) { // <= FOUND
28: revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);
29: }
30: }
['33']
33: function _verifyToken1Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
34: if (((token1Reserves_) < (token0Reserves_ * centerPrice_ / (1e27 * minLiquidity_)))) { // <= FOUND
35: revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);
36: }
37: }
['50']
50: function _verifyMint(uint amt_, uint totalAmt_) internal pure { // <= FOUND
51:
52:
53:
54: if (amt_ < (totalAmt_ / NINE_DECIMALS) || amt_ > (totalAmt_ * NINE_DECIMALS)) { // <= FOUND
55: revert FluidDexError(ErrorTypes.DexT1__MintAmtOverflow);
56: }
57: }
['59']
59: function _verifyRedeem(uint amt_, uint totalAmt_) internal pure { // <= FOUND
60:
61: if (amt_ > (totalAmt_ * 9999 / FOUR_DECIMALS)) { // <= FOUND
62: revert FluidDexError(ErrorTypes.DexT1__BurnAmtOverflow);
63: }
64: }
['26']
26: function _getAmountOut( // <= FOUND
27: uint256 amountIn_,
28: uint iReserveIn_,
29: uint iReserveOut_
30: ) internal pure returns (uint256 amountOut_) {
31:
32: uint256 numerator_ = amountIn_ * iReserveOut_;
33: uint256 denominator_ = iReserveIn_ + amountIn_;
34:
35:
36: amountOut_ = numerator_ / denominator_; // <= FOUND
37: }
['43']
43: function _getAmountIn( // <= FOUND
44: uint256 amountOut_,
45: uint iReserveIn_,
46: uint iReserveOut_
47: ) internal pure returns (uint256 amountIn_) {
48:
49: uint256 numerator_ = amountOut_ * iReserveIn_;
50: uint256 denominator_ = iReserveOut_ - amountOut_;
51:
52:
53: amountIn_ = numerator_ / denominator_; // <= FOUND
54: }
['62']
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
63: if (current_ > old_) {
64: uint diff_ = current_ - old_;
65: current_ = old_ + (diff_ * timePassed_ / shiftDuration_); // <= FOUND
66: } else {
67: uint diff_ = old_ - current_;
68: current_ = old_ - (diff_ * timePassed_ / shiftDuration_);
69: }
70: return current_;
71: }
['147']
147: function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) { // <= FOUND
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40;
149: oldCenterPrice_ = (oldCenterPrice_ >> DEFAULT_EXPONENT_SIZE) << (oldCenterPrice_ & DEFAULT_EXPONENT_MASK);
150: uint centerPriceShift_ = _centerPriceShift;
151: uint startTimeStamp_ = centerPriceShift_ & X33;
152: uint percent_ = (centerPriceShift_ >> 33) & X20;
153: uint time_ = (centerPriceShift_ >> 53) & X20;
154:
155: uint fromTimeStamp_ = (dexVariables_ >> 121) & X33;
156: fromTimeStamp_ = fromTimeStamp_ > startTimeStamp_ ? fromTimeStamp_ : startTimeStamp_;
157:
158: newCenterPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, ((dexVariables2_ >> 112) & X30))).centerPrice();
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS); // <= FOUND
160:
161: if (newCenterPrice_ > oldCenterPrice_) {
162:
163: oldCenterPrice_ += priceShift_;
164: if (newCenterPrice_ > oldCenterPrice_) {
165: newCenterPrice_ = oldCenterPrice_;
166: } else {
167:
168: delete _centerPriceShift;
169:
170:
171: dexVariables2 = dexVariables2 & ~uint(1 << 248);
172: }
173: } else {
174: unchecked {
175: oldCenterPrice_ = oldCenterPrice_ > priceShift_ ? oldCenterPrice_ - priceShift_ : 0;
176:
177:
178:
179:
180: }
181: if (newCenterPrice_ < oldCenterPrice_) {
182: newCenterPrice_ = oldCenterPrice_;
183: } else {
184:
185: delete _centerPriceShift;
186:
187:
188: dexVariables2 = dexVariables2 & ~uint(1 << 248);
189: }
190: }
191: }
['350']
350: function _calculateReservesOutsideRange( // <= FOUND
351: uint gp_,
352: uint pa_,
353: uint rx_,
354: uint ry_
355: ) internal pure returns (
356: uint xa_,
357: uint yb_
358: ) {
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383: uint p1_ = pa_ - gp_;
384: uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);
385: uint p3_ = rx_ * ry_;
386:
387: p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27; // <= FOUND
388:
389:
390:
391: xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));
392: yb_ = (xa_ * gp_) / 1e27;
393: }
['400']
400: function _getLiquidityCollateral( // <= FOUND
401: bytes32 supplyTokenSlot_,
402: uint tokenExchangePrice_,
403: bool isToken0_
404: ) internal view returns (uint tokenSupply_) {
405: uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);
406: tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
407: tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);
408:
409: if (tokenSupplyData_ & 1 == 1) {
410:
411: tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION; // <= FOUND
412: }
413:
414: tokenSupply_ = isToken0_ ?
415: ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) :
416: ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);
417: }
['433']
433: function getCollateralReserves( // <= FOUND
434: uint geometricMean_,
435: uint upperRange_,
436: uint lowerRange_,
437: uint token0SupplyExchangePrice_,
438: uint token1SupplyExchangePrice_
439: ) public view returns (CollateralReserves memory c_) {
440: uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);
441: uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);
442:
443: if (geometricMean_ < 1e27) {
444: (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(geometricMean_, upperRange_, token0Supply_, token1Supply_);
445: } else {
446:
447:
448:
449:
450: (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange((1e54 / geometricMean_), (1e54 / lowerRange_), token1Supply_, token0Supply_); // <= FOUND
451: }
452:
453: c_.token0RealReserves = token0Supply_;
454: c_.token1RealReserves = token1Supply_;
455: c_.token0ImaginaryReserves += token0Supply_;
456: c_.token1ImaginaryReserves += token1Supply_;
457: }
['470']
470: function _calculateDebtReserves( // <= FOUND
471: uint gp_,
472: uint pb_,
473: uint dx_,
474: uint dy_
475: ) internal pure returns (
476: uint rx_,
477: uint ry_,
478: uint irx_,
479: uint iry_
480: ) {
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534: int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);
535: uint p2_ = (dx_ * dy_);
536: p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;
537: ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));
538:
539:
540:
541:
542:
543:
544:
545:
546:
547: iry_ = ((ry_ * 1e27) - (dx_ * pb_));
548: if (iry_ < SIX_DECIMALS) {
549:
550: revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);
551: }
552: if (ry_ < 1e25) {
553: iry_ = (ry_ * ry_ * 1e27) / iry_; // <= FOUND
554: } else {
555:
556: iry_ = (ry_ * ry_) / (iry_ / 1e27);
557: }
558:
559:
560:
561:
562:
563:
564: irx_ = ((iry_ * dx_) / ry_) - dx_;
565:
566:
567:
568:
569: rx_ = (irx_ * dy_) / (iry_ + dy_);
570: }
['577']
577: function _getLiquidityDebt( // <= FOUND
578: bytes32 borrowTokenSlot_,
579: uint tokenExchangePrice_,
580: bool isToken0_
581: ) internal view returns (uint tokenDebt_) {
582: uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);
583:
584: tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
585: tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);
586:
587: if (tokenBorrowData_ & 1 == 1) {
588:
589: tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION; // <= FOUND
590: }
591:
592: tokenDebt_ = isToken0_ ?
593: ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) :
594: ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);
595: }
['610']
610: function getDebtReserves( // <= FOUND
611: uint geometricMean_,
612: uint upperRange_,
613: uint lowerRange_,
614: uint token0BorrowExchangePrice_,
615: uint token1BorrowExchangePrice_
616: ) public view returns (DebtReserves memory d_) {
617: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);
618: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);
619:
620: d_.token0Debt = token0Debt_;
621: d_.token1Debt = token1Debt_;
622:
623: if (geometricMean_ < 1e27) {
624: (d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);
625: } else {
626:
627:
628:
629:
630: (d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_); // <= FOUND
631: }
632:
633: }
['644']
644: function _swapRoutingIn( // <= FOUND
645: uint t,
646: uint x,
647: uint y,
648: uint x2,
649: uint y2
650: ) internal pure returns (
651: int a_
652: ) {
653:
654:
655:
656:
657:
658:
659:
660:
661: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
663:
664: a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
665: }
['676']
676: function _swapRoutingOut( // <= FOUND
677: uint t,
678: uint x,
679: uint y,
680: uint x2,
681: uint y2
682: ) internal pure returns (
683: int a_
684: ) {
685:
686:
687:
688:
689:
690:
691:
692:
693: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);
694: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);
695:
696:
697: a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
698: }
['705']
705: function _getSwapAndDeposit( // <= FOUND
706: uint c_,
707: uint d_,
708: uint e_,
709: uint f_,
710: uint i_
711: ) internal pure returns (
712: uint shares_
713: ) {
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_;
737: uint temp2_ = 4 * c_ * e_;
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
739:
740:
741:
742:
743:
744: if ( // <= FOUND
745: (amtToSwap_ > ((c_ * SIX_DECIMALS - 1) / SIX_DECIMALS)) ||
746: (amtToSwap_ < (c_ / SIX_DECIMALS))
747: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndDepositTooLowOrTooHigh);
748:
749:
750: temp_ = c_ - amtToSwap_;
751:
752:
753: temp2_ = (d_ * amtToSwap_) / (e_ + amtToSwap_);
754:
755:
756: temp_ = temp_ * 1e18 / (f_ + amtToSwap_);
757:
758: temp2_ = temp2_ * 1e18 / (i_ - temp2_);
759:
760: shares_ = temp_ > temp2_ ? temp2_ : temp_;
761: }
['769']
769: function _getUpdatedColReserves( // <= FOUND
770: uint newShares_,
771: uint totalOldShares_,
772: CollateralReserves memory c_,
773: bool mintOrBurn_
774: ) internal pure returns (
775: CollateralReserves memory c2_
776: ) {
777: if (mintOrBurn_) {
778:
779: c2_.token0RealReserves = c_.token0RealReserves + c_.token0RealReserves * newShares_ / totalOldShares_; // <= FOUND
780: c2_.token1RealReserves = c_.token1RealReserves + c_.token1RealReserves * newShares_ / totalOldShares_;
781: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves + c_.token0ImaginaryReserves * newShares_ / totalOldShares_;
782: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves + c_.token1ImaginaryReserves * newShares_ / totalOldShares_;
783: } else {
784:
785: c2_.token0RealReserves = c_.token0RealReserves - (c_.token0RealReserves * newShares_ / totalOldShares_);
786: c2_.token1RealReserves = c_.token1RealReserves - (c_.token1RealReserves * newShares_ / totalOldShares_);
787: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves - (c_.token0ImaginaryReserves * newShares_ / totalOldShares_);
788: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves - (c_.token1ImaginaryReserves * newShares_ / totalOldShares_);
789: }
790: return c2_;
791: }
['798']
798: function _getWithdrawAndSwap( // <= FOUND
799: uint c_,
800: uint d_,
801: uint e_,
802: uint f_,
803: uint g_
804: ) internal pure returns (
805: uint shares_
806: ) {
807:
808:
809:
810:
811:
812:
813:
814:
815:
816:
817:
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
830:
831:
832:
833:
834:
835:
836:
837:
838:
839:
840:
841:
842:
843:
844:
845:
846:
847: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_);
848:
849:
850: uint temp2_ = (((c_ * f_) / d_) + c_) * g_;
851:
852:
853: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_);
854:
855:
856:
857:
858:
859: if ( // <= FOUND
860: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
861: tokenAxa_ < (g_ / SIX_DECIMALS)
862: ) revert FluidDexError(ErrorTypes.DexT1__WithdrawAndSwapTooLowOrTooHigh);
863:
864: shares_ = tokenAxa_ * 1e18 / c_;
865: }
['872']
872: function _getBorrowAndSwap( // <= FOUND
873: uint c_,
874: uint d_,
875: uint e_,
876: uint f_,
877: uint g_
878: ) internal pure returns (
879: uint shares_
880: ) {
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915:
916:
917:
918:
919:
920: uint temp_ = (c_ * f_ + d_ * e_ + d_ * g_) / (2 * d_);
921:
922:
923:
924: uint temp2_ = (c_ * f_ * g_) / d_;
925:
926:
927: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_);
928:
929:
930:
931:
932:
933: if ( // <= FOUND
934: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
935: tokenAxa_ < (g_ / SIX_DECIMALS)
936: ) revert FluidDexError(ErrorTypes.DexT1__BorrowAndSwapTooLowOrTooHigh);
937:
938: shares_ = tokenAxa_ * 1e18 / c_;
939: }
['955']
955: function _getUpdateDebtReserves( // <= FOUND
956: uint shares_,
957: uint totalShares_,
958: DebtReserves memory d_,
959: bool mintOrBurn_
960: ) internal pure returns (
961: DebtReserves memory d2_
962: ) {
963: if (mintOrBurn_) {
964: d2_.token0Debt = d_.token0Debt + d_.token0Debt * shares_ / totalShares_; // <= FOUND
965: d2_.token1Debt = d_.token1Debt + d_.token1Debt * shares_ / totalShares_;
966: d2_.token0RealReserves = d_.token0RealReserves + d_.token0RealReserves * shares_ / totalShares_;
967: d2_.token1RealReserves = d_.token1RealReserves + d_.token1RealReserves * shares_ / totalShares_;
968: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves + d_.token0ImaginaryReserves * shares_ / totalShares_;
969: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves + d_.token1ImaginaryReserves * shares_ / totalShares_;
970: } else {
971: d2_.token0Debt = d_.token0Debt - d_.token0Debt * shares_ / totalShares_;
972: d2_.token1Debt = d_.token1Debt - d_.token1Debt * shares_ / totalShares_;
973: d2_.token0RealReserves = d_.token0RealReserves - d_.token0RealReserves * shares_ / totalShares_;
974: d2_.token1RealReserves = d_.token1RealReserves - d_.token1RealReserves * shares_ / totalShares_;
975: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves - d_.token0ImaginaryReserves * shares_ / totalShares_;
976: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves - d_.token1ImaginaryReserves * shares_ / totalShares_;
977: }
978:
979: return d2_;
980: }
['988']
988: function _getSwapAndPaybackOneTokenPerfectShares( // <= FOUND
989: uint a_,
990: uint b_,
991: uint c_,
992: uint d_,
993: uint i_,
994: uint j_
995: ) internal pure returns (uint tokenAmt_) {
996:
997: uint l_ = a_ - i_;
998:
999: uint m_ = b_ - j_;
1000:
1001: uint w_ = a_ * b_;
1002:
1003: uint z_ = w_ / l_;
1004:
1005: uint y_ = w_ / m_;
1006:
1007: uint v_ = z_ - m_ - d_;
1008:
1009: uint x_ = (v_ * y_) / (m_ + v_);
1010:
1011:
1012: tokenAmt_ = c_ - x_;
1013:
1014:
1015:
1016:
1017:
1018: if ( // <= FOUND
1019: (tokenAmt_ > (c_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS)
1020: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
1021: }
['1028']
1028: function _getSwapAndPayback( // <= FOUND
1029: uint c_,
1030: uint d_,
1031: uint e_,
1032: uint f_,
1033: uint g_
1034: ) internal pure returns (
1035: uint shares_
1036: ) {
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059:
1060:
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_;
1092:
1093:
1094: uint temp2_ = 4 * e_ * g_;
1095:
1096: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
1097:
1098:
1099:
1100:
1101:
1102: if ( // <= FOUND
1103: (amtToSwap_ > (g_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS) ||
1104: (amtToSwap_ < (g_ / SIX_DECIMALS))
1105: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
1106:
1107:
1108: temp_ = g_ - amtToSwap_;
1109:
1110:
1111: temp2_ = (f_ * amtToSwap_) / (e_ + amtToSwap_);
1112:
1113:
1114: temp_ = temp_ * 1e18 / (c_ - amtToSwap_);
1115:
1116: temp2_ = temp2_ * 1e18 / (d_ + temp2_);
1117:
1118: shares_ = temp_ > temp2_ ? temp2_ : temp_;
1119: }
['145']
145: function _turnOnSmartDebt( // <= FOUND
146: uint token0Amt_,
147: uint centerPrice_
148: ) internal {
149: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
150: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
151:
152: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision; // <= FOUND
153:
154: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
155:
156: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
157:
158: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
159:
160: liquidity_.operate(c_.token0, 0, int(token0Amt_), address(0), TEAM_MULTISIG, new bytes(0));
161: liquidity_.operate(c_.token1, 0, int(token1Amt_), address(0), TEAM_MULTISIG, new bytes(0));
162:
163:
164:
165:
166: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
167:
168: if (_totalBorrowShares < NINE_DECIMALS) {
169: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
170: }
171: }
Taking 0 as a valid argument in Solidity without checks can lead to severe security issues. A historical example is the infamous 0x0 address bug where numerous tokens were lost. This happens because '0' can be interpreted as an uninitialized address, leading to transfers to the '0x0' address, effectively burning tokens. Moreover, 0 as a denominator in division operations would cause a runtime exception. It's also often indicative of a logical error in the caller's code. It's important to always validate input and handle edge cases like 0 appropriately. Use require()
statements to enforce conditions and provide clear error messages to facilitate debugging and safer code.
Num of instances: 15
Click to show findings
['286']
286: function swapOut( // <= FOUND
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0); // <= FOUND
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
['511']
511: function depositPerfect( // <= FOUND
512: uint shares_,
513: uint maxToken0Deposit_,
514: uint maxToken1Deposit_,
515: bool estimate_
516: ) public payable returns (uint token0Amt_, uint token1Amt_) {
517: uint dexVariables_ = dexVariables;
518: uint dexVariables2_ = dexVariables2;
519:
520: _check(dexVariables_, dexVariables2_);
521:
522: uint userSupplyData_ = _userSupplyData[msg.sender];
523:
524:
525: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
526:
527:
528: if ((dexVariables2_ & 1) == 1) {
529: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
530:
531:
532: uint totalSupplyShares_ = _totalSupplyShares;
533:
534: _verifyMint(shares_, totalSupplyShares_);
535:
536:
537:
538: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
539: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
540:
541:
542:
543: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
544: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
545:
546: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
547:
548: if (token0Amt_ > maxToken0Deposit_ || token1Amt_ > maxToken1Deposit_) {
549: revert FluidDexError(ErrorTypes.DexT1__AboveDepositMax);
550: }
551:
552: _depositOrPaybackInLiquidity(TOKEN_0, token0Amt_, 0); // <= FOUND
553:
554: _depositOrPaybackInLiquidity(TOKEN_1, token1Amt_, 0);
555:
556: uint userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
557:
558: userSupply_ = ((userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK));
559:
560:
561: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
562:
563: userSupply_ += shares_;
564:
565:
566: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
567:
568:
569: _totalSupplyShares = totalSupplyShares_ + shares_;
570: } else {
571: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
572: }
573:
574:
575: dexVariables = dexVariables_;
576:
577: emit LogDepositPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
578: }
['587']
587: function withdrawPerfect( // <= FOUND
588: uint shares_,
589: uint minToken0Withdraw_,
590: uint minToken1Withdraw_,
591: bool estimate_
592: ) public returns (uint token0Amt_, uint token1Amt_) {
593: uint dexVariables_ = dexVariables;
594: uint dexVariables2_ = dexVariables2;
595:
596: _check(dexVariables_, dexVariables2_);
597:
598: uint userSupplyData_ = _userSupplyData[msg.sender];
599:
600: if (userSupplyData_ & 1 == 0 && !estimate_) {
601: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
602: }
603:
604:
605: if ((dexVariables2_ & 1) == 1) {
606: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
607:
608: uint totalSupplyShares_ = _totalSupplyShares;
609:
610: _verifyRedeem(shares_, totalSupplyShares_);
611:
612:
613:
614: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
615: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
616:
617:
618: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
619: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
620:
621: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
622:
623: if (token0Amt_ < minToken0Withdraw_ || token1Amt_ < minToken1Withdraw_) {
624: revert FluidDexError(ErrorTypes.DexT1__BelowWithdrawMin);
625: }
626:
627: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
628: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
629:
630:
631: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
632: userSupply_ -= shares_;
633:
634:
635: if (userSupply_ < newWithdrawalLimit_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
636:
637: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
638:
639: _totalSupplyShares = totalSupplyShares_ - shares_;
640:
641:
642:
643: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
644:
645:
646:
647: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
648: } else {
649: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
650: }
651:
652:
653: dexVariables = dexVariables_;
654:
655: emit LogWithdrawPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
656: }
['665']
665: function borrowPerfect( // <= FOUND
666: uint shares_,
667: uint minToken0Borrow_,
668: uint minToken1Borrow_,
669: bool estimate_
670: ) public returns (uint token0Amt_, uint token1Amt_) {
671: uint dexVariables_ = dexVariables;
672: uint dexVariables2_ = dexVariables2;
673:
674: _check(dexVariables_, dexVariables2_);
675:
676: uint userBorrowData_ = _userBorrowData[msg.sender];
677:
678:
679: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
680:
681:
682: if (((dexVariables2_ >> 1) & 1) == 1) {
683: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
684:
685: uint totalBorrowShares_ = _totalBorrowShares;
686:
687: _verifyMint(shares_, totalBorrowShares_);
688:
689:
690: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
691: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
692:
693: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
694: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
695:
696: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
697:
698: if (token0Amt_ < minToken0Borrow_ || token1Amt_ < minToken1Borrow_) {
699: revert FluidDexError(ErrorTypes.DexT1__BelowBorrowMin);
700: }
701:
702:
703: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
704: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
705:
706:
707: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
708:
709: userBorrow_ += shares_;
710:
711:
712: if (userBorrow_ > newBorrowLimit_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached);
713:
714:
715:
716: LIQUIDITY.operate(TOKEN_0, 0, int(token0Amt_), address(0), msg.sender, new bytes(0)); // <= FOUND
717:
718:
719:
720: LIQUIDITY.operate(TOKEN_1, 0, int(token1Amt_), address(0), msg.sender, new bytes(0));
721:
722: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
723:
724: _totalBorrowShares = totalBorrowShares_ + shares_;
725: } else {
726: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
727: }
728:
729:
730: dexVariables = dexVariables_;
731:
732: emit LogBorrowPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
733: }
['742']
742: function paybackPerfect( // <= FOUND
743: uint shares_,
744: uint maxToken0Payback_,
745: uint maxToken1Payback_,
746: bool estimate_
747: ) public payable returns (uint token0Amt_, uint token1Amt_) {
748: uint dexVariables_ = dexVariables;
749: uint dexVariables2_ = dexVariables2;
750:
751: _check(dexVariables_, dexVariables2_);
752:
753: uint userBorrowData_ = _userBorrowData[msg.sender];
754:
755: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
756:
757:
758: if (((dexVariables2_ >> 1) & 1) == 1) {
759: uint totalBorrowShares_ = _totalBorrowShares;
760:
761: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
762:
763: _verifyRedeem(shares_, totalBorrowShares_);
764:
765:
766: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
767: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
768:
769: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
770: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
771:
772: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
773:
774: if (token0Amt_ > maxToken0Payback_ || token1Amt_ > maxToken1Payback_) {
775: revert FluidDexError(ErrorTypes.DexT1__AbovePaybackMax);
776: }
777:
778: _depositOrPaybackInLiquidity(TOKEN_0, 0, token0Amt_); // <= FOUND
779:
780: _depositOrPaybackInLiquidity(TOKEN_1, 0, token1Amt_);
781:
782:
783: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
784: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
785:
786:
787: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
788:
789: userBorrow_ -= shares_;
790:
791: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
792:
793: _totalBorrowShares = totalBorrowShares_ - shares_;
794: } else {
795: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
796: }
797:
798:
799: dexVariables = dexVariables_;
800:
801: emit LogPaybackPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
802: }
['810']
810: function deposit( // <= FOUND
811: uint token0Amt_,
812: uint token1Amt_,
813: uint minSharesAmt_,
814: bool estimate_
815: ) public payable returns (uint shares_) {
816: uint dexVariables_ = dexVariables;
817: uint dexVariables2_ = dexVariables2;
818:
819: _check(dexVariables_, dexVariables2_);
820:
821: uint userSupplyData_ = _userSupplyData[msg.sender];
822:
823: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
824:
825:
826: if ((dexVariables2_ & 1) == 1) {
827: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
828:
829: DepositColMemory memory d_;
830:
831: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
832: CollateralReserves memory c2_ = c_;
833:
834: if (token0Amt_ > 0) {
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
836: _verifySwapAndNonPerfectActions(d_.token0AmtAdjusted, token0Amt_);
837: _verifyMint(d_.token0AmtAdjusted, c_.token0RealReserves);
838: }
839:
840: if (token1Amt_ > 0) {
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
842: _verifySwapAndNonPerfectActions(d_.token1AmtAdjusted, token1Amt_);
843: _verifyMint(d_.token1AmtAdjusted, c_.token1RealReserves);
844: }
845:
846: uint temp_;
847: uint temp2_;
848:
849: uint totalSupplyShares_ = _totalSupplyShares;
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) {
851:
852: shares_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
853: totalSupplyShares_ += shares_;
854: } else if ((d_.token1AmtAdjusted > 0 && d_.token0AmtAdjusted == 0) && (c_.token1RealReserves > 0) && (c_.token0RealReserves == 0)) {
855:
856: shares_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
857: totalSupplyShares_ += shares_;
858: } else {
859: if (d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted > 0) {
860:
861:
862: temp_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
863:
864: temp2_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
865: if (temp_ > temp2_) {
866:
867: shares_ = (temp2_ * totalSupplyShares_) / 1e18;
868:
869: temp_ = ((temp_ - temp2_) * c_.token0RealReserves) / 1e18;
870: temp2_ = 0;
871: } else if (temp2_ > temp_) {
872:
873: shares_ = (temp_ * totalSupplyShares_) / 1e18;
874:
875: temp2_ = ((temp2_ - temp_) * c_.token1RealReserves) / 1e18;
876: temp_ = 0;
877: } else {
878:
879: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
880: }
881:
882:
883: c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, true);
884:
885: totalSupplyShares_ += shares_;
886: } else if (d_.token0AmtAdjusted > 0) {
887: temp_ = d_.token0AmtAdjusted;
888: temp2_ = 0;
889: } else if (d_.token1AmtAdjusted > 0) {
890: temp_ = 0;
891: temp2_ = d_.token1AmtAdjusted;
892: } else {
893:
894: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
895: }
896:
897: if (temp_ > 0) {
898:
899: temp_ = _getSwapAndDeposit(
900: temp_,
901: c2_.token1ImaginaryReserves,
902: c2_.token0ImaginaryReserves,
903: c2_.token0RealReserves,
904: c2_.token1RealReserves
905: );
906: } else if (temp2_ > 0) {
907:
908: temp_ = _getSwapAndDeposit(
909: temp2_,
910: c2_.token0ImaginaryReserves,
911: c2_.token1ImaginaryReserves,
912: c2_.token1RealReserves,
913: c2_.token0RealReserves
914: );
915: } else {
916:
917: revert FluidDexError(ErrorTypes.DexT1__DepositAmtsZero);
918: }
919:
920:
921: temp_ = temp_ * totalSupplyShares_ / 1e18;
922:
923:
924:
925: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
926:
927: shares_ += temp_;
928:
929: totalSupplyShares_ += temp_;
930: }
931:
932: if (estimate_) revert FluidDexLiquidityOutput(shares_);
933:
934: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__SharesMintedLess);
935:
936: if (token0Amt_ > 0) {
937: _verifyToken1Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
938: temp_ = token0Amt_;
939: _depositOrPaybackInLiquidity(TOKEN_0, temp_, 0); // <= FOUND
940: }
941:
942: if (token1Amt_ > 0) {
943: _verifyToken0Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
944: temp_ = token1Amt_;
945: _depositOrPaybackInLiquidity(TOKEN_1, temp_, 0);
946: }
947:
948:
949: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
950:
951: temp_ = ((temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK));
952:
953:
954:
955: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
956:
957: temp_ += shares_;
958:
959: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
960:
961:
962: _totalSupplyShares = totalSupplyShares_;
963:
964: emit LogDepositColLiquidity(token0Amt_, token1Amt_, shares_);
965:
966: _arbitrage(dexVariables_, dexVariables2_, pex_);
967: } else {
968: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
969: }
970: }
['978']
978: function withdraw( // <= FOUND
979: uint token0Amt_,
980: uint token1Amt_,
981: uint maxSharesAmt_,
982: bool estimate_
983: ) public returns (uint shares_) {
984: uint dexVariables_ = dexVariables;
985: uint dexVariables2_ = dexVariables2;
986:
987: _check(dexVariables_, dexVariables2_);
988:
989: uint userSupplyData_ = _userSupplyData[msg.sender];
990:
991: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
992:
993:
994: if ((dexVariables2_ & 1) == 1) {
995: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
996:
997: WithdrawColMemory memory w_;
998:
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true);
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false);
1001: w_.token0ReservesInitial = token0Reserves_;
1002: w_.token1ReservesInitial = token1Reserves_;
1003:
1004: if (token0Amt_ > 0) {
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1006: _verifySwapAndNonPerfectActions(w_.token0AmtAdjusted, token0Amt_);
1007: _verifyRedeem(w_.token0AmtAdjusted, token0Reserves_);
1008: }
1009:
1010: if (token1Amt_ > 0) {
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1012: _verifySwapAndNonPerfectActions(w_.token1AmtAdjusted, token1Amt_);
1013: _verifyRedeem(w_.token1AmtAdjusted, token1Reserves_);
1014: }
1015:
1016: uint temp_;
1017: uint temp2_;
1018:
1019: uint totalSupplyShares_ = _totalSupplyShares;
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) {
1021:
1022: shares_ = (w_.token0AmtAdjusted * 1e18 / token0Reserves_);
1023: totalSupplyShares_ -= shares_;
1024: } else if ((w_.token1AmtAdjusted > 0 && w_.token0AmtAdjusted == 0) && (token1Reserves_ > 0) && (token0Reserves_ == 0)) {
1025:
1026: shares_ = (w_.token1AmtAdjusted * 1e18 / token1Reserves_);
1027: totalSupplyShares_ -= shares_;
1028: } else {
1029: if (w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted > 0) {
1030:
1031:
1032: temp_ = w_.token0AmtAdjusted * 1e18 / token0Reserves_;
1033:
1034: temp2_ = w_.token1AmtAdjusted * 1e18 / token1Reserves_;
1035: if (temp_ > temp2_) {
1036:
1037: shares_ = ((temp2_ * totalSupplyShares_) / 1e18);
1038:
1039: temp_ = ((temp_ - temp2_) * token0Reserves_) / 1e18;
1040: temp2_ = 0;
1041: } else if (temp2_ > temp_) {
1042:
1043: shares_ = ((temp_ * totalSupplyShares_) / 1e18);
1044:
1045: temp2_ = ((temp2_ - temp_) * token1Reserves_) / 1e18;
1046: temp_ = 0;
1047: } else {
1048:
1049: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1050: }
1051:
1052:
1053: token0Reserves_ = token0Reserves_ - (token0Reserves_ * shares_ / totalSupplyShares_);
1054: token1Reserves_ = token1Reserves_ - (token1Reserves_ * shares_ / totalSupplyShares_);
1055: totalSupplyShares_ -= shares_;
1056: } else if (w_.token0AmtAdjusted > 0) {
1057: temp_ = w_.token0AmtAdjusted;
1058: temp2_ = 0;
1059: } else if (w_.token1AmtAdjusted > 0) {
1060: temp_ = 0;
1061: temp2_ = w_.token1AmtAdjusted;
1062: } else {
1063:
1064: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1065: }
1066:
1067: uint token0ImaginaryReservesOutsideRangpex_;
1068: uint token1ImaginaryReservesOutsideRangpex_;
1069:
1070: if (pex_.geometricMean < 1e27) {
1071: (token0ImaginaryReservesOutsideRangpex_, token1ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange(pex_.geometricMean, pex_.upperRange, (token0Reserves_ - temp_), (token1Reserves_ - temp2_));
1072: } else {
1073:
1074:
1075:
1076:
1077: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_));
1078: }
1079:
1080: if (temp_ > 0) {
1081:
1082: temp_ = _getWithdrawAndSwap(
1083: token0Reserves_,
1084: token1Reserves_,
1085: token0ImaginaryReservesOutsideRangpex_,
1086: token1ImaginaryReservesOutsideRangpex_,
1087: temp_
1088: );
1089: } else if (temp2_ > 0) {
1090:
1091: temp_ = _getWithdrawAndSwap(
1092: token1Reserves_,
1093: token0Reserves_,
1094: token1ImaginaryReservesOutsideRangpex_,
1095: token0ImaginaryReservesOutsideRangpex_,
1096: temp2_
1097: );
1098: } else {
1099:
1100: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1101: }
1102:
1103:
1104: temp_ = (temp_ * totalSupplyShares_ / 1e18);
1105:
1106:
1107: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1108:
1109: shares_ += temp_;
1110:
1111: totalSupplyShares_ -= temp_;
1112: }
1113:
1114: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1115:
1116: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__WithdrawExcessSharesBurn);
1117:
1118:
1119: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1120: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1121:
1122:
1123:
1124: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
1125:
1126: temp_ -= shares_;
1127:
1128:
1129: if (temp_ < temp2_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1130:
1131: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
1132:
1133:
1134: _totalSupplyShares = totalSupplyShares_;
1135:
1136: if (w_.token0AmtAdjusted > 0) {
1137: _verifyToken0Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1138:
1139: temp_ = token0Amt_;
1140: LIQUIDITY.operate(TOKEN_0, -int(temp_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1141: }
1142:
1143: if (w_.token1AmtAdjusted > 0) {
1144: _verifyToken1Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1145:
1146: temp_ = token1Amt_;
1147: LIQUIDITY.operate(TOKEN_1, -int(temp_), 0, msg.sender, address(0), new bytes(0));
1148: }
1149:
1150: emit LogWithdrawColLiquidity(token0Amt_, token1Amt_, shares_);
1151:
1152: _arbitrage(dexVariables_, dexVariables2_, pex_);
1153: } else {
1154: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1155: }
1156:
1157: }
['1165']
1165: function borrow( // <= FOUND
1166: uint token0Amt_,
1167: uint token1Amt_,
1168: uint maxSharesAmt_,
1169: bool estimate_
1170: ) public returns (uint shares_) {
1171: uint dexVariables_ = dexVariables;
1172: uint dexVariables2_ = dexVariables2;
1173:
1174: _check(dexVariables_, dexVariables2_);
1175:
1176: uint userBorrowData_ = _userBorrowData[msg.sender];
1177:
1178: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1179:
1180:
1181: if (((dexVariables2_ >> 1) & 1) == 1) {
1182: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1183:
1184: BorrowDebtMemory memory b_;
1185:
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true);
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false);
1188: b_.token0DebtInitial = token0Debt_;
1189: b_.token1DebtInitial = token1Debt_;
1190:
1191: if (token0Amt_ > 0) {
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1193: _verifySwapAndNonPerfectActions(b_.token0AmtAdjusted, token0Amt_);
1194: _verifyMint(b_.token0AmtAdjusted, token0Debt_);
1195: }
1196:
1197: if (token1Amt_ > 0) {
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1199: _verifySwapAndNonPerfectActions(b_.token1AmtAdjusted, token1Amt_);
1200: _verifyMint(b_.token1AmtAdjusted, token1Debt_);
1201: }
1202:
1203: uint temp_;
1204: uint temp2_;
1205:
1206: uint totalBorrowShares_ = _totalBorrowShares;
1207: if ((b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted == 0) && (token0Debt_ > 0) && (token1Debt_ == 0)) {
1208:
1209: shares_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1210: totalBorrowShares_ += shares_;
1211: } else if ((b_.token1AmtAdjusted > 0 && b_.token0AmtAdjusted == 0) && (token1Debt_ > 0) && (token0Debt_ == 0)) {
1212:
1213: shares_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1214: totalBorrowShares_ += shares_;
1215: } else {
1216: if (b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted > 0) {
1217:
1218:
1219: temp_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1220:
1221: temp2_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1222: if (temp_ > temp2_) {
1223:
1224: shares_ = (temp2_ * totalBorrowShares_) / 1e18;
1225:
1226: temp_ = ((temp_ - temp2_) * token0Debt_) / 1e18;
1227: temp2_ = 0;
1228: } else if (temp2_ > temp_) {
1229:
1230: shares_ = (temp_ * totalBorrowShares_) / 1e18;
1231:
1232: temp2_ = ((temp2_ - temp_) * token1Debt_) / 1e18;
1233: temp_ = 0;
1234: } else {
1235:
1236: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1237: }
1238:
1239:
1240: token0Debt_ = token0Debt_ + token0Debt_ * shares_ / totalBorrowShares_;
1241: token1Debt_ = token1Debt_ + token1Debt_ * shares_ / totalBorrowShares_;
1242: totalBorrowShares_ += shares_;
1243: } else if (b_.token0AmtAdjusted > 0) {
1244: temp_ = b_.token0AmtAdjusted;
1245: temp2_ = 0;
1246: } else if (b_.token1AmtAdjusted > 0) {
1247: temp_ = 0;
1248: temp2_ = b_.token1AmtAdjusted;
1249: } else {
1250:
1251: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1252: }
1253:
1254: uint token0FinalImaginaryReserves_;
1255: uint token1FinalImaginaryReserves_;
1256:
1257: if (pex_.geometricMean < 1e27) {
1258: (, , token0FinalImaginaryReserves_, token1FinalImaginaryReserves_) =
1259: _calculateDebtReserves(pex_.geometricMean, pex_.lowerRange, (token0Debt_ + temp_), (token1Debt_ + temp2_));
1260: } else {
1261:
1262:
1263:
1264:
1265: (, , token1FinalImaginaryReserves_, token0FinalImaginaryReserves_) =
1266: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_));
1267: }
1268:
1269: if (temp_ > 0) {
1270:
1271: temp_ = _getBorrowAndSwap(
1272: token0Debt_,
1273: token1Debt_,
1274: token0FinalImaginaryReserves_,
1275: token1FinalImaginaryReserves_,
1276: temp_
1277: );
1278: } else if (temp2_ > 0) {
1279:
1280: temp_ = _getBorrowAndSwap(
1281: token1Debt_,
1282: token0Debt_,
1283: token1FinalImaginaryReserves_,
1284: token0FinalImaginaryReserves_,
1285: temp2_
1286: );
1287: } else {
1288:
1289: revert FluidDexError(ErrorTypes.DexT1__BorrowAmtsZero);
1290: }
1291:
1292:
1293: temp_ = temp_ * totalBorrowShares_ / 1e18;
1294:
1295:
1296: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1297:
1298: shares_ += temp_;
1299:
1300: totalBorrowShares_ += temp_;
1301: }
1302:
1303: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1304:
1305: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__BorrowExcessSharesMinted);
1306:
1307:
1308:
1309: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1310: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1311:
1312:
1313:
1314: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1315:
1316: temp_ += shares_;
1317:
1318:
1319: if (temp_ > temp2_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached);
1320:
1321: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1322:
1323: if (b_.token0AmtAdjusted > 0) {
1324:
1325: _verifyToken1Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1326:
1327: temp_ = token0Amt_;
1328:
1329: LIQUIDITY.operate(TOKEN_0, 0, int(temp_), address(0), msg.sender, new bytes(0)); // <= FOUND
1330: }
1331:
1332: if (b_.token1AmtAdjusted > 0) {
1333:
1334: _verifyToken0Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1335:
1336: temp_ = token1Amt_;
1337:
1338: LIQUIDITY.operate(TOKEN_1, 0, int(temp_), address(0), msg.sender, new bytes(0));
1339: }
1340:
1341:
1342: _totalBorrowShares = totalBorrowShares_;
1343:
1344: emit LogBorrowDebtLiquidity(token0Amt_, token1Amt_, shares_);
1345:
1346: _arbitrage(dexVariables_, dexVariables2_, pex_);
1347: } else {
1348: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1349: }
1350:
1351: }
['1359']
1359: function payback( // <= FOUND
1360: uint token0Amt_,
1361: uint token1Amt_,
1362: uint minSharesAmt_,
1363: bool estimate_
1364: ) public payable returns (uint shares_) {
1365: uint dexVariables_ = dexVariables;
1366: uint dexVariables2_ = dexVariables2;
1367:
1368: _check(dexVariables_, dexVariables2_);
1369:
1370: uint userBorrowData_ = _userBorrowData[msg.sender];
1371:
1372: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1373:
1375:
1376: if (((dexVariables2_ >> 1) & 1) == 1) {
1377: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1378:
1379: PaybackDebtMemory memory p_;
1380:
1381: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1382: DebtReserves memory d2_ = d_;
1383:
1384: if (token0Amt_ > 0) {
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
1386: _verifySwapAndNonPerfectActions(p_.token0AmtAdjusted, token0Amt_);
1387: _verifyRedeem(p_.token0AmtAdjusted, d_.token0Debt);
1388: }
1389:
1390: if (token1Amt_ > 0) {
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
1392: _verifySwapAndNonPerfectActions(p_.token1AmtAdjusted, token1Amt_);
1393: _verifyRedeem(p_.token1AmtAdjusted, d_.token1Debt);
1394: }
1395:
1396: uint temp_;
1397: uint temp2_;
1398:
1399: uint totalBorrowShares_ = _totalBorrowShares;
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) {
1401:
1402: shares_ = (p_.token0AmtAdjusted * 1e18 / d_.token0Debt);
1403: totalBorrowShares_ -= shares_;
1404: } else if ((p_.token1AmtAdjusted > 0 && p_.token0AmtAdjusted == 0) && (d_.token1Debt > 0) && (d_.token0Debt == 0)) {
1405:
1406: shares_ = (p_.token1AmtAdjusted * 1e18 / d_.token1Debt);
1407: totalBorrowShares_ -= shares_;
1408: } else {
1409: if (p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted > 0) {
1410:
1411:
1412: temp_ = p_.token0AmtAdjusted * 1e18 / d_.token0Debt;
1413:
1414: temp2_ = p_.token1AmtAdjusted * 1e18 / d_.token1Debt;
1415: if (temp_ > temp2_) {
1416:
1417: shares_ = ((temp2_ * totalBorrowShares_) / 1e18);
1418:
1419: temp_ = p_.token0AmtAdjusted - (temp2_ * p_.token0AmtAdjusted) / temp_;
1420: temp2_ = 0;
1421: } else if (temp2_ > temp_) {
1422:
1423: shares_ = ((temp_ * totalBorrowShares_) / 1e18);
1424:
1425: temp2_ = p_.token1AmtAdjusted - ((temp_ * p_.token1AmtAdjusted) / temp2_);
1426: temp_ = 0;
1427: } else {
1428:
1429: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1430: }
1431:
1432:
1433: d2_ = _getUpdateDebtReserves(
1434: shares_,
1435: totalBorrowShares_,
1436: d_,
1437: false
1438: );
1439: totalBorrowShares_ -= shares_;
1440: } else if (p_.token0AmtAdjusted > 0) {
1441: temp_ = p_.token0AmtAdjusted;
1442: temp2_ = 0;
1443: } else if (p_.token1AmtAdjusted > 0) {
1444: temp_ = 0;
1445: temp2_ = p_.token1AmtAdjusted;
1446: } else {
1447:
1448: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1449: }
1450:
1451: if (temp_ > 0) {
1452:
1453: temp_ = _getSwapAndPayback(
1454: d2_.token0Debt,
1455: d2_.token1Debt,
1456: d2_.token0ImaginaryReserves,
1457: d2_.token1ImaginaryReserves,
1458: temp_
1459: );
1460: } else if (temp2_ > 0) {
1461:
1462: temp_ = _getSwapAndPayback(
1463: d2_.token1Debt,
1464: d2_.token0Debt,
1465: d2_.token1ImaginaryReserves,
1466: d2_.token0ImaginaryReserves,
1467: temp2_
1468: );
1469: } else {
1470:
1471: revert FluidDexError(ErrorTypes.DexT1__PaybackAmtsZero);
1472: }
1473:
1474:
1475: temp_ = (temp_ * totalBorrowShares_ / 1e18);
1476:
1477:
1478:
1479: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1480:
1481: shares_ += temp_;
1482:
1483: totalBorrowShares_ -= temp_;
1484: }
1485:
1486: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1487:
1488: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__PaybackSharedBurnedLess);
1489:
1490: if (token0Amt_ > 0) {
1491:
1492: _verifyToken0Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1493:
1494: temp_ = token0Amt_;
1495: _depositOrPaybackInLiquidity(TOKEN_0, 0, temp_); // <= FOUND
1496: }
1497:
1498: if (token1Amt_ > 0) {
1499:
1500: _verifyToken1Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1501:
1502: temp_ = token1Amt_;
1503: _depositOrPaybackInLiquidity(TOKEN_1, 0, temp_);
1504: }
1505:
1506:
1507:
1508: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1509: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1510:
1511:
1512:
1513: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1514:
1515: temp_ -= shares_;
1516:
1517: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1518:
1519: _totalBorrowShares = totalBorrowShares_;
1520:
1521: emit LogPaybackDebtLiquidity(token0Amt_, token1Amt_, shares_);
1522:
1523: _arbitrage(dexVariables_, dexVariables2_, pex_);
1524: } else {
1525: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1526: }
1527: }
['1535']
1535: function withdrawPerfectInOneToken( // <= FOUND
1536: uint shares_,
1537: uint minToken0_,
1538: uint minToken1_,
1539: bool estimate_
1540: ) public returns (uint withdrawAmt_) {
1541: uint dexVariables_ = dexVariables;
1542: uint dexVariables2_ = dexVariables2;
1543:
1544: _check(dexVariables_, dexVariables2_);
1545:
1546: uint userSupplyData_ = _userSupplyData[msg.sender];
1547:
1548: if (userSupplyData_ & 1 == 0 && !estimate_) {
1549: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
1550: }
1551:
1552: if ((minToken0_ > 0 && minToken1_ > 0) || (minToken0_ == 0 && minToken1_ == 0)) {
1553:
1554: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1555: }
1556:
1557:
1558: if ((dexVariables2_ & 1) == 1) {
1559: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1560:
1561: uint totalSupplyShares_ = _totalSupplyShares;
1562:
1563: _verifyRedeem(shares_, totalSupplyShares_);
1564:
1565: uint token0Amt_;
1566: uint token1Amt_;
1567:
1568: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1569: CollateralReserves memory c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, false);
1570:
1571: token0Amt_ = c_.token0RealReserves - c2_.token0RealReserves - 1;
1572: token1Amt_ = c_.token1RealReserves - c2_.token1RealReserves - 1;
1573:
1574: if (minToken0_ > 0) {
1575:
1576: token0Amt_ += _getAmountOut(token1Amt_, c2_.token1ImaginaryReserves, c2_.token0ImaginaryReserves);
1577: token1Amt_ = 0;
1578: _verifyToken0Reserves((c_.token0RealReserves - token0Amt_), c_.token1RealReserves, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1579:
1580:
1581: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
1582:
1583:
1584: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1585:
1586: withdrawAmt_ = token0Amt_;
1587: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1588: if (withdrawAmt_ < minToken0_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1589: } else {
1590:
1591: token1Amt_ += _getAmountOut(token0Amt_, c2_.token0ImaginaryReserves, c2_.token1ImaginaryReserves);
1592: token0Amt_ = 0;
1593: _verifyToken1Reserves(c_.token0RealReserves, (c_.token1RealReserves - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1594:
1595:
1596: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
1597:
1598:
1599: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1600:
1601: withdrawAmt_ = token1Amt_;
1602: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1603: if (withdrawAmt_ < minToken1_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1604: }
1605:
1606: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1607: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
1608:
1609:
1610:
1611: uint256 temp_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
1612:
1613: userSupply_ -= shares_;
1614:
1615:
1616: if (userSupply_ < temp_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1617:
1618: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, temp_);
1619:
1620: _totalSupplyShares = totalSupplyShares_ - shares_;
1621:
1622: if (minToken0_ > 0) {
1623:
1624: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1625: } else {
1626:
1627: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
1628: }
1629:
1630:
1631: temp_ = shares_;
1632: emit LogWithdrawColInOneToken(temp_, token0Amt_, token1Amt_);
1633:
1634: _arbitrage(dexVariables_, dexVariables2_, pex_);
1635: } else {
1636: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1637: }
1638: }
['1646']
1646: function paybackPerfectInOneToken( // <= FOUND
1647: uint shares_,
1648: uint maxToken0_,
1649: uint maxToken1_,
1650: bool estimate_
1651: ) public payable returns (uint paybackAmt_) {
1652: uint dexVariables_ = dexVariables;
1653: uint dexVariables2_ = dexVariables2;
1654:
1655: _check(dexVariables_, dexVariables2_);
1656:
1657: uint userBorrowData_ = _userBorrowData[msg.sender];
1658:
1659: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1660:
1661: if ((maxToken0_ > 0 && maxToken1_ > 0) || (maxToken0_ == 0 && maxToken1_ == 0)) {
1662:
1663: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1664: }
1665:
1666:
1667: if (((dexVariables2_ >> 1) & 1) == 1) {
1668: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1669:
1670: uint totalBorrowShares_ = _totalBorrowShares;
1671:
1672: _verifyRedeem(shares_, totalBorrowShares_);
1673:
1674: uint token0Amt_;
1675: uint token1Amt_;
1676:
1677:
1678: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1679:
1680: DebtReserves memory d2_ = _getUpdateDebtReserves(shares_, totalBorrowShares_, d_, false);
1681:
1682: if (maxToken0_ > 0) {
1683:
1684: token0Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1685: d2_.token0ImaginaryReserves,
1686: d2_.token1ImaginaryReserves,
1687: d_.token0Debt,
1688: d_.token1Debt,
1689: d2_.token0RealReserves,
1690: d2_.token1RealReserves
1691: );
1692: _verifyToken0Reserves((d_.token0Debt - token0Amt_), d_.token1Debt, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1693:
1694:
1695: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
1696:
1697:
1698: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1699:
1700: paybackAmt_ = token0Amt_;
1701: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1702: if (paybackAmt_ > maxToken0_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1703: _depositOrPaybackInLiquidity(TOKEN_0, 0, paybackAmt_); // <= FOUND
1704: } else {
1705:
1706: token1Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1707: d2_.token1ImaginaryReserves,
1708: d2_.token0ImaginaryReserves,
1709: d_.token1Debt,
1710: d_.token0Debt,
1711: d2_.token1RealReserves,
1712: d2_.token0RealReserves
1713: );
1714: _verifyToken1Reserves(d_.token0Debt, (d_.token1Debt - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1715:
1716:
1717: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
1718:
1719:
1720: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1721:
1722: paybackAmt_ = token1Amt_;
1723: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1724: if (paybackAmt_ > maxToken1_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1725: _depositOrPaybackInLiquidity(TOKEN_1, 0, paybackAmt_);
1726: }
1727:
1728:
1729: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1730: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
1731:
1732:
1733:
1734: uint256 temp_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
1735: userBorrow_ -= shares_;
1736:
1737: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, temp_);
1738:
1739: _totalBorrowShares = totalBorrowShares_ - shares_;
1740:
1741:
1742: temp_ = shares_;
1743: emit LogPaybackDebtInOneToken(temp_, token0Amt_, token1Amt_);
1744:
1745: _arbitrage(dexVariables_, dexVariables2_, pex_);
1746: } else {
1747: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1748: }
1749: }
['1758']
1758: function _arbitrage(uint dexVariables_, uint dexVariables2_, PricesAndExchangePrice memory pex_) private { // <= FOUND
1759: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
1760:
1761: CollateralReserves memory c_;
1762: DebtReserves memory d_;
1763: uint price_;
1764: if ((dexVariables2_ & 1) == 1) {
1765: c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1766: }
1767: if ((dexVariables2_ & 2) == 2) {
1768: d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1769: }
1770: if ((dexVariables2_ & 3) < 3) {
1771: price_ = ((dexVariables2_ & 1) == 1) ?
1772: ((c_.token1ImaginaryReserves) * 1e27) / (c_.token0ImaginaryReserves) :
1773: ((d_.token1ImaginaryReserves) * 1e27) / (d_.token0ImaginaryReserves);
1774:
1775:
1776: dexVariables = _updateOracle(
1777: price_,
1778: pex_.centerPrice,
1779: dexVariables_
1780: );
1781: return;
1782: }
1783:
1784: uint temp_;
1785: uint amtOut_;
1786: uint amtIn_;
1787:
1788:
1789:
1790:
1791: int a_ = _swapRoutingIn(0, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves); // <= FOUND
1792: if (a_ > 0) {
1793:
1794: temp_ = uint(a_);
1795: amtOut_ = _getAmountOut(temp_ , c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
1796: amtIn_ = _getAmountIn(temp_ , d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
1797:
1798:
1799:
1800:
1801: price_ = ((c_.token1ImaginaryReserves - amtOut_) * 1e27) / (c_.token0ImaginaryReserves + temp_);
1802:
1803:
1804: a_ = (((a_) * int(TOKEN_0_DENOMINATOR_PRECISION)) / int(TOKEN_0_NUMERATOR_PRECISION));
1805: amtOut_ = (((amtOut_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1806: amtIn_ = (((amtIn_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1807:
1808:
1809:
1810: LIQUIDITY.operate(TOKEN_0, a_, a_, address(0), address(this), abi.encode(SKIP_TRANSFERS, address(this)));
1811: LIQUIDITY.operate(TOKEN_1, -int(amtOut_), -int(amtIn_), address(this), address(0), abi.encode(SKIP_TRANSFERS, address(this)));
1812: } else if (a_ < 0) {
1813:
1814: temp_ = uint(-a_);
1815: amtOut_ = _getAmountOut(temp_ , d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
1816: amtIn_ = _getAmountIn(temp_ , c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
1817:
1818:
1819:
1820:
1821: price_ = ((d_.token1ImaginaryReserves - amtOut_) * 1e27) / (d_.token0ImaginaryReserves + temp_);
1822:
1823:
1824: a_ = ((a_ * int(TOKEN_0_DENOMINATOR_PRECISION)) / int(TOKEN_0_NUMERATOR_PRECISION));
1825: amtOut_ = ((amtOut_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1826: amtIn_ = (((amtIn_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1827:
1828:
1829:
1830: LIQUIDITY.operate(TOKEN_0, a_, a_, address(this), address(0), abi.encode(SKIP_TRANSFERS, address(this)));
1831: LIQUIDITY.operate(TOKEN_1, int(amtIn_), int(amtOut_), address(0), address(this), abi.encode(SKIP_TRANSFERS, address(this)));
1832: } else {
1833:
1834: revert FluidDexError(ErrorTypes.DexT1__NothingToArbitrage);
1835: }
1836:
1837:
1838: temp_ = (dexVariables2_ >> 142) & X30;
1839: if (temp_ > 0) {
1840: uint lastPrice_ = (dexVariables_ >> 41) & X40;
1841: lastPrice_ = (lastPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastPrice_ & DEFAULT_EXPONENT_MASK);
1842: _hookVerify(temp_, 2, lastPrice_ > price_, price_);
1843: }
1844:
1845:
1846: dexVariables = _updateOracle(
1847: price_,
1848: pex_.centerPrice,
1849: dexVariables_
1850: );
1851:
1852: emit LogArbitrage(a_, amtOut_);
1853: }
['1125']
1125: function _depositOrPaybackInLiquidity(address token_, uint depositAmt_, uint paybackAmt_) internal { // <= FOUND
1126:
1127:
1128:
1129: if (depositAmt_ > 0 && paybackAmt_ > 0) revert();
1130: if (token_ == NATIVE_TOKEN) {
1131: uint amt_ = depositAmt_ > 0 ? depositAmt_ : paybackAmt_;
1132: if (msg.value > amt_) {
1133: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_);
1134: } else if (msg.value < amt_) {
1135: revert FluidDexError(ErrorTypes.DexT1__MsgValueLowOnDepositOrPayback);
1136: }
1137:
1138:
1139: LIQUIDITY.operate{ value: amt_ }(token_, int(depositAmt_), -int(paybackAmt_), address(0), address(0), abi.encode(msg.sender)); // <= FOUND
1140: } else {
1141: LIQUIDITY.operate(token_, int(depositAmt_), -int(paybackAmt_), address(0), address(0), abi.encode(msg.sender));
1142: }
1143: }
['76']
76: function _turnOnSmartCol( // <= FOUND
77: uint token0Amt_,
78: uint centerPrice_
79: ) internal {
80: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
81: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
82:
83: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision;
84:
85: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
86:
87: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
88:
89: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
90:
91: address token_;
92: uint amt_;
93: for (uint i = 0; i < 2; i++) {
94: if (i == 0) {
95: token_ = c_.token0;
96: amt_ = token0Amt_;
97: } else {
98: token_ = c_.token1;
99: amt_ = token1Amt_;
100: }
101: if (token_ == NATIVE_TOKEN) {
102: if (msg.value > amt_) {
103: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_);
104: } else if (msg.value < amt_) {
105: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
106: }
107:
108: liquidity_.operate{ value: amt_ }(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender)); // <= FOUND
109: } else {
110:
111: liquidity_.operate(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
112: }
113: }
114:
115:
116:
117:
118: _totalSupplyShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
119:
120: if (_totalSupplyShares < NINE_DECIMALS) {
121: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
122: }
123: }
['145']
145: function _turnOnSmartDebt( // <= FOUND
146: uint token0Amt_,
147: uint centerPrice_
148: ) internal {
149: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
150: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
151:
152: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision;
153:
154: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
155:
156: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
157:
158: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
159:
160: liquidity_.operate(c_.token0, 0, int(token0Amt_), address(0), TEAM_MULTISIG, new bytes(0)); // <= FOUND
161: liquidity_.operate(c_.token1, 0, int(token1Amt_), address(0), TEAM_MULTISIG, new bytes(0));
162:
163:
164:
165:
166: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
167:
168: if (_totalBorrowShares < NINE_DECIMALS) {
169: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
170: }
171: }
When calculating price involves division, ensure there is a check of loss of precision in place, if this check is triggered the price should be rounded up by adding 1
Num of instances: 2
Click to show findings
['72']
72: function swapIn(
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_) {
78: uint dexVariables_ = dexVariables;
79: uint dexVariables2_ = dexVariables2;
80:
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
82:
83: _check(dexVariables_, dexVariables2_);
84:
85: if (to_ == address(0)) to_ = msg.sender;
86:
87: SwapInMemory memory s_;
88:
89: if (swap0to1_) {
90: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
91: s_.amtInAdjusted = amountIn_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
92: } else {
93: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
94: s_.amtInAdjusted = amountIn_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
95: }
96:
97: _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);
98:
99: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
100:
101: if (msg.value > 0) {
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
103: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
104: }
105:
106:
107: uint temp_ = dexVariables2_ & 1;
108:
109: uint temp2_ = (dexVariables2_ >> 1) & 1;
110:
111: uint temp3_;
112: uint temp4_;
113:
114:
115: temp3_ = ((dexVariables2_ >> 2) & X17);
116:
117:
118:
119:
120: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
121:
122:
123: s_.fee = SIX_DECIMALS - temp3_;
124:
125: CollateralReservesSwap memory cs_;
126: DebtReservesSwap memory ds_;
127: if (temp_ == 1) {
128:
129: {
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
131: if (swap0to1_) {
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
134: } else {
135: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
137: }
138: }
139: }
140:
141: if (temp2_ == 1) {
142:
143: {
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
145: if (swap0to1_) {
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
148: } else {
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
151: }
152: }
153: }
154:
155:
156:
157:
158:
159:
160: if (
161: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
162: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
163:
164: if (temp_ == 1 && temp2_ == 1) {
165:
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves);
167: }
168:
169:
170:
171:
172:
173:
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
175:
176:
177: temp_ = uint(s_.swapRoutingAmt);
178:
179: temp3_ = s_.amtInAdjusted - temp_;
180:
181: (temp2_, temp4_) = (0, 0);
182:
183:
184: s_.withdrawTo = to_;
185: s_.borrowTo = to_;
186: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {
187:
188: (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);
189:
190: s_.withdrawTo = to_;
191: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
192:
193: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);
194:
195: s_.borrowTo = to_;
196: } else {
197:
198: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
199: }
200:
201: if (temp_ > 0) {
202:
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
204: swap0to1_ ?
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
207: }
208: if (temp3_ > 0) {
209:
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
211: swap0to1_ ?
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
214: }
215:
216:
217: if (temp_ > temp3_) {
218:
219: s_.price = swap0to1_ ? // <= FOUND
220: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) :
221: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
222: } else {
223:
224: s_.price = swap0to1_ ? // <= FOUND
225: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) :
226: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
227: }
228:
229:
230: if (swap0to1_) {
231: temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
232: temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
233: temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
234: temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
235: } else {
236: temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
237: temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
238: temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
239: temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
240: }
241:
242: amountOut_ = temp2_ + temp4_;
243:
244:
245: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);
246:
247: if (amountOut_ < amountOutMin_) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);
248:
249:
250: temp_ = (temp_ * s_.revenueCut) / SIX_DECIMALS;
251: temp3_ = (temp3_ * s_.revenueCut) / SIX_DECIMALS;
252:
253: s_.data = abi.encode(amountIn_, msg.sender);
254:
255: LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);
256:
257: LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));
258:
259:
260: temp_ = (dexVariables2_ >> 142) & X30;
261: if (temp_ > 0) {
262: s_.swap0to1 = swap0to1_;
263: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
264: }
265:
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
269:
271: dexVariables = _updateOracle(
272: s_.price,
273: pex_.centerPrice,
274: dexVariables_
275: );
276:
277: emit Swap(swap0to1_, amountIn_, amountOut_, to_);
278: }
['286']
286: function swapOut(
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ? // <= FOUND
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ? // <= FOUND
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
When a contract function accepts Ethereum and executes a .call()
or similar function that also forwards Ethereum value, it's important to check for and refund any remaining balance. This is because some of the supplied value may not be used during the call execution due to gas constraints, a revert in the called contract, or simply because not all the value was needed.
If you do not account for this remaining balance, it can become "locked" in the contract. It's crucial to either return the remaining balance to the sender or handle it in a way that ensures it is not permanently stuck. Neglecting to do so can lead to loss of funds and degradation of the contract's reliability. Furthermore, it's good practice to ensure fairness and trust with your users by returning unused funds.
Num of instances: 2
Click to show findings
['72']
72: function swapIn(
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_) { // <= FOUND
78: uint dexVariables_ = dexVariables;
79: uint dexVariables2_ = dexVariables2;
80:
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
82:
83: _check(dexVariables_, dexVariables2_);
84:
85: if (to_ == address(0)) to_ = msg.sender;
86:
87: SwapInMemory memory s_;
88:
89: if (swap0to1_) {
90: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
91: s_.amtInAdjusted = amountIn_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
92: } else {
93: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
94: s_.amtInAdjusted = amountIn_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
95: }
96:
97: _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);
98:
99: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
100:
101: if (msg.value > 0) {
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
103: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
104: }
105:
106:
107: uint temp_ = dexVariables2_ & 1;
108:
109: uint temp2_ = (dexVariables2_ >> 1) & 1;
110:
111: uint temp3_;
112: uint temp4_;
113:
114:
115: temp3_ = ((dexVariables2_ >> 2) & X17);
116:
117:
118:
119:
120: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
121:
122:
123: s_.fee = SIX_DECIMALS - temp3_;
124:
125: CollateralReservesSwap memory cs_;
126: DebtReservesSwap memory ds_;
127: if (temp_ == 1) {
128:
129: {
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
131: if (swap0to1_) {
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
134: } else {
135: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
137: }
138: }
139: }
140:
141: if (temp2_ == 1) {
142:
143: {
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
145: if (swap0to1_) {
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
148: } else {
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
151: }
152: }
153: }
154:
155:
156:
157:
158:
159:
160: if (
161: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
162: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
163:
164: if (temp_ == 1 && temp2_ == 1) {
165:
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves);
167: }
168:
169:
170:
171:
172:
173:
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
175:
176:
177: temp_ = uint(s_.swapRoutingAmt);
178:
179: temp3_ = s_.amtInAdjusted - temp_;
180:
181: (temp2_, temp4_) = (0, 0);
182:
183:
184: s_.withdrawTo = to_;
185: s_.borrowTo = to_;
186: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {
187:
188: (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);
189:
190: s_.withdrawTo = to_;
191: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
192:
193: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);
194:
195: s_.borrowTo = to_;
196: } else {
197:
198: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
199: }
200:
201: if (temp_ > 0) {
202:
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
204: swap0to1_ ?
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
207: }
208: if (temp3_ > 0) {
209:
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
211: swap0to1_ ?
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
214: }
215:
216:
217: if (temp_ > temp3_) {
218:
219: s_.price = swap0to1_ ?
220: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) :
221: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
222: } else {
223:
224: s_.price = swap0to1_ ?
225: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) :
226: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
227: }
228:
229:
230: if (swap0to1_) {
231: temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
232: temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
233: temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
234: temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
235: } else {
236: temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
237: temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
238: temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
239: temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
240: }
241:
242: amountOut_ = temp2_ + temp4_;
243:
244:
245: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);
246:
247: if (amountOut_ < amountOutMin_) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);
248:
249:
250: temp_ = (temp_ * s_.revenueCut) / SIX_DECIMALS;
251: temp3_ = (temp3_ * s_.revenueCut) / SIX_DECIMALS;
252:
253: s_.data = abi.encode(amountIn_, msg.sender);
254:
255: LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data); // <= FOUND
256:
257: LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));
258:
259:
260: temp_ = (dexVariables2_ >> 142) & X30;
261: if (temp_ > 0) {
262: s_.swap0to1 = swap0to1_;
263: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
264: }
265:
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
269:
271: dexVariables = _updateOracle(
272: s_.price,
273: pex_.centerPrice,
274: dexVariables_
275: );
276:
277: emit Swap(swap0to1_, amountIn_, amountOut_, to_);
278: }
['286']
286: function swapOut(
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) { // <= FOUND
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data); // <= FOUND
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
The use of fixed decimal values such as 1e18 or 1e8 in Solidity contracts can lead to inaccuracies, bugs, and vulnerabilities, particularly when interacting with tokens having different decimal configurations. Not all ERC20 tokens follow the standard 18 decimal places, and assumptions about decimal places can lead to miscalculations.
Resolution: Always retrieve and use the decimals()
function from the token contract itself when performing calculations involving token amounts. This ensures that your contract correctly handles tokens with any number of decimal places, mitigating the risk of numerical errors or under/overflows that could jeopardize contract integrity and user funds.
Num of instances: 43
Click to show findings
['852']
852:
853: shares_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves; // <= FOUND
['856']
856:
857: shares_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves; // <= FOUND
['862']
862:
863:
864: temp_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves; // <= FOUND
['864']
864:
865: temp2_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves; // <= FOUND
['867']
867:
868: shares_ = (temp2_ * totalSupplyShares_) / 1e18; // <= FOUND
['869']
869:
870: temp_ = ((temp_ - temp2_) * c_.token0RealReserves) / 1e18; // <= FOUND
['873']
873:
874: shares_ = (temp_ * totalSupplyShares_) / 1e18; // <= FOUND
['875']
875:
876: temp2_ = ((temp2_ - temp_) * c_.token1RealReserves) / 1e18; // <= FOUND
['921']
921:
922: temp_ = temp_ * totalSupplyShares_ / 1e18; // <= FOUND
['1022']
1022:
1023: shares_ = (w_.token0AmtAdjusted * 1e18 / token0Reserves_); // <= FOUND
['1026']
1026:
1027: shares_ = (w_.token1AmtAdjusted * 1e18 / token1Reserves_); // <= FOUND
['1032']
1032:
1033:
1034: temp_ = w_.token0AmtAdjusted * 1e18 / token0Reserves_; // <= FOUND
['1034']
1034:
1035: temp2_ = w_.token1AmtAdjusted * 1e18 / token1Reserves_; // <= FOUND
['1037']
1037:
1038: shares_ = ((temp2_ * totalSupplyShares_) / 1e18); // <= FOUND
['1039']
1039:
1040: temp_ = ((temp_ - temp2_) * token0Reserves_) / 1e18; // <= FOUND
['1043']
1043:
1044: shares_ = ((temp_ * totalSupplyShares_) / 1e18); // <= FOUND
['1045']
1045:
1046: temp2_ = ((temp2_ - temp_) * token1Reserves_) / 1e18; // <= FOUND
['1104']
1104:
1105: temp_ = (temp_ * totalSupplyShares_ / 1e18); // <= FOUND
['1209']
1209:
1210: shares_ = b_.token0AmtAdjusted * 1e18 / token0Debt_; // <= FOUND
['1213']
1213:
1214: shares_ = b_.token1AmtAdjusted * 1e18 / token1Debt_; // <= FOUND
['1219']
1219:
1220:
1221: temp_ = b_.token0AmtAdjusted * 1e18 / token0Debt_; // <= FOUND
['1221']
1221:
1222: temp2_ = b_.token1AmtAdjusted * 1e18 / token1Debt_; // <= FOUND
['1224']
1224:
1225: shares_ = (temp2_ * totalBorrowShares_) / 1e18; // <= FOUND
['1226']
1226:
1227: temp_ = ((temp_ - temp2_) * token0Debt_) / 1e18; // <= FOUND
['1230']
1230:
1231: shares_ = (temp_ * totalBorrowShares_) / 1e18; // <= FOUND
['1232']
1232:
1233: temp2_ = ((temp2_ - temp_) * token1Debt_) / 1e18; // <= FOUND
['1293']
1293:
1294: temp_ = temp_ * totalBorrowShares_ / 1e18; // <= FOUND
['1402']
1402:
1403: shares_ = (p_.token0AmtAdjusted * 1e18 / d_.token0Debt); // <= FOUND
['1406']
1406:
1407: shares_ = (p_.token1AmtAdjusted * 1e18 / d_.token1Debt); // <= FOUND
['1412']
1412:
1413:
1414: temp_ = p_.token0AmtAdjusted * 1e18 / d_.token0Debt; // <= FOUND
['1414']
1414:
1415: temp2_ = p_.token1AmtAdjusted * 1e18 / d_.token1Debt; // <= FOUND
['1417']
1417:
1418: shares_ = ((temp2_ * totalBorrowShares_) / 1e18); // <= FOUND
['1423']
1423:
1424: shares_ = ((temp_ * totalBorrowShares_) / 1e18); // <= FOUND
['1475']
1475:
1476: temp_ = (temp_ * totalBorrowShares_ / 1e18); // <= FOUND
['331']
331:
332: pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18; // <= FOUND
['661']
661:
662:
663:
664:
665:
666:
667:
668:
669: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18); // <= FOUND
['662']
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18); // <= FOUND
['756']
756:
757: temp_ = temp_ * 1e18 / (f_ + amtToSwap_); // <= FOUND
['758']
758:
759: temp2_ = temp2_ * 1e18 / (i_ - temp2_); // <= FOUND
['864']
864: shares_ = tokenAxa_ * 1e18 / c_; // <= FOUND
['1114']
1114:
1115: temp_ = temp_ * 1e18 / (c_ - amtToSwap_); // <= FOUND
['1116']
1116:
1117: temp2_ = temp2_ * 1e18 / (d_ + temp2_); // <= FOUND
['63']
63: uint256 internal constant ORACLE_PRECISION = 1e18; // <= FOUND
Utilizing msg.sig
for validation in if
or require
statements can be precarious in Solidity because msg.sig
only includes the first four bytes of the hash of the function signature, and not the entire signature. This means an attacker can feasibly brute force to find another function signature that generates the same first four bytes of the hash, thereby bypassing the intended security mechanism. This is known as a hash collision and is possible due to the limited size of msg.sig
. A safer alternative is to rely on role-based access control or specific address-based permissions, which are far less susceptible to such vulnerabilities.
Num of instances: 1
ETH balances can change due to gas costs, miner reordering, or unexpected transactions. Directly comparing an expected balance with ==
or !=
can lead to unpredictable results. Instead, use range checks or require a minimum balance. For instance, instead of requiring an exact balance, check if an account's balance is within an acceptable range or above a certain threshold. This provides flexibility and accounts for slight variations that might occur due to the dynamic nature of blockchain transactions and fees. By avoiding exact balance checks, smart contracts can avoid unintentional failures and enhance robustness.
Num of instances: 2
Click to show findings
['102']
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch); // <= FOUND
['316']
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch); // <= FOUND
Function parameters in Solidity are passed by value, meaning they are essentially local copies. Mutating them can lead to confusion and errors because the changes don't persist outside the function. By keeping function parameters immutable, you ensure clarity in code behavior, preventing unintended side-effects. If you need to modify a value based on a parameter, use a local variable inside the function, leaving the original parameter unaltered. By adhering to this practice, you maintain a clear distinction between input data and the internal processing logic, improving code readability and reducing the potential for bugs.
Num of instances: 11
Click to show findings
['72']
72: function swapIn( // <= FOUND
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_) {
78: uint dexVariables_ = dexVariables;
79: uint dexVariables2_ = dexVariables2;
80:
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
82:
83: _check(dexVariables_, dexVariables2_);
84:
85: if (to_ == address(0)) to_ = msg.sender; // <= FOUND
86:
87: SwapInMemory memory s_;
88:
89: if (swap0to1_) {
90: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
91: s_.amtInAdjusted = amountIn_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
92: } else {
93: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
94: s_.amtInAdjusted = amountIn_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
95: }
96:
97: _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);
98:
99: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
100:
101: if (msg.value > 0) {
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
103: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
104: }
105:
106:
107: uint temp_ = dexVariables2_ & 1;
108:
109: uint temp2_ = (dexVariables2_ >> 1) & 1;
110:
111: uint temp3_;
112: uint temp4_;
113:
114:
115: temp3_ = ((dexVariables2_ >> 2) & X17);
116:
117:
118:
119:
120: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
121:
122:
123: s_.fee = SIX_DECIMALS - temp3_;
124:
125: CollateralReservesSwap memory cs_;
126: DebtReservesSwap memory ds_;
127: if (temp_ == 1) {
128:
129: {
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
131: if (swap0to1_) {
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
134: } else {
135: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
137: }
138: }
139: }
140:
141: if (temp2_ == 1) {
142:
143: {
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
145: if (swap0to1_) {
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
148: } else {
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
151: }
152: }
153: }
154:
155:
156:
157:
158:
159:
160: if (
161: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
162: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
163:
164: if (temp_ == 1 && temp2_ == 1) {
165:
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves);
167: }
168:
169:
170:
171:
172:
173:
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
175:
176:
177: temp_ = uint(s_.swapRoutingAmt);
178:
179: temp3_ = s_.amtInAdjusted - temp_;
180:
181: (temp2_, temp4_) = (0, 0);
182:
183:
184: s_.withdrawTo = to_;
185: s_.borrowTo = to_;
186: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {
187:
188: (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);
189:
190: s_.withdrawTo = to_;
191: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
192:
193: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);
194:
195: s_.borrowTo = to_;
196: } else {
197:
198: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
199: }
200:
201: if (temp_ > 0) {
202:
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
204: swap0to1_ ?
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
207: }
208: if (temp3_ > 0) {
209:
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
211: swap0to1_ ?
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
214: }
215:
216:
217: if (temp_ > temp3_) {
218:
219: s_.price = swap0to1_ ?
220: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) :
221: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
222: } else {
223:
224: s_.price = swap0to1_ ?
225: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) :
226: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
227: }
228:
229:
230: if (swap0to1_) {
231: temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
232: temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
233: temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
234: temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
235: } else {
236: temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
237: temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
238: temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
239: temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
240: }
241:
242: amountOut_ = temp2_ + temp4_;
243:
244:
245: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);
246:
247: if (amountOut_ < amountOutMin_) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);
248:
249:
250: temp_ = (temp_ * s_.revenueCut) / SIX_DECIMALS;
251: temp3_ = (temp3_ * s_.revenueCut) / SIX_DECIMALS;
252:
253: s_.data = abi.encode(amountIn_, msg.sender);
254:
255: LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);
256:
257: LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));
258:
259:
260: temp_ = (dexVariables2_ >> 142) & X30;
261: if (temp_ > 0) {
262: s_.swap0to1 = swap0to1_;
263: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
264: }
265:
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
269:
271: dexVariables = _updateOracle(
272: s_.price,
273: pex_.centerPrice,
274: dexVariables_
275: );
276:
277: emit Swap(swap0to1_, amountIn_, amountOut_, to_);
278: }
['286']
286: function swapOut( // <= FOUND
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender; // <= FOUND
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
['62']
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
63: if (current_ > old_) {
64: uint diff_ = current_ - old_;
65: current_ = old_ + (diff_ * timePassed_ / shiftDuration_); // <= FOUND
66: } else {
67: uint diff_ = old_ - current_;
68: current_ = old_ - (diff_ * timePassed_ / shiftDuration_); // <= FOUND
69: }
70: return current_;
71: }
['80']
80: function _calcRangeShifting(uint upperRange_, uint lowerRange_, uint dexVariables2_) internal returns (uint, uint, uint) { // <= FOUND
81: uint rangeShift_ = _rangeShift;
82: uint oldUpperRange_ = rangeShift_ & X20;
83: uint oldLowerRange_ = (rangeShift_ >> 20) & X20;
84: uint shiftDuration_ = (rangeShift_ >> 40) & X20;
85: uint startTimeStamp_ = ((rangeShift_ >> 60) & X33);
86: if ((startTimeStamp_ + shiftDuration_) < block.timestamp) {
87:
88: delete _rangeShift;
89:
90:
91: dexVariables2_ = dexVariables2_ & ~uint(1 << 26); // <= FOUND
92: dexVariables2 = dexVariables2_;
93: return (upperRange_, lowerRange_, dexVariables2_);
94: }
95: uint timePassed_ = block.timestamp - startTimeStamp_;
96: return (
97: _calcShiftingDone(upperRange_, oldUpperRange_, timePassed_, shiftDuration_),
98: _calcShiftingDone(lowerRange_, oldLowerRange_, timePassed_, shiftDuration_),
99: dexVariables2_
100: );
101: }
['1297']
1297: function _updatingUserSupplyDataOnStorage( // <= FOUND
1298: uint userSupplyData_,
1299: uint userSupply_,
1300: uint newWithdrawalLimit_
1301: ) internal {
1302:
1303: newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitAfterOperate(
1304: userSupplyData_,
1305: userSupply_,
1306: newWithdrawalLimit_
1307: );
1308:
1309: userSupply_ = userSupply_.toBigNumber( // <= FOUND
1310: DEFAULT_COEFFICIENT_SIZE,
1311: DEFAULT_EXPONENT_SIZE,
1312: BigMathMinified.ROUND_DOWN
1313: );
1314:
1315: newWithdrawalLimit_ = newWithdrawalLimit_.toBigNumber(
1316: DEFAULT_COEFFICIENT_SIZE,
1317: DEFAULT_EXPONENT_SIZE,
1318: BigMathMinified.ROUND_DOWN
1319: );
1320:
1321: if (((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64) == userSupply_) {
1322:
1323:
1324: revert FluidDexError(ErrorTypes.DexT1__SharesAmountInsufficient);
1325: }
1326:
1327:
1328: _userSupplyData[msg.sender] =
1329:
1330: (userSupplyData_ & 0xfffffffffffffffffffffffc0000000000000000000000000000000000000001) |
1331: (userSupply_ << DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) |
1332: (newWithdrawalLimit_ << DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) |
1333: (block.timestamp << DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP);
1334: }
['1336']
1336: function _updatingUserBorrowDataOnStorage( // <= FOUND
1337: uint userBorrowData_,
1338: uint userBorrow_,
1339: uint newBorrowLimit_
1340: ) internal {
1341:
1342: newBorrowLimit_ = DexCalcs.calcBorrowLimitAfterOperate(userBorrowData_, userBorrow_, newBorrowLimit_);
1343:
1344:
1345: userBorrow_ = userBorrow_.toBigNumber( // <= FOUND
1346: DEFAULT_COEFFICIENT_SIZE,
1347: DEFAULT_EXPONENT_SIZE,
1348: BigMathMinified.ROUND_UP
1349: );
1350:
1351:
1352: newBorrowLimit_ = newBorrowLimit_.toBigNumber(
1353: DEFAULT_COEFFICIENT_SIZE,
1354: DEFAULT_EXPONENT_SIZE,
1355: BigMathMinified.ROUND_DOWN
1356: );
1357:
1358: if (((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64) == userBorrow_) {
1359:
1360:
1361: revert FluidDexError(ErrorTypes.DexT1__SharesAmountInsufficient);
1362: }
1363:
1364:
1365: _userBorrowData[msg.sender] =
1366:
1367: (userBorrowData_ & 0xfffffffffffffffffffffffc0000000000000000000000000000000000000001) |
1368: (userBorrow_ << DexSlotsLink.BITS_USER_BORROW_AMOUNT) |
1369: (newBorrowLimit_ << DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) |
1370: (block.timestamp << DexSlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP);
1371: }
['1373']
1373: function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view { // <= FOUND
1374: if (utilizationLimit_ < THREE_DECIMALS) {
1375: utilizationLimit_ = utilizationLimit_ * 10; // <= FOUND
1376:
1377: uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);
1378: liquidityLayerUtilization_ = (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14;
1379:
1380:
1381:
1382: if (liquidityLayerUtilization_ > utilizationLimit_) revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);
1383: }
1384: }
['175']
175: function updateFeeAndRevenueCut(uint fee_, uint revenueCut_) public _check _onlyDelegateCall { // <= FOUND
176:
177:
178: if(revenueCut_ != 0 && revenueCut_ < FOUR_DECIMALS){
179:
180: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
181: }
182:
183: revenueCut_ = revenueCut_ / FOUR_DECIMALS; // <= FOUND
184:
185: if (fee_ > FIVE_DECIMALS || revenueCut_ > TWO_DECIMALS) {
186: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
187: }
188:
189: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000003) |
190: (fee_ << 2) |
191: (revenueCut_ << 19);
192:
193: emit LogUpdateFeeAndRevenueCut(fee_, revenueCut_ * FOUR_DECIMALS);
194: }
['232']
232: function updateThresholdPercent( // <= FOUND
233: uint upperThresholdPercent_,
234: uint lowerThresholdPercent_,
235: uint thresholdShiftTime_,
236: uint shiftTime_
237: ) public _check _onlyDelegateCall {
238: uint dexVariables2_ = dexVariables2;
239:
240:
241:
242: upperThresholdPercent_ = upperThresholdPercent_ / THREE_DECIMALS; // <= FOUND
243: lowerThresholdPercent_ = lowerThresholdPercent_ / THREE_DECIMALS;
244: if (
245: (upperThresholdPercent_ > THREE_DECIMALS) ||
246: (lowerThresholdPercent_ > THREE_DECIMALS) ||
247: (thresholdShiftTime_ == 0) ||
248: (thresholdShiftTime_ > X24) ||
249: (upperThresholdPercent_ == 0) ||
250: (lowerThresholdPercent_ == 0) ||
251: (shiftTime_ > X20) ||
252: (((dexVariables2_ >> 67) & 1) == 1)
253: ) {
254: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
255: }
256:
257: dexVariables2 = (dexVariables2_ & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000007FFFFFFFFFFFFFFFF) |
258: (uint((shiftTime_ > 0) ? 1 : 0) << 67) |
259: (upperThresholdPercent_ << 68) |
260: (lowerThresholdPercent_ << 78) |
261: (thresholdShiftTime_ << 88);
262:
263: uint oldUpperThresholdPercent_ = (dexVariables2_ >> 68) & X10;
264: uint oldLowerThresholdPercent_ = (dexVariables2_ >> 78) & X10;
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24;
266:
267: if (shiftTime_ > 0) {
268: _thresholdShift = uint128(oldUpperThresholdPercent_ |
269: (oldLowerThresholdPercent_ << 20) |
270: (shiftTime_ << 40) |
271: (block.timestamp << 60) |
272: (oldThresholdTime_ << 93));
273: }
274:
275:
276: emit LogUpdateThresholdPercent(upperThresholdPercent_ * THREE_DECIMALS, lowerThresholdPercent_ * THREE_DECIMALS, thresholdShiftTime_, shiftTime_);
277: }
['352']
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall { // <= FOUND
353: if((token0UtilizationLimit_ != 0 && token0UtilizationLimit_ < THREE_DECIMALS) || (token1UtilizationLimit_ != 0 && token1UtilizationLimit_ < THREE_DECIMALS)){
354:
355: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
356: }
357:
358: token0UtilizationLimit_ = token0UtilizationLimit_ / THREE_DECIMALS; // <= FOUND
359: token1UtilizationLimit_ = token1UtilizationLimit_ / THREE_DECIMALS;
360:
361: if (token0UtilizationLimit_ > THREE_DECIMALS || token1UtilizationLimit_ > THREE_DECIMALS) {
362: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
363: }
364:
365: dexVariables2 = (dexVariables2 & 0xFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
366: (token0UtilizationLimit_ << 228) |
367: (token1UtilizationLimit_ << 238);
368:
369: emit LogUpdateUtilizationLimit(token0UtilizationLimit_ * THREE_DECIMALS, token1UtilizationLimit_ * THREE_DECIMALS);
370: }
['431']
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall { // <= FOUND
432: _checkIsContract(user_);
433:
434:
435: uint256 userSupplyData_ = _userSupplyData[user_];
436: if (userSupplyData_ == 0) {
437: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
438: }
439:
440:
441: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
442: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
443:
444:
445: uint256 maxExpansionLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;
446: maxExpansionLimit_ = userSupply_ - ((userSupply_ * maxExpansionLimit_) / FOUR_DECIMALS);
447:
448: if (newLimit_ == 0 || newLimit_ < maxExpansionLimit_) {
449:
450:
451:
452:
453:
454: newLimit_ = maxExpansionLimit_; // <= FOUND
455: } else if (newLimit_ == type(uint256).max || newLimit_ > userSupply_) {
456:
457: newLimit_ = userSupply_; // <= FOUND
458: }
459:
460:
461:
462:
463: uint256 baseLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;
464: baseLimit_ = (baseLimit_ >> DEFAULT_EXPONENT_SIZE) << (baseLimit_ & DEFAULT_EXPONENT_MASK);
465: if (userSupply_ < baseLimit_) {
466: newLimit_ = 0; // <= FOUND
467:
468:
469:
470: }
471:
472:
473: _userSupplyData[user_] =
474:
475: (userSupplyData_ & 0xFFFFFFFFFFFFFFFFFFFFFFFC000000000000000000000001FFFFFFFFFFFFFFFF) |
476: (newLimit_.toBigNumber(DEFAULT_COEFFICIENT_SIZE, DEFAULT_EXPONENT_SIZE, BigMathMinified.ROUND_DOWN) <<
477: DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) |
478: (block.timestamp << DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP);
479:
480: emit LogUpdateUserWithdrawalLimit(user_, newLimit_);
481: }
The used OpenZeppelin version has known vulnerabilities. Please see: https(colon)//security(dot)snyk(dot)io/package/npm/@openzeppelin%2Fcontracts for more details
Num of instances: 1
Click to show findings
['1']
1: {
2: "name": "instadapp-fluidity-contracts",
3: "version": "1.0.0",
4: "description": "",
5: "main": "index.js",
6: "scripts": {
7: "build": "npm run clean && npm run compile",
8: "clean": "npx hardhat clean",
9: "compile": "npx hardhat compile",
10: "test": "npx hardhat test",
11: "forge-test-getRatioAtTick": "npx ts-node test/js-scripts/getRatioAtTick.ts",
12: "forge-test-getRatioAtTick-precision": "npx ts-node test/js-scripts/getRatioAtTick-precision.ts",
13: "forge-test-getTickAtRatio": "npx ts-node test/js-scripts/getTickAtRatio.ts",
14: "forge-test-bigMathVault-mulDivNormal": "npx ts-node test/js-scripts/bigMathVault/mulDivNormal.ts",
15: "forge-test-bigMathVault-mulDivBigNumber": "npx ts-node test/js-scripts/bigMathVault/mulDivBigNumber.ts",
16: "forge-test-bigMathVault-mulBigNumber": "npx ts-node test/js-scripts/bigMathVault/mulBigNumber.ts",
17: "forge-test-bigMathVault-divBigNumber": "npx ts-node test/js-scripts/bigMathVault/divBigNumber.ts"
18: },
19: "repository": {
20: "type": "git",
21: "url": "git+https://github.com/instadapp/fluid-contracts-public/issues"
22: },
23: "author": {
24: "name": "INSTADAPP LABS LLC",
25: "email": "info@instadapp.io"
26: },
27: "license": "MIT",
28: "bugs": {
29: "url": "https://github.com/instadapp/fluid-contracts-public/issues"
30: },
31: "devDependencies": {
32: "@ethersproject/providers": "5.7.2",
33: "@nomicfoundation/hardhat-chai-matchers": "1.0.5",
34: "@nomicfoundation/hardhat-foundry": "1.1.1",
35: "@nomicfoundation/hardhat-network-helpers": "1.0.7",
36: "@nomicfoundation/hardhat-toolbox": "2.0.0",
37: "@nomicfoundation/hardhat-verify": "1.1.0",
38: "@nomiclabs/hardhat-ethers": "2.2.1",
39: "@nomiclabs/hardhat-etherscan": "3.1.3",
40: "@typechain/ethers-v5": "10.2.0",
41: "@typechain/hardhat": "6.1.5",
42: "@types/mocha": "~9.1.1",
43: "chai": "~4.3.7",
44: "chalk": "~4.1.2",
45: "decimal.js": "~10.2.1",
46: "dotenv": "~16.0.3",
47: "ethers": "5.7.2",
48: "folder-hash": "~4.0.4",
49: "hardhat": "2.17.3",
50: "hardhat-contract-sizer": "2.10.0",
51: "hardhat-deploy": "0.11.22",
52: "hardhat-gas-reporter": "1.0.9",
53: "prettier": "2.8.2",
54: "prettier-plugin-solidity": "1.1.1",
55: "solidity-coverage": "0.8.2",
56: "solidity-docgen": "0.6.0-beta.36",
57: "ts-node": "10.9.1",
58: "typechain": "8.1.1",
59: "typescript": "4.9.4"
60: },
61: "dependencies": {
62: "@openzeppelin/contracts": "4.8.2", // <= FOUND
63: "@openzeppelin/contracts-upgradeable": "4.8.2",
64: "solmate": "6.2.0"
65: }
66: }
67:
In Solidity, the try-catch
statement is used for handling exceptions in external function calls and contract creation. However, when a try-catch
block doesn't include a catch for specific human-readable errors (using catch Error(string memory reason)
), it can miss catching exceptions that provide explanatory error messages. This lack of detailed error handling could hinder debugging and obscure the reasons behind transaction failures. To address this, it's recommended to include a catch block specifically for Error
to capture and handle these descriptive error messages effectively. This practice enhances the contract's robustness by providing clearer insights into why certain operations fail, thereby improving maintainability and troubleshooting.
Num of instances: 1
To ensure accuracy in comparisons within programming, especially when dealing with integers, it's often more efficient to use multiplication rather than division. This approach stems from the fact that division operations are generally slower and more complex than multiplication. And in the context of solidity they can cause precision errors.
Suppose you want to compare if a/b is greater than c/d (where a, b, c, and d are integers). Instead of performing division, which is prone to precision errors, you can cross-multiply to avoid division. The comparison a/b > c/d is equivalent to ad > bc. This way, you only use multiplication, which is faster and avoids potential inaccuracies or complexities associated with division.
Num of instances: 14
Click to show findings
['27']
27: if (((token0Reserves_) < (token1Reserves_ * 1e27 / (centerPrice_ * minLiquidity_)))) {
['34']
34: if (((token1Reserves_) < (token0Reserves_ * centerPrice_ / (1e27 * minLiquidity_)))) {
['54']
54:
55:
56:
57: if (amt_ < (totalAmt_ / NINE_DECIMALS) || amt_ > (totalAmt_ * NINE_DECIMALS)) {
['276']
276: } else if (lastStoredPrice_ < (centerPrice_ - (centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_) / THREE_DECIMALS)) {
['744']
744:
745:
746:
747:
748: if (
749: (amtToSwap_ > ((c_ * SIX_DECIMALS - 1) / SIX_DECIMALS)) ||
750: (amtToSwap_ < (c_ / SIX_DECIMALS))
751: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndDepositTooLowOrTooHigh);
['859']
859:
860:
861:
862:
863: if (
864: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
865: tokenAxa_ < (g_ / SIX_DECIMALS)
866: ) revert FluidDexError(ErrorTypes.DexT1__WithdrawAndSwapTooLowOrTooHigh);
['933']
933:
934:
935:
936:
937: if (
938: tokenAxa_ > ((g_ * SIX_DECIMALS - 1) / SIX_DECIMALS) ||
939: tokenAxa_ < (g_ / SIX_DECIMALS)
940: ) revert FluidDexError(ErrorTypes.DexT1__BorrowAndSwapTooLowOrTooHigh);
['1102']
1102:
1103:
1104:
1105:
1106: if (
1107: (amtToSwap_ > (g_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS) ||
1108: (amtToSwap_ < (g_ / SIX_DECIMALS))
1109: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
['1263']
1263:
1264: if (
1265: (centerPrice_ < ((EIGHT_DECIMALS - 1) * temp_ / EIGHT_DECIMALS)) ||
1266: (centerPrice_ > ((EIGHT_DECIMALS + 1) * temp_ / EIGHT_DECIMALS))
1267: ) {
['61']
61:
62: if (amt_ > (totalAmt_ * 9999 / FOUR_DECIMALS)) {
['160']
160:
161:
162:
163:
164:
165: if (
166: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
167: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
['373']
373:
374:
375:
376:
377:
378: if (
379: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
380: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
['265']
265:
266: if (lastStoredPrice_ > (centerPrice_ + (upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_) / THREE_DECIMALS)) {
['1018']
1018:
1019:
1020:
1021:
1022: if (
1023: (tokenAmt_ > (c_ * (SIX_DECIMALS - 1)) / SIX_DECIMALS)
1024: ) revert FluidDexError(ErrorTypes.DexT1__SwapAndPaybackTooLowOrTooHigh);
Low decimal places in token contracts can lead to increased rounding errors, affecting financial calculations and user balances. When a token has fewer decimal places, operations like division or percentage calculations become less precise, potentially resulting in significant discrepancies over many transactions. This imprecision can harm user trust and contract functionality, especially in DeFi applications where accurate calculations are critical. Using a higher number of decimals, like the standard 18 for ERC-20 tokens, helps ensure finer granularity and more accurate results in token transfers and calculations, maintaining the integrity and reliability of the contract.
Num of instances: 1
Sensitive setter functions in smart contracts often alter critical state variables. Without events emitted in these functions, external observers or dApps cannot easily track or react to these state changes. Missing events can obscure contract activity, hampering transparency and making integration more challenging. To resolve this, incorporate appropriate event emissions within these functions. Events offer an efficient way to log crucial changes, aiding in real-time tracking and post-transaction verification.
Num of instances: 2
Click to show findings
['1145']
1145: function _updateOracle(
1146: uint newPrice_,
1147: uint centerPrice_,
1148: uint dexVariables_
1149: ) internal returns (uint)
['1145']
1145: function _updateOracle( // <= FOUND
1146: uint newPrice_,
1147: uint centerPrice_,
1148: uint dexVariables_
1149: ) internal returns (uint) {
1150:
1151: uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);
1152:
1153: uint temp_;
1154: uint temp2_;
1155: uint temp3_;
1156:
1157: if (timeDiff_ > 0) {
1158:
1159:
1160:
1161: temp_ = (dexVariables_ >> 1) & X40;
1162: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1163:
1164:
1165: temp2_ = (dexVariables_ >> 41) & X40;
1166: temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);
1167:
1168:
1169:
1170: int priceDiff_ = int(ORACLE_PRECISION) - int((temp2_ * ORACLE_PRECISION) / newPrice_);
1171:
1172: if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {
1173:
1174:
1175:
1176:
1177: revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);
1178: }
1179:
1180:
1181: priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);
1182:
1183:
1184:
1185: if (priceDiff_ < 0) {
1186: temp3_ = (uint(-priceDiff_) * X22 / ORACLE_LIMIT) << 1;
1187: } else {
1188:
1189: temp3_ = ((uint(priceDiff_) * X22 / ORACLE_LIMIT) << 1) | 1;
1190: }
1191:
1192: if (timeDiff_ > X22) {
1193:
1194:
1195: timeDiff_ = X22;
1196: }
1197:
1198:
1199: temp_ = (dexVariables_ >> 154) & X22;
1200: uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);
1201: uint oracleMap_ = (dexVariables_ >> 179) & X16;
1202: if (temp_ > X9) {
1203: if (nextOracleSlot_ > 0) {
1204:
1205:
1206: temp3_ = (temp3_ << 41) | (temp_ << 9);
1207: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));
1208: if (nextOracleSlot_ > 0) {
1209: --nextOracleSlot_;
1210: } else {
1211:
1212: nextOracleSlot_ = 7;
1213: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1214: _oracle[oracleMap_] = 0;
1215: }
1216: } else {
1217:
1218:
1219:
1220:
1221: temp3_ = temp3_ << 9;
1222: _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;
1223: nextOracleSlot_ = 6;
1224: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1225:
1226: _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);
1227: }
1228: } else {
1229: temp3_ = (temp3_ << 9) | temp_;
1230: if (nextOracleSlot_ < 7) {
1231: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));
1232: } else {
1233: _oracle[oracleMap_] = temp3_ << ((7 * 32));
1234: }
1235: if (nextOracleSlot_ > 0) {
1236: --nextOracleSlot_;
1237: } else {
1238: nextOracleSlot_ = 7;
1239: oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;
1240: }
1241: }
1242:
1243:
1244: temp_ = newPrice_;
1245: temp2_ = centerPrice_;
1246: temp3_ = dexVariables_;
1247:
1248:
1249: temp3_ = (temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |
1250: (((temp3_ >> 41) & X40) << 1) |
1251: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |
1252: (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |
1253: (block.timestamp << 121) |
1254: (timeDiff_ << 154) |
1255: (nextOracleSlot_ << 176) |
1256: (oracleMap_ << 179);
1257: } else {
1258:
1259: temp_ = (dexVariables_ >> 81) & X40;
1260: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1261:
1262:
1263: if (
1264: (centerPrice_ < ((EIGHT_DECIMALS - 1) * temp_ / EIGHT_DECIMALS)) ||
1265: (centerPrice_ > ((EIGHT_DECIMALS + 1) * temp_ / EIGHT_DECIMALS))
1266: ) {
1267: revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);
1268: }
1269:
1270:
1271: temp_ = (dexVariables_ >> 1) & X40;
1272: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1273:
1274:
1275:
1276: int priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / newPrice_);
1277:
1278: if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {
1279:
1280:
1281:
1282:
1283: revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);
1284: }
1285:
1286:
1287: temp_ = newPrice_;
1288: temp3_ = dexVariables_;
1289:
1290: temp3_ = (temp3_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |
1291: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41);
1292: }
1293:
1294: return temp3_;
1295: }
Num of instances: 4
Click to show findings
['315']
315: function updateHookAddress(uint hookAddress_) public _check _onlyDelegateCall { // <= FOUND
316: if (hookAddress_ > X30) {
317: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
318: }
319:
320: if (hookAddress_ > 0) {
321: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView(); // <= FOUND
322: address hook_ = AddressCalcs.addressCalc(c_.deployerContract, hookAddress_);
323: _checkIsContract(hook_);
324: }
325:
326: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFF00000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
327: (hookAddress_ << 142);
328:
329: emit LogUpdateHookAddress(hookAddress_);
330: }
['282']
282: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall { // <= FOUND
283: if (
284: (centerPriceAddress_ > X30) ||
285: (percent_ == 0) ||
286: (percent_ > X20) ||
287: (time_ == 0) ||
288: (time_ > X20)
289: ) {
290: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow);
291: }
292:
293: if (centerPriceAddress_ > 0) {
294: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView(); // <= FOUND
295: address centerPrice_ = AddressCalcs.addressCalc(c_.deployerContract, centerPriceAddress_);
296: _checkIsContract(centerPrice_);
297:
298: dexVariables2 = (dexVariables2 & 0xFeFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
299: (centerPriceAddress_ << 112) |
300: uint(1) << 248;
301:
302: _centerPriceShift = block.timestamp | (percent_ << 33) | (time_ << 53);
303: } else {
304: dexVariables2 = (dexVariables2 & 0xFeFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF);
305:
306: _centerPriceShift = 0;
307: }
308:
309: emit LogUpdateCenterPriceAddress(centerPriceAddress_, percent_, time_);
310: }
['145']
145: function _turnOnSmartDebt( // <= FOUND
146: uint token0Amt_,
147: uint centerPrice_
148: ) internal {
149: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView(); // <= FOUND
150: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
151:
152: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision;
153:
154: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
155:
156: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
157:
158: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
159:
160: liquidity_.operate(c_.token0, 0, int(token0Amt_), address(0), TEAM_MULTISIG, new bytes(0));
161: liquidity_.operate(c_.token1, 0, int(token1Amt_), address(0), TEAM_MULTISIG, new bytes(0));
162:
163:
164:
165:
166: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
167:
168: if (_totalBorrowShares < NINE_DECIMALS) {
169: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
170: }
171: }
['76']
76: function _turnOnSmartCol( // <= FOUND
77: uint token0Amt_,
78: uint centerPrice_
79: ) internal {
80: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView(); // <= FOUND
81: IFluidDexT1.ConstantViews2 memory c2_ = IFluidDexT1(address(this)).constantsView2();
82:
83: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision;
84:
85: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27;
86:
87: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision;
88:
89: IFluidLiquidity liquidity_ = IFluidLiquidity(c_.liquidity);
90:
91: address token_;
92: uint amt_;
93: for (uint i = 0; i < 2; i++) {
94: if (i == 0) {
95: token_ = c_.token0;
96: amt_ = token0Amt_;
97: } else {
98: token_ = c_.token1;
99: amt_ = token1Amt_;
100: }
101: if (token_ == NATIVE_TOKEN) {
102: if (msg.value > amt_) {
103: SafeTransfer.safeTransferNative(msg.sender, msg.value - amt_);
104: } else if (msg.value < amt_) {
105: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams);
106: }
107:
108: liquidity_.operate{ value: amt_ }(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
109: } else {
110:
111: liquidity_.operate(token_, int(amt_), 0, address(0), address(0), abi.encode(msg.sender));
112: }
113: }
114:
115:
116:
117:
118: _totalSupplyShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
119:
120: if (_totalSupplyShares < NINE_DECIMALS) {
121: revert FluidDexError(ErrorTypes.DexT1Admin__UnexpectedPoolState);
122: }
123: }
[Low-22] Common tokens such as WETH9
work differently on chains such a Blast
which isn't taken into account during transfer calls.
There is a difference on chains such as Blast on how WETH9 is implemented. On most chains the WETH9 contract contains handling for the case where src == msg.sender, however on chains such as Blast, Arbitrum and Fantom. This isn’t the case. Failing to take this discrepancy into account can results in the protocol not functioning as intended on these chains which can have drastic results. Particularly in cases where the contract interacts with it’s own WETH allowance through transferFrom calls, in such cases these can fail if the contract fails to approve itself to use it’s WETH balance which normally isn't done as most WETH contracts do not require approval for instances where src is msg.sender.
Num of instances: 1
Click to show findings
['1857']
1857: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external { // <= FOUND
1858: if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity);
1859: if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn);
1860:
1861: if (data_.length == 64) {
1862: (uint amountWithRevenueCut_, address from_) = abi.decode(data_, (uint, address));
1863:
1864: SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountWithRevenueCut_); // <= FOUND
1865: } else {
1866: SafeTransfer.safeTransferFrom(token_, abi.decode(data_, (address)), address(LIQUIDITY), amount_);
1867: }
1868: }
In L2 deployments, incorporating an uptime feed is crucial to mitigate issues arising from sequencer downtime. Downtime can disrupt services, leading to transaction failures or incorrect data readings, affecting overall system reliability. By integrating an uptime feed, you gain insight into the operational status of the L2 network, enabling proactive measures like halting sensitive operations or alerting users. This approach ensures that your contract behaves predictably and securely during network outages, enhancing the robustness and reliability of your decentralized application, which is especially important in mission-critical or high-stakes environments.
Num of instances: 10
Click to show findings
['15']
15: contract FluidDexT1 is Helpers // <= FOUND
['21']
21: contract FluidDexT1Admin is ConstantVariables, Variables, Structs, Events, Error // <= FOUND
['19']
19: abstract contract Helpers is Variables, ImmutableVariables, Events // <= FOUND
['4']
4: abstract contract Structs // <= FOUND
['11']
11: abstract contract ImmutableVariables is ConstantVariables, Structs, Error // <= FOUND
['10']
10: abstract contract ConstantVariables is StorageRead // <= FOUND
['4']
4: abstract contract Events // <= FOUND
['4']
4: abstract contract Variables // <= FOUND
['4']
4: abstract contract Structs // <= FOUND
['6']
6: abstract contract Events is Structs // <= FOUND
Num of instances: 9
Click to show findings
['543']
543: // <= FOUND
544: // <= FOUND
545: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['544']
544: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1; // <= FOUND
['543']
543: // <= FOUND
544: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['1005']
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1011']
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1192']
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1198']
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1695']
1695: // <= FOUND
1696: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['1717']
1717: // <= FOUND
1718: // <= FOUND
1719: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1; // <= FOUND
Within unchecked blocks in Solidity, arithmetic operations bypass overflow and underflow checks. When subtractions occur without proper bounds validation, they may underflow. An underflow in an unsigned integer subtraction can wrap the value around to its maximum, leading to unintended contract behavior or potential vulnerabilities. To prevent such scenarios, developers should either avoid unchecked blocks for subtraction operations or manually implement checks to ensure operands' validity before subtraction.
Num of instances: 2
Click to show findings
['494']
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
['174']
174: unchecked {
175: oldCenterPrice_ = oldCenterPrice_ > priceShift_ ? oldCenterPrice_ - priceShift_ : 0;
176:
177:
178:
179:
180: }
Num of instances: 1
Click to show findings
['15']
15: address internal constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e; // <= FOUND
Num of instances: 6
Click to show findings
['153']
153: uint time_ = (centerPriceShift_ >> 53) & X20; // <= FOUND
['116']
116: uint oldThresholdTime_ = (thresholdShift_ >> 93) & X24;
['259']
259: uint shiftingTime_ = (dexVariables2_ >> 88) & X24;
['265']
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24;
['84']
84: uint shiftDuration_ = (rangeShift_ >> 40) & X20;
['114']
114: uint shiftDuration_ = (thresholdShift_ >> 40) & X20;
Num of instances: 2
Click to show findings
['546']
546: function pauseUser(
547: address user_,
548: bool pauseSupply_,
549: bool pauseBorrow_
550: ) public _onlyDelegateCall {
551: _checkIsContract(user_);
552:
553: uint256 userData_;
554:
555: if (pauseSupply_) {
556:
557: userData_ = _userSupplyData[user_];
558: if (userData_ == 0) {
559: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
560: }
561: if (userData_ & 1 == 0) {
562: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle);
563: }
564:
565: _userSupplyData[user_] = userData_ & (~uint(1)); // <= FOUND
566: }
567:
568: if (pauseBorrow_) {
569:
570: userData_ = _userBorrowData[user_];
571: if (userData_ == 0) {
572: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
573: }
574: if (userData_ & 1 == 0) {
575: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle);
576: }
577:
578: _userBorrowData[user_] = userData_ & (~uint(1));
579: }
580:
581: emit LogPauseUser(user_, pauseSupply_, pauseBorrow_);
582: }
['584']
584: function unpauseUser(
585: address user_,
586: bool unpauseSupply_,
587: bool unpauseBorrow_
588: ) public _onlyDelegateCall {
589: _checkIsContract(user_);
590:
591: uint256 userData_;
592:
593: if (unpauseSupply_) {
594:
595: userData_ = _userSupplyData[user_];
596: if (userData_ == 0) {
597: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
598: }
599: if (userData_ & 1 == 1) {
600: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle);
601: }
602:
603:
604: _userSupplyData[user_] = userData_ | 1; // <= FOUND
605: }
606:
607: if (unpauseBorrow_) {
608:
609: userData_ = _userBorrowData[user_];
610: if (userData_ == 0) {
611: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined);
612: }
613: if (userData_ & 1 == 1) {
614: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle);
615: }
616:
617:
618: _userBorrowData[user_] = userData_ | 1;
619: }
620:
621: emit LogUnpauseUser(user_, unpauseSupply_, unpauseBorrow_);
622: }
[NonCritical-5] Address function parameter is compared against a state variable. This check can be bypassed for tokens with multiple addresses (proxy tokens)
Comparing an address function parameter directly against a state variable can be problematic, especially for proxy tokens or tokens with multiple addresses. Proxy tokens often use a fixed proxy address with a separate implementation contract address. If a function relies solely on comparing the caller's address with a state variable, it might fail to recognize legitimate calls from a token's proxy address. This oversight can lead to bypassing security checks, as the actual implementation logic resides elsewhere. To address this, consider verifying against the token's intended logic, such as using a designated interface or an authorized registry, ensuring all valid instances are accounted for.
Num of instances: 1
Click to show findings
['48']
48: function _checkIsContractOrNativeAddress(address value_) internal view { // <= FOUND
49: if (value_.code.length == 0 && value_ != NATIVE_TOKEN) { // <= FOUND
50: revert FluidDexError(ErrorTypes.DexT1Admin__AddressNotAContract);
51: }
52: }
It is general standard to declare interfaces on files separate from regular contract declarations
Num of instances: 1
[NonCritical-7] Events regarding state variable changes should emit the previous state variable value
Modify such events to contain the previous value of the state variable as demonstrated in the example below
Num of instances: 8
Click to show findings
['24']
24: event LogUpdateRangePercents(uint upperPercent, uint lowerPercent, uint shiftTime);
['42']
42: event LogUpdateCenterPriceAddress(uint centerPriceAddress, uint percent, uint time);
['46']
46: event LogUpdateHookAddress(uint hookAddress);
['51']
51: event LogUpdateCenterPriceLimits(uint maxCenterPrice, uint minCenterPrice);
['56']
56: event LogUpdateUtilizationLimit(uint token0UtilizationLimit, uint token1UtilizationLimit);
['60']
60: event LogUpdateUserSupplyConfigs(UserSupplyConfig[] userSupplyConfigs);
['64']
64: event LogUpdateUserBorrowConfigs(UserBorrowConfig[] userBorrowConfigs);
['123']
123: event LogUpdateUserWithdrawalLimit(address user, uint256 newLimit);
[NonCritical-8] In functions which accept an address as a parameter, there should be a zero address check to prevent bugs
In smart contract development, especially with Solidity, it's crucial to validate inputs to functions. When a function accepts an Ethereum address as a parameter, implementing a zero address check (i.e., ensuring the address is not 0x0
) is a best practice to prevent potential bugs and vulnerabilities. The zero address (0x0
) is a default value and generally indicates an uninitialized or invalid state. Passing the zero address to certain functions can lead to unintended behaviors, like funds getting locked permanently or transactions failing silently. By checking for and rejecting the zero address, developers can ensure that the function operates as intended and interacts only with valid Ethereum addresses. This check enhances the contract's robustness and security.
Num of instances: 10
Click to show findings
['1857']
1857: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external
['2077']
2077: function _spell(address target_, bytes memory data_) private returns (bytes memory response_)
['1125']
1125: function _depositOrPaybackInLiquidity(address token_, uint depositAmt_, uint paybackAmt_) internal
['76']
76: function _calcNumeratorAndDenominator(address token_) private view returns (uint256 numerator_, uint256 denominator_)
['78']
78: function _decimals(address token_) internal view returns (uint256)
['48']
48: function _checkIsContractOrNativeAddress(address value_) internal view
['55']
55: function _checkIsContract(address value_) internal view
['431']
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall
['546']
546: function pauseUser(
547: address user_,
548: bool pauseSupply_,
549: bool pauseBorrow_
550: ) public _onlyDelegateCall
['584']
584: function unpauseUser(
585: address user_,
586: bool unpauseSupply_,
587: bool unpauseBorrow_
588: ) public _onlyDelegateCall
Create a commented enum value to use in place of constant array indexes, this makes the code far easier to understand
Num of instances: 1
In instances where a new variable is defined, there is no need to set it to it's default value.
Num of instances: 1
[NonCritical-11] Revert statements within external and public functions can be used to perform DOS attacks
In Solidity, 'revert' statements are used to undo changes and throw an exception when certain conditions are not met. However, in public and external functions, improper use of revert
can be exploited for Denial of Service (DoS) attacks. An attacker can intentionally trigger these 'revert' conditions, causing legitimate transactions to consistently fail. For example, if a function relies on specific conditions from user input or contract state, an attacker could manipulate these to continually force reverts, blocking the function's execution. Therefore, it's crucial to design contract logic to handle exceptions properly and avoid scenarios where revert
can be predictably triggered by malicious actors. This includes careful input validation and considering alternative design patterns that are less susceptible to such abuses.
Num of instances: 32
Click to show findings
['1857']
1857: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external {
1858: if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity); // <= FOUND
1859: if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn); // <= FOUND
1860:
1861: if (data_.length == 64) {
1862: (uint amountWithRevenueCut_, address from_) = abi.decode(data_, (uint, address));
1863:
1864: SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountWithRevenueCut_);
1865: } else {
1866: SafeTransfer.safeTransferFrom(token_, abi.decode(data_, (address)), address(LIQUIDITY), amount_);
1867: }
1868: }
['1878']
1878: function oraclePrice(
1879: uint[] memory secondsAgos_
1880: ) external view returns (
1881: Oracle[] memory twaps_,
1882: uint currentPrice_
1883: ) {
1884: OraclePriceMemory memory o_;
1885:
1886: uint dexVariables_ = dexVariables;
1887: twaps_ = new Oracle[](secondsAgos_.length);
1888:
1889: uint totalTime_;
1890: uint time_;
1891:
1892: uint i;
1893: uint secondsAgo_ = secondsAgos_[0];
1894:
1895: currentPrice_ = (dexVariables_ >> 41) & X40;
1896: currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);
1897: uint price_ = currentPrice_;
1898: o_.lowestPrice1by0 = currentPrice_;
1899: o_.highestPrice1by0 = currentPrice_;
1900:
1901: uint twap1by0_;
1902: uint twap0by1_;
1903:
1904: uint j;
1905:
1906: o_.oracleSlot = (dexVariables_ >> 176) & X3;
1907: o_.oracleMap = (dexVariables_ >> 179) & X16;
1908:
1909: o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;
1910:
1911: uint slotData_;
1912: uint percentDiff_;
1913:
1914: if (((dexVariables_ >> 121) & X33) < block.timestamp) {
1915:
1916:
1917: time_ = block.timestamp - ((dexVariables_ >> 121) & X33);
1918: } else {
1919:
1920: ++j;
1921: }
1922:
1923: while (true) {
1924: if (j == 2) {
1925: if (++o_.oracleSlot == 8) {
1926: o_.oracleSlot = 0;
1927: if (o_.oracleMap == 0) {
1928: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1929: }
1930: o_.oracle = _oracle[--o_.oracleMap];
1931: }
1932:
1933: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1934: if (slotData_ > 0) {
1935: time_ = slotData_ & X9;
1936: if (time_ == 0) {
1937:
1938: time_ = slotData_ >> 9;
1939:
1940: if (o_.oracleSlot == 7) {
1941: o_.oracleSlot = 0;
1942: if (o_.oracleMap == 0) {
1943: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1944: }
1945: o_.oracle = _oracle[--o_.oracleMap];
1946: slotData_ = o_.oracle & X32;
1947: } else {
1948: ++o_.oracleSlot;
1949: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1950: }
1951: }
1952: percentDiff_ = slotData_ >> 10;
1953: percentDiff_ = ORACLE_LIMIT * percentDiff_ / X22;
1954: if (((slotData_ >> 9) & 1 == 1)) {
1955:
1956: price_ = price_ - price_ * percentDiff_ / ORACLE_PRECISION;
1957: } else {
1958:
1959: price_ = price_ + price_ * percentDiff_ / ORACLE_PRECISION;
1960: }
1961: } else {
1962:
1963: revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData); // <= FOUND
1964: }
1965: } else if (j == 1) {
1966:
1967: price_ = (dexVariables_ >> 1) & X40;
1968: price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);
1969: time_ = (dexVariables_ >> 154) & X22;
1970: ++j;
1971: } else if (j == 0) {
1972: ++j;
1973: }
1974:
1975: totalTime_ += time_;
1976: if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;
1977: if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;
1978: if (totalTime_ < secondsAgo_) {
1979: twap1by0_ += price_ * time_;
1980: twap0by1_ += (1e54 / price_) * time_;
1981: } else {
1982: time_ = time_ + secondsAgo_ - totalTime_;
1983: twap1by0_ += price_ * time_;
1984: twap0by1_ += (1e54 / price_) * time_;
1985:
1986: twap1by0_ = twap1by0_ / secondsAgo_;
1987: twap0by1_ = twap0by1_ / secondsAgo_;
1988:
1989: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
1990:
1991:
1992: o_.lowestPrice1by0 = price_;
1993: o_.highestPrice1by0 = price_;
1994:
1995: while (++i < secondsAgos_.length) {
1996:
1997: time_ = totalTime_ - secondsAgo_;
1998:
1999: totalTime_ = time_;
2000:
2001: secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];
2002: if (totalTime_ < secondsAgo_) {
2003: twap1by0_ = price_ * time_;
2004: twap0by1_ = (1e54 / price_) * time_;
2005:
2006: if (time_ == 0) {
2007: o_.lowestPrice1by0 = type(uint).max;
2008: o_.highestPrice1by0 = 0;
2009: }
2010: break;
2011: } else {
2012: time_ = time_ + secondsAgo_ - totalTime_;
2013:
2014: twap1by0_ = price_ * time_;
2015:
2016: twap0by1_ = (1e54 / price_) * time_;
2017: twap1by0_ = twap1by0_ / secondsAgo_;
2018: twap0by1_ = twap0by1_ / secondsAgo_;
2019: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
2020: }
2021: }
2022: if (i == secondsAgos_.length) return (twaps_, currentPrice_);
2023: }
2024: }
2025:
2026: }
['372']
372: function updateUserSupplyConfigs(UserSupplyConfig[] memory userSupplyConfigs_) external _check _onlyDelegateCall {
373: uint256 userSupplyData_;
374:
375: for (uint256 i; i < userSupplyConfigs_.length; ) {
376: _checkIsContract(userSupplyConfigs_[i].user);
377: if (userSupplyConfigs_[i].expandDuration == 0) {
378:
379:
380:
381: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
382: }
383: if (userSupplyConfigs_[i].expandPercent > FOUR_DECIMALS) {
384: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
385: }
386: if (userSupplyConfigs_[i].expandDuration > X24) {
387:
388: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
389: }
390: if (userSupplyConfigs_[i].baseWithdrawalLimit == 0) {
391:
392:
393: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
394: }
395:
396:
397:
398: userSupplyData_ = _userSupplyData[userSupplyConfigs_[i].user];
399:
400:
401: _userSupplyData[userSupplyConfigs_[i].user] =
402:
403: (userSupplyData_ & 0xfffffffffc00000000000003ffffffffffffffffffffffffffffffffffffffff) |
404: (1) |
405: (userSupplyConfigs_[i].expandPercent << DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) |
406: (userSupplyConfigs_[i].expandDuration << DexSlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) |
407:
408: (userSupplyConfigs_[i].baseWithdrawalLimit.toBigNumber(
409: SMALL_COEFFICIENT_SIZE,
410: DEFAULT_EXPONENT_SIZE,
411: BigMathMinified.ROUND_DOWN
412: ) << DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT);
413:
414: unchecked {
415: ++i;
416: }
417: }
418:
419: emit LogUpdateUserSupplyConfigs(userSupplyConfigs_);
420: }
['431']
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall {
432: _checkIsContract(user_);
433:
434:
435: uint256 userSupplyData_ = _userSupplyData[user_];
436: if (userSupplyData_ == 0) {
437: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined); // <= FOUND
438: }
439:
440:
441: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
442: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
443:
444:
445: uint256 maxExpansionLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;
446: maxExpansionLimit_ = userSupply_ - ((userSupply_ * maxExpansionLimit_) / FOUR_DECIMALS);
447:
448: if (newLimit_ == 0 || newLimit_ < maxExpansionLimit_) {
449:
450:
451:
452:
453:
454: newLimit_ = maxExpansionLimit_;
455: } else if (newLimit_ == type(uint256).max || newLimit_ > userSupply_) {
456:
457: newLimit_ = userSupply_;
458: }
459:
460:
461:
462:
463: uint256 baseLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;
464: baseLimit_ = (baseLimit_ >> DEFAULT_EXPONENT_SIZE) << (baseLimit_ & DEFAULT_EXPONENT_MASK);
465: if (userSupply_ < baseLimit_) {
466: newLimit_ = 0;
467:
468:
469:
470: }
471:
472:
473: _userSupplyData[user_] =
474:
475: (userSupplyData_ & 0xFFFFFFFFFFFFFFFFFFFFFFFC000000000000000000000001FFFFFFFFFFFFFFFF) |
476: (newLimit_.toBigNumber(DEFAULT_COEFFICIENT_SIZE, DEFAULT_EXPONENT_SIZE, BigMathMinified.ROUND_DOWN) <<
477: DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) |
478: (block.timestamp << DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP);
479:
480: emit LogUpdateUserWithdrawalLimit(user_, newLimit_);
481: }
['483']
483: function updateUserBorrowConfigs(UserBorrowConfig[] memory userBorrowConfigs_) external _check _onlyDelegateCall {
484: uint256 userBorrowData_;
485:
486: for (uint256 i; i < userBorrowConfigs_.length; ) {
487: _checkIsContract(userBorrowConfigs_[i].user);
488: if (
489:
490: userBorrowConfigs_[i].baseDebtCeiling > userBorrowConfigs_[i].maxDebtCeiling ||
491:
492:
493:
494: userBorrowConfigs_[i].expandDuration == 0
495: ) {
496: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
497: }
498: if (userBorrowConfigs_[i].expandPercent > X14) {
499:
500: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
501: }
502: if (userBorrowConfigs_[i].expandDuration > X24) {
503:
504: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
505: }
506: if (userBorrowConfigs_[i].baseDebtCeiling == 0 || userBorrowConfigs_[i].maxDebtCeiling == 0) {
507:
508:
509: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
510: }
511:
512:
513:
514:
515: userBorrowData_ = _userBorrowData[userBorrowConfigs_[i].user];
516:
517:
518:
519: _userBorrowData[userBorrowConfigs_[i].user] =
520:
521: (userBorrowData_ & 0xfffff0000000000000000003ffffffffffffffffffffffffffffffffffffffff) |
522: (1) |
523: (userBorrowConfigs_[i].expandPercent << DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) |
524: (userBorrowConfigs_[i].expandDuration << DexSlotsLink.BITS_USER_BORROW_EXPAND_DURATION) |
525:
526: (userBorrowConfigs_[i].baseDebtCeiling.toBigNumber(
527: SMALL_COEFFICIENT_SIZE,
528: DEFAULT_EXPONENT_SIZE,
529: BigMathMinified.ROUND_DOWN
530: ) << DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) |
531:
532: (userBorrowConfigs_[i].maxDebtCeiling.toBigNumber(
533: SMALL_COEFFICIENT_SIZE,
534: DEFAULT_EXPONENT_SIZE,
535: BigMathMinified.ROUND_DOWN
536: ) << DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT);
537:
538: unchecked {
539: ++i;
540: }
541: }
542:
543: emit LogUpdateUserBorrowConfigs(userBorrowConfigs_);
544: }
['72']
72: function swapIn(
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_) {
78: uint dexVariables_ = dexVariables;
79: uint dexVariables2_ = dexVariables2;
80:
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused); // <= FOUND
82:
83: _check(dexVariables_, dexVariables2_);
84:
85: if (to_ == address(0)) to_ = msg.sender;
86:
87: SwapInMemory memory s_;
88:
89: if (swap0to1_) {
90: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
91: s_.amtInAdjusted = amountIn_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
92: } else {
93: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
94: s_.amtInAdjusted = amountIn_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
95: }
96:
97: _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);
98:
99: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
100:
101: if (msg.value > 0) {
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch); // <= FOUND
103: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap); // <= FOUND
104: }
105:
106:
107: uint temp_ = dexVariables2_ & 1;
108:
109: uint temp2_ = (dexVariables2_ >> 1) & 1;
110:
111: uint temp3_;
112: uint temp4_;
113:
114:
115: temp3_ = ((dexVariables2_ >> 2) & X17);
116:
117:
118:
119:
120: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
121:
122:
123: s_.fee = SIX_DECIMALS - temp3_;
124:
125: CollateralReservesSwap memory cs_;
126: DebtReservesSwap memory ds_;
127: if (temp_ == 1) {
128:
129: {
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
131: if (swap0to1_) {
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
134: } else {
135: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
137: }
138: }
139: }
140:
141: if (temp2_ == 1) {
142:
143: {
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
145: if (swap0to1_) {
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
148: } else {
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
151: }
152: }
153: }
154:
155:
156:
157:
158:
159:
160: if (
161: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
162: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts); // <= FOUND
163:
164: if (temp_ == 1 && temp2_ == 1) {
165:
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves);
167: }
168:
169:
170:
171:
172:
173:
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
175:
176:
177: temp_ = uint(s_.swapRoutingAmt);
178:
179: temp3_ = s_.amtInAdjusted - temp_;
180:
181: (temp2_, temp4_) = (0, 0);
182:
183:
184: s_.withdrawTo = to_;
185: s_.borrowTo = to_;
186: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {
187:
188: (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);
189:
190: s_.withdrawTo = to_;
191: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
192:
193: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);
194:
195: s_.borrowTo = to_;
196: } else {
197:
198: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute); // <= FOUND
199: }
200:
201: if (temp_ > 0) {
202:
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
204: swap0to1_ ?
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
207: }
208: if (temp3_ > 0) {
209:
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
211: swap0to1_ ?
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
214: }
215:
216:
217: if (temp_ > temp3_) {
218:
219: s_.price = swap0to1_ ?
220: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) :
221: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
222: } else {
223:
224: s_.price = swap0to1_ ?
225: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) :
226: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
227: }
228:
229:
230: if (swap0to1_) {
231: temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
232: temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
233: temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
234: temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
235: } else {
236: temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
237: temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
238: temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
239: temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
240: }
241:
242: amountOut_ = temp2_ + temp4_;
243:
244:
245: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_); // <= FOUND
246:
247: if (amountOut_ < amountOutMin_) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut); // <= FOUND
248:
249:
250: temp_ = (temp_ * s_.revenueCut) / SIX_DECIMALS;
251: temp3_ = (temp3_ * s_.revenueCut) / SIX_DECIMALS;
252:
253: s_.data = abi.encode(amountIn_, msg.sender);
254:
255: LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);
256:
257: LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));
258:
259:
260: temp_ = (dexVariables2_ >> 142) & X30;
261: if (temp_ > 0) {
262: s_.swap0to1 = swap0to1_;
263: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
264: }
265:
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
269:
271: dexVariables = _updateOracle(
272: s_.price,
273: pex_.centerPrice,
274: dexVariables_
275: );
276:
277: emit Swap(swap0to1_, amountIn_, amountOut_, to_);
278: }
['286']
286: function swapOut(
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused); // <= FOUND
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch); // <= FOUND
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap); // <= FOUND
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts); // <= FOUND
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute); // <= FOUND
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_); // <= FOUND
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax); // <= FOUND
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
['511']
511: function depositPerfect(
512: uint shares_,
513: uint maxToken0Deposit_,
514: uint maxToken1Deposit_,
515: bool estimate_
516: ) public payable returns (uint token0Amt_, uint token1Amt_) {
517: uint dexVariables_ = dexVariables;
518: uint dexVariables2_ = dexVariables2;
519:
520: _check(dexVariables_, dexVariables2_);
521:
522: uint userSupplyData_ = _userSupplyData[msg.sender];
523:
524:
525: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn); // <= FOUND
526:
527:
528: if ((dexVariables2_ & 1) == 1) {
529: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
530:
531:
532: uint totalSupplyShares_ = _totalSupplyShares;
533:
534: _verifyMint(shares_, totalSupplyShares_);
535:
536:
537:
538: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
539: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
540:
541:
542:
543: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
544: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
545:
546: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_); // <= FOUND
547:
548: if (token0Amt_ > maxToken0Deposit_ || token1Amt_ > maxToken1Deposit_) {
549: revert FluidDexError(ErrorTypes.DexT1__AboveDepositMax); // <= FOUND
550: }
551:
552: _depositOrPaybackInLiquidity(TOKEN_0, token0Amt_, 0);
553:
554: _depositOrPaybackInLiquidity(TOKEN_1, token1Amt_, 0);
555:
556: uint userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
557:
558: userSupply_ = ((userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK));
559:
560:
561: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
562:
563: userSupply_ += shares_;
564:
565:
566: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
567:
568:
569: _totalSupplyShares = totalSupplyShares_ + shares_;
570: } else {
571: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled); // <= FOUND
572: }
573:
574:
575: dexVariables = dexVariables_;
576:
577: emit LogDepositPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
578: }
['587']
587: function withdrawPerfect(
588: uint shares_,
589: uint minToken0Withdraw_,
590: uint minToken1Withdraw_,
591: bool estimate_
592: ) public returns (uint token0Amt_, uint token1Amt_) {
593: uint dexVariables_ = dexVariables;
594: uint dexVariables2_ = dexVariables2;
595:
596: _check(dexVariables_, dexVariables2_);
597:
598: uint userSupplyData_ = _userSupplyData[msg.sender];
599:
600: if (userSupplyData_ & 1 == 0 && !estimate_) {
601: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn); // <= FOUND
602: }
603:
604:
605: if ((dexVariables2_ & 1) == 1) {
606: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
607:
608: uint totalSupplyShares_ = _totalSupplyShares;
609:
610: _verifyRedeem(shares_, totalSupplyShares_);
611:
612:
613:
614: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
615: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
616:
617:
618: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
619: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
620:
621: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_); // <= FOUND
622:
623: if (token0Amt_ < minToken0Withdraw_ || token1Amt_ < minToken1Withdraw_) {
624: revert FluidDexError(ErrorTypes.DexT1__BelowWithdrawMin); // <= FOUND
625: }
626:
627: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
628: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
629:
630:
631: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
632: userSupply_ -= shares_;
633:
634:
635: if (userSupply_ < newWithdrawalLimit_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached); // <= FOUND
636:
637: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
638:
639: _totalSupplyShares = totalSupplyShares_ - shares_;
640:
641:
642:
643: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0));
644:
645:
646:
647: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
648: } else {
649: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled); // <= FOUND
650: }
651:
652:
653: dexVariables = dexVariables_;
654:
655: emit LogWithdrawPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
656: }
['665']
665: function borrowPerfect(
666: uint shares_,
667: uint minToken0Borrow_,
668: uint minToken1Borrow_,
669: bool estimate_
670: ) public returns (uint token0Amt_, uint token1Amt_) {
671: uint dexVariables_ = dexVariables;
672: uint dexVariables2_ = dexVariables2;
673:
674: _check(dexVariables_, dexVariables2_);
675:
676: uint userBorrowData_ = _userBorrowData[msg.sender];
677:
678:
679: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn); // <= FOUND
680:
681:
682: if (((dexVariables2_ >> 1) & 1) == 1) {
683: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
684:
685: uint totalBorrowShares_ = _totalBorrowShares;
686:
687: _verifyMint(shares_, totalBorrowShares_);
688:
689:
690: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
691: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
692:
693: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
694: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
695:
696: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_); // <= FOUND
697:
698: if (token0Amt_ < minToken0Borrow_ || token1Amt_ < minToken1Borrow_) {
699: revert FluidDexError(ErrorTypes.DexT1__BelowBorrowMin); // <= FOUND
700: }
701:
702:
703: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
704: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
705:
706:
707: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
708:
709: userBorrow_ += shares_;
710:
711:
712: if (userBorrow_ > newBorrowLimit_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached); // <= FOUND
713:
714:
715:
716: LIQUIDITY.operate(TOKEN_0, 0, int(token0Amt_), address(0), msg.sender, new bytes(0));
717:
718:
719:
720: LIQUIDITY.operate(TOKEN_1, 0, int(token1Amt_), address(0), msg.sender, new bytes(0));
721:
722: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
723:
724: _totalBorrowShares = totalBorrowShares_ + shares_;
725: } else {
726: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled); // <= FOUND
727: }
728:
729:
730: dexVariables = dexVariables_;
731:
732: emit LogBorrowPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
733: }
['742']
742: function paybackPerfect(
743: uint shares_,
744: uint maxToken0Payback_,
745: uint maxToken1Payback_,
746: bool estimate_
747: ) public payable returns (uint token0Amt_, uint token1Amt_) {
748: uint dexVariables_ = dexVariables;
749: uint dexVariables2_ = dexVariables2;
750:
751: _check(dexVariables_, dexVariables2_);
752:
753: uint userBorrowData_ = _userBorrowData[msg.sender];
754:
755: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn); // <= FOUND
756:
757:
758: if (((dexVariables2_ >> 1) & 1) == 1) {
759: uint totalBorrowShares_ = _totalBorrowShares;
760:
761: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
762:
763: _verifyRedeem(shares_, totalBorrowShares_);
764:
765:
766: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
767: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
768:
769: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
770: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
771:
772: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_); // <= FOUND
773:
774: if (token0Amt_ > maxToken0Payback_ || token1Amt_ > maxToken1Payback_) {
775: revert FluidDexError(ErrorTypes.DexT1__AbovePaybackMax); // <= FOUND
776: }
777:
778: _depositOrPaybackInLiquidity(TOKEN_0, 0, token0Amt_);
779:
780: _depositOrPaybackInLiquidity(TOKEN_1, 0, token1Amt_);
781:
782:
783: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
784: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
785:
786:
787: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
788:
789: userBorrow_ -= shares_;
790:
791: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
792:
793: _totalBorrowShares = totalBorrowShares_ - shares_;
794: } else {
795: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled); // <= FOUND
796: }
797:
798:
799: dexVariables = dexVariables_;
800:
801: emit LogPaybackPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
802: }
['810']
810: function deposit(
811: uint token0Amt_,
812: uint token1Amt_,
813: uint minSharesAmt_,
814: bool estimate_
815: ) public payable returns (uint shares_) {
816: uint dexVariables_ = dexVariables;
817: uint dexVariables2_ = dexVariables2;
818:
819: _check(dexVariables_, dexVariables2_);
820:
821: uint userSupplyData_ = _userSupplyData[msg.sender];
822:
823: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn); // <= FOUND
824:
825:
826: if ((dexVariables2_ & 1) == 1) {
827: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
828:
829: DepositColMemory memory d_;
830:
831: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
832: CollateralReserves memory c2_ = c_;
833:
834: if (token0Amt_ > 0) {
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
836: _verifySwapAndNonPerfectActions(d_.token0AmtAdjusted, token0Amt_);
837: _verifyMint(d_.token0AmtAdjusted, c_.token0RealReserves);
838: }
839:
840: if (token1Amt_ > 0) {
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
842: _verifySwapAndNonPerfectActions(d_.token1AmtAdjusted, token1Amt_);
843: _verifyMint(d_.token1AmtAdjusted, c_.token1RealReserves);
844: }
845:
846: uint temp_;
847: uint temp2_;
848:
849: uint totalSupplyShares_ = _totalSupplyShares;
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) {
851:
852: shares_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
853: totalSupplyShares_ += shares_;
854: } else if ((d_.token1AmtAdjusted > 0 && d_.token0AmtAdjusted == 0) && (c_.token1RealReserves > 0) && (c_.token0RealReserves == 0)) {
855:
856: shares_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
857: totalSupplyShares_ += shares_;
858: } else {
859: if (d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted > 0) {
860:
861:
862: temp_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
863:
864: temp2_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
865: if (temp_ > temp2_) {
866:
867: shares_ = (temp2_ * totalSupplyShares_) / 1e18;
868:
869: temp_ = ((temp_ - temp2_) * c_.token0RealReserves) / 1e18;
870: temp2_ = 0;
871: } else if (temp2_ > temp_) {
872:
873: shares_ = (temp_ * totalSupplyShares_) / 1e18;
874:
875: temp2_ = ((temp2_ - temp_) * c_.token1RealReserves) / 1e18;
876: temp_ = 0;
877: } else {
878:
879: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts); // <= FOUND
880: }
881:
882:
883: c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, true);
884:
885: totalSupplyShares_ += shares_;
886: } else if (d_.token0AmtAdjusted > 0) {
887: temp_ = d_.token0AmtAdjusted;
888: temp2_ = 0;
889: } else if (d_.token1AmtAdjusted > 0) {
890: temp_ = 0;
891: temp2_ = d_.token1AmtAdjusted;
892: } else {
893:
894: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts); // <= FOUND
895: }
896:
897: if (temp_ > 0) {
898:
899: temp_ = _getSwapAndDeposit(
900: temp_,
901: c2_.token1ImaginaryReserves,
902: c2_.token0ImaginaryReserves,
903: c2_.token0RealReserves,
904: c2_.token1RealReserves
905: );
906: } else if (temp2_ > 0) {
907:
908: temp_ = _getSwapAndDeposit(
909: temp2_,
910: c2_.token0ImaginaryReserves,
911: c2_.token1ImaginaryReserves,
912: c2_.token1RealReserves,
913: c2_.token0RealReserves
914: );
915: } else {
916:
917: revert FluidDexError(ErrorTypes.DexT1__DepositAmtsZero); // <= FOUND
918: }
919:
920:
921: temp_ = temp_ * totalSupplyShares_ / 1e18;
922:
923:
924:
925: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
926:
927: shares_ += temp_;
928:
929: totalSupplyShares_ += temp_;
930: }
931:
932: if (estimate_) revert FluidDexLiquidityOutput(shares_); // <= FOUND
933:
934: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__SharesMintedLess); // <= FOUND
935:
936: if (token0Amt_ > 0) {
937: _verifyToken1Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
938: temp_ = token0Amt_;
939: _depositOrPaybackInLiquidity(TOKEN_0, temp_, 0);
940: }
941:
942: if (token1Amt_ > 0) {
943: _verifyToken0Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
944: temp_ = token1Amt_;
945: _depositOrPaybackInLiquidity(TOKEN_1, temp_, 0);
946: }
947:
948:
949: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
950:
951: temp_ = ((temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK));
952:
953:
954:
955: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
956:
957: temp_ += shares_;
958:
959: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
960:
961:
962: _totalSupplyShares = totalSupplyShares_;
963:
964: emit LogDepositColLiquidity(token0Amt_, token1Amt_, shares_);
965:
966: _arbitrage(dexVariables_, dexVariables2_, pex_);
967: } else {
968: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled); // <= FOUND
969: }
970: }
['978']
978: function withdraw(
979: uint token0Amt_,
980: uint token1Amt_,
981: uint maxSharesAmt_,
982: bool estimate_
983: ) public returns (uint shares_) {
984: uint dexVariables_ = dexVariables;
985: uint dexVariables2_ = dexVariables2;
986:
987: _check(dexVariables_, dexVariables2_);
988:
989: uint userSupplyData_ = _userSupplyData[msg.sender];
990:
991: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn); // <= FOUND
992:
993:
994: if ((dexVariables2_ & 1) == 1) {
995: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
996:
997: WithdrawColMemory memory w_;
998:
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true);
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false);
1001: w_.token0ReservesInitial = token0Reserves_;
1002: w_.token1ReservesInitial = token1Reserves_;
1003:
1004: if (token0Amt_ > 0) {
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1006: _verifySwapAndNonPerfectActions(w_.token0AmtAdjusted, token0Amt_);
1007: _verifyRedeem(w_.token0AmtAdjusted, token0Reserves_);
1008: }
1009:
1010: if (token1Amt_ > 0) {
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1012: _verifySwapAndNonPerfectActions(w_.token1AmtAdjusted, token1Amt_);
1013: _verifyRedeem(w_.token1AmtAdjusted, token1Reserves_);
1014: }
1015:
1016: uint temp_;
1017: uint temp2_;
1018:
1019: uint totalSupplyShares_ = _totalSupplyShares;
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) {
1021:
1022: shares_ = (w_.token0AmtAdjusted * 1e18 / token0Reserves_);
1023: totalSupplyShares_ -= shares_;
1024: } else if ((w_.token1AmtAdjusted > 0 && w_.token0AmtAdjusted == 0) && (token1Reserves_ > 0) && (token0Reserves_ == 0)) {
1025:
1026: shares_ = (w_.token1AmtAdjusted * 1e18 / token1Reserves_);
1027: totalSupplyShares_ -= shares_;
1028: } else {
1029: if (w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted > 0) {
1030:
1031:
1032: temp_ = w_.token0AmtAdjusted * 1e18 / token0Reserves_;
1033:
1034: temp2_ = w_.token1AmtAdjusted * 1e18 / token1Reserves_;
1035: if (temp_ > temp2_) {
1036:
1037: shares_ = ((temp2_ * totalSupplyShares_) / 1e18);
1038:
1039: temp_ = ((temp_ - temp2_) * token0Reserves_) / 1e18;
1040: temp2_ = 0;
1041: } else if (temp2_ > temp_) {
1042:
1043: shares_ = ((temp_ * totalSupplyShares_) / 1e18);
1044:
1045: temp2_ = ((temp2_ - temp_) * token1Reserves_) / 1e18;
1046: temp_ = 0;
1047: } else {
1048:
1049: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts); // <= FOUND
1050: }
1051:
1052:
1053: token0Reserves_ = token0Reserves_ - (token0Reserves_ * shares_ / totalSupplyShares_);
1054: token1Reserves_ = token1Reserves_ - (token1Reserves_ * shares_ / totalSupplyShares_);
1055: totalSupplyShares_ -= shares_;
1056: } else if (w_.token0AmtAdjusted > 0) {
1057: temp_ = w_.token0AmtAdjusted;
1058: temp2_ = 0;
1059: } else if (w_.token1AmtAdjusted > 0) {
1060: temp_ = 0;
1061: temp2_ = w_.token1AmtAdjusted;
1062: } else {
1063:
1064: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero); // <= FOUND
1065: }
1066:
1067: uint token0ImaginaryReservesOutsideRangpex_;
1068: uint token1ImaginaryReservesOutsideRangpex_;
1069:
1070: if (pex_.geometricMean < 1e27) {
1071: (token0ImaginaryReservesOutsideRangpex_, token1ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange(pex_.geometricMean, pex_.upperRange, (token0Reserves_ - temp_), (token1Reserves_ - temp2_));
1072: } else {
1073:
1074:
1075:
1076:
1077: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_));
1078: }
1079:
1080: if (temp_ > 0) {
1081:
1082: temp_ = _getWithdrawAndSwap(
1083: token0Reserves_,
1084: token1Reserves_,
1085: token0ImaginaryReservesOutsideRangpex_,
1086: token1ImaginaryReservesOutsideRangpex_,
1087: temp_
1088: );
1089: } else if (temp2_ > 0) {
1090:
1091: temp_ = _getWithdrawAndSwap(
1092: token1Reserves_,
1093: token0Reserves_,
1094: token1ImaginaryReservesOutsideRangpex_,
1095: token0ImaginaryReservesOutsideRangpex_,
1096: temp2_
1097: );
1098: } else {
1099:
1100: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero); // <= FOUND
1101: }
1102:
1103:
1104: temp_ = (temp_ * totalSupplyShares_ / 1e18);
1105:
1106:
1107: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1108:
1109: shares_ += temp_;
1110:
1111: totalSupplyShares_ -= temp_;
1112: }
1113:
1114: if (estimate_) revert FluidDexLiquidityOutput(shares_); // <= FOUND
1115:
1116: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__WithdrawExcessSharesBurn); // <= FOUND
1117:
1118:
1119: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1120: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1121:
1122:
1123:
1124: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
1125:
1126: temp_ -= shares_;
1127:
1128:
1129: if (temp_ < temp2_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached); // <= FOUND
1130:
1131: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
1132:
1133:
1134: _totalSupplyShares = totalSupplyShares_;
1135:
1136: if (w_.token0AmtAdjusted > 0) {
1137: _verifyToken0Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1138:
1139: temp_ = token0Amt_;
1140: LIQUIDITY.operate(TOKEN_0, -int(temp_), 0, msg.sender, address(0), new bytes(0));
1141: }
1142:
1143: if (w_.token1AmtAdjusted > 0) {
1144: _verifyToken1Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1145:
1146: temp_ = token1Amt_;
1147: LIQUIDITY.operate(TOKEN_1, -int(temp_), 0, msg.sender, address(0), new bytes(0));
1148: }
1149:
1150: emit LogWithdrawColLiquidity(token0Amt_, token1Amt_, shares_);
1151:
1152: _arbitrage(dexVariables_, dexVariables2_, pex_);
1153: } else {
1154: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled); // <= FOUND
1155: }
1156:
1157: }
['1165']
1165: function borrow(
1166: uint token0Amt_,
1167: uint token1Amt_,
1168: uint maxSharesAmt_,
1169: bool estimate_
1170: ) public returns (uint shares_) {
1171: uint dexVariables_ = dexVariables;
1172: uint dexVariables2_ = dexVariables2;
1173:
1174: _check(dexVariables_, dexVariables2_);
1175:
1176: uint userBorrowData_ = _userBorrowData[msg.sender];
1177:
1178: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn); // <= FOUND
1179:
1180:
1181: if (((dexVariables2_ >> 1) & 1) == 1) {
1182: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1183:
1184: BorrowDebtMemory memory b_;
1185:
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true);
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false);
1188: b_.token0DebtInitial = token0Debt_;
1189: b_.token1DebtInitial = token1Debt_;
1190:
1191: if (token0Amt_ > 0) {
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1193: _verifySwapAndNonPerfectActions(b_.token0AmtAdjusted, token0Amt_);
1194: _verifyMint(b_.token0AmtAdjusted, token0Debt_);
1195: }
1196:
1197: if (token1Amt_ > 0) {
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1199: _verifySwapAndNonPerfectActions(b_.token1AmtAdjusted, token1Amt_);
1200: _verifyMint(b_.token1AmtAdjusted, token1Debt_);
1201: }
1202:
1203: uint temp_;
1204: uint temp2_;
1205:
1206: uint totalBorrowShares_ = _totalBorrowShares;
1207: if ((b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted == 0) && (token0Debt_ > 0) && (token1Debt_ == 0)) {
1208:
1209: shares_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1210: totalBorrowShares_ += shares_;
1211: } else if ((b_.token1AmtAdjusted > 0 && b_.token0AmtAdjusted == 0) && (token1Debt_ > 0) && (token0Debt_ == 0)) {
1212:
1213: shares_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1214: totalBorrowShares_ += shares_;
1215: } else {
1216: if (b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted > 0) {
1217:
1218:
1219: temp_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1220:
1221: temp2_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1222: if (temp_ > temp2_) {
1223:
1224: shares_ = (temp2_ * totalBorrowShares_) / 1e18;
1225:
1226: temp_ = ((temp_ - temp2_) * token0Debt_) / 1e18;
1227: temp2_ = 0;
1228: } else if (temp2_ > temp_) {
1229:
1230: shares_ = (temp_ * totalBorrowShares_) / 1e18;
1231:
1232: temp2_ = ((temp2_ - temp_) * token1Debt_) / 1e18;
1233: temp_ = 0;
1234: } else {
1235:
1236: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts); // <= FOUND
1237: }
1238:
1239:
1240: token0Debt_ = token0Debt_ + token0Debt_ * shares_ / totalBorrowShares_;
1241: token1Debt_ = token1Debt_ + token1Debt_ * shares_ / totalBorrowShares_;
1242: totalBorrowShares_ += shares_;
1243: } else if (b_.token0AmtAdjusted > 0) {
1244: temp_ = b_.token0AmtAdjusted;
1245: temp2_ = 0;
1246: } else if (b_.token1AmtAdjusted > 0) {
1247: temp_ = 0;
1248: temp2_ = b_.token1AmtAdjusted;
1249: } else {
1250:
1251: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts); // <= FOUND
1252: }
1253:
1254: uint token0FinalImaginaryReserves_;
1255: uint token1FinalImaginaryReserves_;
1256:
1257: if (pex_.geometricMean < 1e27) {
1258: (, , token0FinalImaginaryReserves_, token1FinalImaginaryReserves_) =
1259: _calculateDebtReserves(pex_.geometricMean, pex_.lowerRange, (token0Debt_ + temp_), (token1Debt_ + temp2_));
1260: } else {
1261:
1262:
1263:
1264:
1265: (, , token1FinalImaginaryReserves_, token0FinalImaginaryReserves_) =
1266: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_));
1267: }
1268:
1269: if (temp_ > 0) {
1270:
1271: temp_ = _getBorrowAndSwap(
1272: token0Debt_,
1273: token1Debt_,
1274: token0FinalImaginaryReserves_,
1275: token1FinalImaginaryReserves_,
1276: temp_
1277: );
1278: } else if (temp2_ > 0) {
1279:
1280: temp_ = _getBorrowAndSwap(
1281: token1Debt_,
1282: token0Debt_,
1283: token1FinalImaginaryReserves_,
1284: token0FinalImaginaryReserves_,
1285: temp2_
1286: );
1287: } else {
1288:
1289: revert FluidDexError(ErrorTypes.DexT1__BorrowAmtsZero); // <= FOUND
1290: }
1291:
1292:
1293: temp_ = temp_ * totalBorrowShares_ / 1e18;
1294:
1295:
1296: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1297:
1298: shares_ += temp_;
1299:
1300: totalBorrowShares_ += temp_;
1301: }
1302:
1303: if (estimate_) revert FluidDexLiquidityOutput(shares_); // <= FOUND
1304:
1305: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__BorrowExcessSharesMinted); // <= FOUND
1306:
1307:
1308:
1309: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1310: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1311:
1312:
1313:
1314: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1315:
1316: temp_ += shares_;
1317:
1318:
1319: if (temp_ > temp2_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached); // <= FOUND
1320:
1321: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1322:
1323: if (b_.token0AmtAdjusted > 0) {
1324:
1325: _verifyToken1Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1326:
1327: temp_ = token0Amt_;
1328:
1329: LIQUIDITY.operate(TOKEN_0, 0, int(temp_), address(0), msg.sender, new bytes(0));
1330: }
1331:
1332: if (b_.token1AmtAdjusted > 0) {
1333:
1334: _verifyToken0Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1335:
1336: temp_ = token1Amt_;
1337:
1338: LIQUIDITY.operate(TOKEN_1, 0, int(temp_), address(0), msg.sender, new bytes(0));
1339: }
1340:
1341:
1342: _totalBorrowShares = totalBorrowShares_;
1343:
1344: emit LogBorrowDebtLiquidity(token0Amt_, token1Amt_, shares_);
1345:
1346: _arbitrage(dexVariables_, dexVariables2_, pex_);
1347: } else {
1348: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled); // <= FOUND
1349: }
1350:
1351: }
['1359']
1359: function payback(
1360: uint token0Amt_,
1361: uint token1Amt_,
1362: uint minSharesAmt_,
1363: bool estimate_
1364: ) public payable returns (uint shares_) {
1365: uint dexVariables_ = dexVariables;
1366: uint dexVariables2_ = dexVariables2;
1367:
1368: _check(dexVariables_, dexVariables2_);
1369:
1370: uint userBorrowData_ = _userBorrowData[msg.sender];
1371:
1372: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn); // <= FOUND
1373:
1375:
1376: if (((dexVariables2_ >> 1) & 1) == 1) {
1377: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1378:
1379: PaybackDebtMemory memory p_;
1380:
1381: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1382: DebtReserves memory d2_ = d_;
1383:
1384: if (token0Amt_ > 0) {
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
1386: _verifySwapAndNonPerfectActions(p_.token0AmtAdjusted, token0Amt_);
1387: _verifyRedeem(p_.token0AmtAdjusted, d_.token0Debt);
1388: }
1389:
1390: if (token1Amt_ > 0) {
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
1392: _verifySwapAndNonPerfectActions(p_.token1AmtAdjusted, token1Amt_);
1393: _verifyRedeem(p_.token1AmtAdjusted, d_.token1Debt);
1394: }
1395:
1396: uint temp_;
1397: uint temp2_;
1398:
1399: uint totalBorrowShares_ = _totalBorrowShares;
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) {
1401:
1402: shares_ = (p_.token0AmtAdjusted * 1e18 / d_.token0Debt);
1403: totalBorrowShares_ -= shares_;
1404: } else if ((p_.token1AmtAdjusted > 0 && p_.token0AmtAdjusted == 0) && (d_.token1Debt > 0) && (d_.token0Debt == 0)) {
1405:
1406: shares_ = (p_.token1AmtAdjusted * 1e18 / d_.token1Debt);
1407: totalBorrowShares_ -= shares_;
1408: } else {
1409: if (p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted > 0) {
1410:
1411:
1412: temp_ = p_.token0AmtAdjusted * 1e18 / d_.token0Debt;
1413:
1414: temp2_ = p_.token1AmtAdjusted * 1e18 / d_.token1Debt;
1415: if (temp_ > temp2_) {
1416:
1417: shares_ = ((temp2_ * totalBorrowShares_) / 1e18);
1418:
1419: temp_ = p_.token0AmtAdjusted - (temp2_ * p_.token0AmtAdjusted) / temp_;
1420: temp2_ = 0;
1421: } else if (temp2_ > temp_) {
1422:
1423: shares_ = ((temp_ * totalBorrowShares_) / 1e18);
1424:
1425: temp2_ = p_.token1AmtAdjusted - ((temp_ * p_.token1AmtAdjusted) / temp2_);
1426: temp_ = 0;
1427: } else {
1428:
1429: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts); // <= FOUND
1430: }
1431:
1432:
1433: d2_ = _getUpdateDebtReserves(
1434: shares_,
1435: totalBorrowShares_,
1436: d_,
1437: false
1438: );
1439: totalBorrowShares_ -= shares_;
1440: } else if (p_.token0AmtAdjusted > 0) {
1441: temp_ = p_.token0AmtAdjusted;
1442: temp2_ = 0;
1443: } else if (p_.token1AmtAdjusted > 0) {
1444: temp_ = 0;
1445: temp2_ = p_.token1AmtAdjusted;
1446: } else {
1447:
1448: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts); // <= FOUND
1449: }
1450:
1451: if (temp_ > 0) {
1452:
1453: temp_ = _getSwapAndPayback(
1454: d2_.token0Debt,
1455: d2_.token1Debt,
1456: d2_.token0ImaginaryReserves,
1457: d2_.token1ImaginaryReserves,
1458: temp_
1459: );
1460: } else if (temp2_ > 0) {
1461:
1462: temp_ = _getSwapAndPayback(
1463: d2_.token1Debt,
1464: d2_.token0Debt,
1465: d2_.token1ImaginaryReserves,
1466: d2_.token0ImaginaryReserves,
1467: temp2_
1468: );
1469: } else {
1470:
1471: revert FluidDexError(ErrorTypes.DexT1__PaybackAmtsZero); // <= FOUND
1472: }
1473:
1474:
1475: temp_ = (temp_ * totalBorrowShares_ / 1e18);
1476:
1477:
1478:
1479: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1480:
1481: shares_ += temp_;
1482:
1483: totalBorrowShares_ -= temp_;
1484: }
1485:
1486: if (estimate_) revert FluidDexLiquidityOutput(shares_); // <= FOUND
1487:
1488: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__PaybackSharedBurnedLess); // <= FOUND
1489:
1490: if (token0Amt_ > 0) {
1491:
1492: _verifyToken0Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1493:
1494: temp_ = token0Amt_;
1495: _depositOrPaybackInLiquidity(TOKEN_0, 0, temp_);
1496: }
1497:
1498: if (token1Amt_ > 0) {
1499:
1500: _verifyToken1Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1501:
1502: temp_ = token1Amt_;
1503: _depositOrPaybackInLiquidity(TOKEN_1, 0, temp_);
1504: }
1505:
1506:
1507:
1508: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1509: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1510:
1511:
1512:
1513: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1514:
1515: temp_ -= shares_;
1516:
1517: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1518:
1519: _totalBorrowShares = totalBorrowShares_;
1520:
1521: emit LogPaybackDebtLiquidity(token0Amt_, token1Amt_, shares_);
1522:
1523: _arbitrage(dexVariables_, dexVariables2_, pex_);
1524: } else {
1525: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled); // <= FOUND
1526: }
1527: }
['1535']
1535: function withdrawPerfectInOneToken(
1536: uint shares_,
1537: uint minToken0_,
1538: uint minToken1_,
1539: bool estimate_
1540: ) public returns (uint withdrawAmt_) {
1541: uint dexVariables_ = dexVariables;
1542: uint dexVariables2_ = dexVariables2;
1543:
1544: _check(dexVariables_, dexVariables2_);
1545:
1546: uint userSupplyData_ = _userSupplyData[msg.sender];
1547:
1548: if (userSupplyData_ & 1 == 0 && !estimate_) {
1549: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn); // <= FOUND
1550: }
1551:
1552: if ((minToken0_ > 0 && minToken1_ > 0) || (minToken0_ == 0 && minToken1_ == 0)) {
1553:
1554: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts); // <= FOUND
1555: }
1556:
1557:
1558: if ((dexVariables2_ & 1) == 1) {
1559: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1560:
1561: uint totalSupplyShares_ = _totalSupplyShares;
1562:
1563: _verifyRedeem(shares_, totalSupplyShares_);
1564:
1565: uint token0Amt_;
1566: uint token1Amt_;
1567:
1568: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1569: CollateralReserves memory c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, false);
1570:
1571: token0Amt_ = c_.token0RealReserves - c2_.token0RealReserves - 1;
1572: token1Amt_ = c_.token1RealReserves - c2_.token1RealReserves - 1;
1573:
1574: if (minToken0_ > 0) {
1575:
1576: token0Amt_ += _getAmountOut(token1Amt_, c2_.token1ImaginaryReserves, c2_.token0ImaginaryReserves);
1577: token1Amt_ = 0;
1578: _verifyToken0Reserves((c_.token0RealReserves - token0Amt_), c_.token1RealReserves, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1579:
1580:
1581: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
1582:
1583:
1584: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1585:
1586: withdrawAmt_ = token0Amt_;
1587: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_); // <= FOUND
1588: if (withdrawAmt_ < minToken0_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough); // <= FOUND
1589: } else {
1590:
1591: token1Amt_ += _getAmountOut(token0Amt_, c2_.token0ImaginaryReserves, c2_.token1ImaginaryReserves);
1592: token0Amt_ = 0;
1593: _verifyToken1Reserves(c_.token0RealReserves, (c_.token1RealReserves - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1594:
1595:
1596: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
1597:
1598:
1599: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1600:
1601: withdrawAmt_ = token1Amt_;
1602: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_); // <= FOUND
1603: if (withdrawAmt_ < minToken1_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough); // <= FOUND
1604: }
1605:
1606: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1607: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
1608:
1609:
1610:
1611: uint256 temp_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
1612:
1613: userSupply_ -= shares_;
1614:
1615:
1616: if (userSupply_ < temp_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached); // <= FOUND
1617:
1618: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, temp_);
1619:
1620: _totalSupplyShares = totalSupplyShares_ - shares_;
1621:
1622: if (minToken0_ > 0) {
1623:
1624: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0));
1625: } else {
1626:
1627: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
1628: }
1629:
1630:
1631: temp_ = shares_;
1632: emit LogWithdrawColInOneToken(temp_, token0Amt_, token1Amt_);
1633:
1634: _arbitrage(dexVariables_, dexVariables2_, pex_);
1635: } else {
1636: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled); // <= FOUND
1637: }
1638: }
['1646']
1646: function paybackPerfectInOneToken(
1647: uint shares_,
1648: uint maxToken0_,
1649: uint maxToken1_,
1650: bool estimate_
1651: ) public payable returns (uint paybackAmt_) {
1652: uint dexVariables_ = dexVariables;
1653: uint dexVariables2_ = dexVariables2;
1654:
1655: _check(dexVariables_, dexVariables2_);
1656:
1657: uint userBorrowData_ = _userBorrowData[msg.sender];
1658:
1659: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn); // <= FOUND
1660:
1661: if ((maxToken0_ > 0 && maxToken1_ > 0) || (maxToken0_ == 0 && maxToken1_ == 0)) {
1662:
1663: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts); // <= FOUND
1664: }
1665:
1666:
1667: if (((dexVariables2_ >> 1) & 1) == 1) {
1668: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1669:
1670: uint totalBorrowShares_ = _totalBorrowShares;
1671:
1672: _verifyRedeem(shares_, totalBorrowShares_);
1673:
1674: uint token0Amt_;
1675: uint token1Amt_;
1676:
1677:
1678: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1679:
1680: DebtReserves memory d2_ = _getUpdateDebtReserves(shares_, totalBorrowShares_, d_, false);
1681:
1682: if (maxToken0_ > 0) {
1683:
1684: token0Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1685: d2_.token0ImaginaryReserves,
1686: d2_.token1ImaginaryReserves,
1687: d_.token0Debt,
1688: d_.token1Debt,
1689: d2_.token0RealReserves,
1690: d2_.token1RealReserves
1691: );
1692: _verifyToken0Reserves((d_.token0Debt - token0Amt_), d_.token1Debt, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1693:
1694:
1695: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
1696:
1697:
1698: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1699:
1700: paybackAmt_ = token0Amt_;
1701: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_); // <= FOUND
1702: if (paybackAmt_ > maxToken0_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh); // <= FOUND
1703: _depositOrPaybackInLiquidity(TOKEN_0, 0, paybackAmt_);
1704: } else {
1705:
1706: token1Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1707: d2_.token1ImaginaryReserves,
1708: d2_.token0ImaginaryReserves,
1709: d_.token1Debt,
1710: d_.token0Debt,
1711: d2_.token1RealReserves,
1712: d2_.token0RealReserves
1713: );
1714: _verifyToken1Reserves(d_.token0Debt, (d_.token1Debt - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1715:
1716:
1717: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
1718:
1719:
1720: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1721:
1722: paybackAmt_ = token1Amt_;
1723: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_); // <= FOUND
1724: if (paybackAmt_ > maxToken1_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh); // <= FOUND
1725: _depositOrPaybackInLiquidity(TOKEN_1, 0, paybackAmt_);
1726: }
1727:
1728:
1729: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1730: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
1731:
1732:
1733:
1734: uint256 temp_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
1735: userBorrow_ -= shares_;
1736:
1737: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, temp_);
1738:
1739: _totalBorrowShares = totalBorrowShares_ - shares_;
1740:
1741:
1742: temp_ = shares_;
1743: emit LogPaybackDebtInOneToken(temp_, token0Amt_, token1Amt_);
1744:
1745: _arbitrage(dexVariables_, dexVariables2_, pex_);
1746: } else {
1747: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled); // <= FOUND
1748: }
1749: }
['2028']
2028: function getPricesAndExchangePrices() public {
2029: uint dexVariables_ = dexVariables;
2030: uint dexVariables2_ = dexVariables2;
2031:
2032: _check(dexVariables_, dexVariables2_);
2033:
2034: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables, dexVariables2);
2035:
2036: revert FluidDexPricesAndExchangeRates(pex_); // <= FOUND
2037: }
['61']
61: function turnOnSmartCol(
62: uint token0Amt_
63: ) public payable _check _onlyDelegateCall {
64: if (dexVariables2 & 1 == 1) {
65: revert FluidDexError(ErrorTypes.DexT1Admin__SmartColIsAlreadyOn); // <= FOUND
66: }
67: uint centerPrice_ = (dexVariables >> 81) & X40;
68: centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);
69: _turnOnSmartCol(token0Amt_, centerPrice_);
70:
71: dexVariables2 = dexVariables2 | 1;
72:
73: emit LogTurnOnSmartCol(token0Amt_);
74: }
['126']
126: function turnOnSmartDebt(
127: uint token0Amt_
128: ) public payable _check _onlyDelegateCall {
129: if (dexVariables2 & 2 == 2) {
130: revert FluidDexError(ErrorTypes.DexT1Admin__SmartDebtIsAlreadyOn); // <= FOUND
131: }
132: uint centerPrice_ = (dexVariables >> 81) & X40;
133: centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);
134: _turnOnSmartDebt(token0Amt_, centerPrice_);
135:
136: dexVariables2 = dexVariables2 | 2;
137:
138: emit LogTurnOnSmartDebt(token0Amt_);
139: }
['175']
175: function updateFeeAndRevenueCut(uint fee_, uint revenueCut_) public _check _onlyDelegateCall {
176:
177:
178: if(revenueCut_ != 0 && revenueCut_ < FOUR_DECIMALS){
179:
180: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
181: }
182:
183: revenueCut_ = revenueCut_ / FOUR_DECIMALS;
184:
185: if (fee_ > FIVE_DECIMALS || revenueCut_ > TWO_DECIMALS) {
186: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
187: }
188:
189: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000003) |
190: (fee_ << 2) |
191: (revenueCut_ << 19);
192:
193: emit LogUpdateFeeAndRevenueCut(fee_, revenueCut_ * FOUR_DECIMALS);
194: }
['199']
199: function updateRangePercents(uint upperPercent_, uint lowerPercent_, uint shiftTime_) public _check _onlyDelegateCall {
200: uint dexVariables2_ = dexVariables2;
201: if (
202: (upperPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
203: (lowerPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
204: (upperPercent_ == 0) ||
205: (lowerPercent_ == 0) ||
206: (shiftTime_ > X20) ||
207: (((dexVariables2_ >> 26) & 1) == 1)
208: ) {
209: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
210: }
211:
212: dexVariables2 = (dexVariables2_ & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000003FFFFFF) |
213: (uint((shiftTime_ > 0) ? 1 : 0) << 26) |
214: (upperPercent_ << 27) |
215: (lowerPercent_ << 47);
216:
217: uint oldUpperPercent_ = (dexVariables2_ >> 27) & X20;
218: uint oldLowerPercent_ = (dexVariables2_ >> 47) & X20;
219:
220: if (shiftTime_ > 0) {
221: _rangeShift = uint128(oldUpperPercent_ | (oldLowerPercent_ << 20) | (shiftTime_ << 40) | (block.timestamp << 60));
222: }
223:
224:
225: emit LogUpdateRangePercents(upperPercent_, lowerPercent_, shiftTime_);
226: }
['232']
232: function updateThresholdPercent(
233: uint upperThresholdPercent_,
234: uint lowerThresholdPercent_,
235: uint thresholdShiftTime_,
236: uint shiftTime_
237: ) public _check _onlyDelegateCall {
238: uint dexVariables2_ = dexVariables2;
239:
240:
241:
242: upperThresholdPercent_ = upperThresholdPercent_ / THREE_DECIMALS;
243: lowerThresholdPercent_ = lowerThresholdPercent_ / THREE_DECIMALS;
244: if (
245: (upperThresholdPercent_ > THREE_DECIMALS) ||
246: (lowerThresholdPercent_ > THREE_DECIMALS) ||
247: (thresholdShiftTime_ == 0) ||
248: (thresholdShiftTime_ > X24) ||
249: (upperThresholdPercent_ == 0) ||
250: (lowerThresholdPercent_ == 0) ||
251: (shiftTime_ > X20) ||
252: (((dexVariables2_ >> 67) & 1) == 1)
253: ) {
254: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
255: }
256:
257: dexVariables2 = (dexVariables2_ & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000007FFFFFFFFFFFFFFFF) |
258: (uint((shiftTime_ > 0) ? 1 : 0) << 67) |
259: (upperThresholdPercent_ << 68) |
260: (lowerThresholdPercent_ << 78) |
261: (thresholdShiftTime_ << 88);
262:
263: uint oldUpperThresholdPercent_ = (dexVariables2_ >> 68) & X10;
264: uint oldLowerThresholdPercent_ = (dexVariables2_ >> 78) & X10;
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24;
266:
267: if (shiftTime_ > 0) {
268: _thresholdShift = uint128(oldUpperThresholdPercent_ |
269: (oldLowerThresholdPercent_ << 20) |
270: (shiftTime_ << 40) |
271: (block.timestamp << 60) |
272: (oldThresholdTime_ << 93));
273: }
274:
275:
276: emit LogUpdateThresholdPercent(upperThresholdPercent_ * THREE_DECIMALS, lowerThresholdPercent_ * THREE_DECIMALS, thresholdShiftTime_, shiftTime_);
277: }
['282']
282: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall {
283: if (
284: (centerPriceAddress_ > X30) ||
285: (percent_ == 0) ||
286: (percent_ > X20) ||
287: (time_ == 0) ||
288: (time_ > X20)
289: ) {
290: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
291: }
292:
293: if (centerPriceAddress_ > 0) {
294: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
295: address centerPrice_ = AddressCalcs.addressCalc(c_.deployerContract, centerPriceAddress_);
296: _checkIsContract(centerPrice_);
297:
298: dexVariables2 = (dexVariables2 & 0xFeFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
299: (centerPriceAddress_ << 112) |
300: uint(1) << 248;
301:
302: _centerPriceShift = block.timestamp | (percent_ << 33) | (time_ << 53);
303: } else {
304: dexVariables2 = (dexVariables2 & 0xFeFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF);
305:
306: _centerPriceShift = 0;
307: }
308:
309: emit LogUpdateCenterPriceAddress(centerPriceAddress_, percent_, time_);
310: }
['315']
315: function updateHookAddress(uint hookAddress_) public _check _onlyDelegateCall {
316: if (hookAddress_ > X30) {
317: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
318: }
319:
320: if (hookAddress_ > 0) {
321: IFluidDexT1.ConstantViews memory c_ = IFluidDexT1(address(this)).constantsView();
322: address hook_ = AddressCalcs.addressCalc(c_.deployerContract, hookAddress_);
323: _checkIsContract(hook_);
324: }
325:
326: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFF00000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
327: (hookAddress_ << 142);
328:
329: emit LogUpdateHookAddress(hookAddress_);
330: }
['332']
332: function updateCenterPriceLimits(uint maxCenterPrice_, uint minCenterPrice_) public _check _onlyDelegateCall {
333: uint centerPrice_ = (dexVariables >> 81) & X40;
334: centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);
335:
336: if (
337: (maxCenterPrice_ <= minCenterPrice_) ||
338: (centerPrice_ <= minCenterPrice_) ||
339: (centerPrice_ >= maxCenterPrice_) ||
340: (minCenterPrice_ == 0)
341: ) {
342: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
343: }
344:
345: dexVariables2 = (dexVariables2 & 0xFFFFFFF00000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
346: (maxCenterPrice_.toBigNumber(20, 8, BigMathMinified.ROUND_UP) << 172) |
347: (minCenterPrice_.toBigNumber(20, 8, BigMathMinified.ROUND_DOWN) << 200);
348:
349: emit LogUpdateCenterPriceLimits(maxCenterPrice_, minCenterPrice_);
350: }
['352']
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall {
353: if((token0UtilizationLimit_ != 0 && token0UtilizationLimit_ < THREE_DECIMALS) || (token1UtilizationLimit_ != 0 && token1UtilizationLimit_ < THREE_DECIMALS)){
354:
355: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
356: }
357:
358: token0UtilizationLimit_ = token0UtilizationLimit_ / THREE_DECIMALS;
359: token1UtilizationLimit_ = token1UtilizationLimit_ / THREE_DECIMALS;
360:
361: if (token0UtilizationLimit_ > THREE_DECIMALS || token1UtilizationLimit_ > THREE_DECIMALS) {
362: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
363: }
364:
365: dexVariables2 = (dexVariables2 & 0xFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
366: (token0UtilizationLimit_ << 228) |
367: (token1UtilizationLimit_ << 238);
368:
369: emit LogUpdateUtilizationLimit(token0UtilizationLimit_ * THREE_DECIMALS, token1UtilizationLimit_ * THREE_DECIMALS);
370: }
['546']
546: function pauseUser(
547: address user_,
548: bool pauseSupply_,
549: bool pauseBorrow_
550: ) public _onlyDelegateCall {
551: _checkIsContract(user_);
552:
553: uint256 userData_;
554:
555: if (pauseSupply_) {
556:
557: userData_ = _userSupplyData[user_];
558: if (userData_ == 0) {
559: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined); // <= FOUND
560: }
561: if (userData_ & 1 == 0) {
562: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle); // <= FOUND
563: }
564:
565: _userSupplyData[user_] = userData_ & (~uint(1));
566: }
567:
568: if (pauseBorrow_) {
569:
570: userData_ = _userBorrowData[user_];
571: if (userData_ == 0) {
572: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined); // <= FOUND
573: }
574: if (userData_ & 1 == 0) {
575: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle); // <= FOUND
576: }
577:
578: _userBorrowData[user_] = userData_ & (~uint(1));
579: }
580:
581: emit LogPauseUser(user_, pauseSupply_, pauseBorrow_);
582: }
['584']
584: function unpauseUser(
585: address user_,
586: bool unpauseSupply_,
587: bool unpauseBorrow_
588: ) public _onlyDelegateCall {
589: _checkIsContract(user_);
590:
591: uint256 userData_;
592:
593: if (unpauseSupply_) {
594:
595: userData_ = _userSupplyData[user_];
596: if (userData_ == 0) {
597: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined); // <= FOUND
598: }
599: if (userData_ & 1 == 1) {
600: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle); // <= FOUND
601: }
602:
603:
604: _userSupplyData[user_] = userData_ | 1;
605: }
606:
607: if (unpauseBorrow_) {
608:
609: userData_ = _userBorrowData[user_];
610: if (userData_ == 0) {
611: revert FluidDexError(ErrorTypes.DexT1Admin__UserNotDefined); // <= FOUND
612: }
613: if (userData_ & 1 == 1) {
614: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidPauseToggle); // <= FOUND
615: }
616:
617:
618: _userBorrowData[user_] = userData_ | 1;
619: }
620:
621: emit LogUnpauseUser(user_, unpauseSupply_, unpauseBorrow_);
622: }
['626']
626: function initialize(InitializeVariables memory i_) public payable _onlyDelegateCall {
627: _checkIsContract(TEAM_MULTISIG);
628:
629: if (!(i_.smartCol || i_.smartDebt)) {
630:
631: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
632: }
633:
634:
635: if(i_.revenueCut != 0 && i_.revenueCut < FOUR_DECIMALS){
636:
637: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
638: }
639:
641:
642: i_.revenueCut = i_.revenueCut / FOUR_DECIMALS;
643: i_.upperShiftThreshold = i_.upperShiftThreshold / THREE_DECIMALS;
644: i_.lowerShiftThreshold = i_.lowerShiftThreshold / THREE_DECIMALS;
645:
646: if (
647: (i_.fee > FIVE_DECIMALS) ||
648: (i_.revenueCut > TWO_DECIMALS) ||
649: (i_.upperPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
650: (i_.lowerPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
651: (i_.upperPercent == 0) ||
652: (i_.lowerPercent == 0) ||
653: (i_.upperShiftThreshold > THREE_DECIMALS) ||
654: (i_.lowerShiftThreshold > THREE_DECIMALS) ||
655: (i_.upperShiftThreshold == 0) ||
656: (i_.lowerShiftThreshold == 0) ||
657: (i_.thresholdShiftTime == 0) ||
658: (i_.thresholdShiftTime > X24) ||
659: (i_.centerPriceAddress > X30) ||
660: (i_.hookAddress > X30) ||
661: (i_.centerPrice <= i_.minCenterPrice) ||
662: (i_.centerPrice >= i_.maxCenterPrice) ||
663: (i_.minCenterPrice == 0)
664: ) {
665: revert FluidDexError(ErrorTypes.DexT1Admin__ConfigOverflow); // <= FOUND
666: }
667:
668: uint dexVariables2_;
669:
670: if (i_.smartCol) {
671: _turnOnSmartCol(i_.token0ColAmt, i_.centerPrice);
672: dexVariables2_ = dexVariables2_ | 1;
673: }
674:
675: if (i_.smartDebt) {
676: _turnOnSmartDebt(i_.token0DebtAmt, i_.centerPrice);
677: dexVariables2_ = dexVariables2_ | 2;
678: }
679:
680: i_.centerPrice = i_.centerPrice.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN);
681:
682: dexVariables = (i_.centerPrice << 1) |
683: (i_.centerPrice << 41) |
684: (i_.centerPrice << 81) |
685: (block.timestamp << 121) |
686: (60 << 154) |
687: (7 << 176);
688:
689: dexVariables2 = dexVariables2_ |
690: (i_.fee << 2) |
691: (i_.revenueCut << 19) |
692: (i_.upperPercent << 27) |
693: (i_.lowerPercent << 47) |
694: (i_.upperShiftThreshold << 68) |
695: (i_.lowerShiftThreshold << 78) |
696: (i_.thresholdShiftTime << 88) |
697: (i_.centerPriceAddress << 112) |
698: (i_.hookAddress << 142) |
699: (i_.maxCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_UP) << 172) |
700: (i_.minCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_DOWN) << 200) |
701: (THREE_DECIMALS << 228) |
702: (THREE_DECIMALS << 238);
703:
704: emit LogInitializePoolConfig(
705: i_.smartCol,
706: i_.smartDebt,
707: i_.token0ColAmt,
708: i_.token0DebtAmt,
709: i_.fee,
710: i_.revenueCut * FOUR_DECIMALS,
711: i_.centerPriceAddress,
712: i_.hookAddress
713: );
714:
715: emit LogInitializePriceParams(
716: i_.upperPercent,
717: i_.lowerPercent,
718: i_.upperShiftThreshold * THREE_DECIMALS,
719: i_.lowerShiftThreshold * THREE_DECIMALS,
720: i_.thresholdShiftTime,
721: i_.maxCenterPrice,
722: i_.minCenterPrice
723: );
724: }
['726']
726: function pauseSwapAndArbitrage() public _onlyDelegateCall {
727: uint dexVariables2_ = dexVariables2;
728: if ((dexVariables2_ >> 255) == 1) {
729:
730: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
731: }
732: dexVariables2 = dexVariables2_ | (uint(1) << 255);
733:
734: emit LogPauseSwapAndArbitrage();
735: }
['737']
737: function unpauseSwapAndArbitrage() public _onlyDelegateCall {
738: uint dexVariables2_ = dexVariables2;
739: if ((dexVariables2_ >> 255) == 0) {
740:
741: revert FluidDexError(ErrorTypes.DexT1Admin__InvalidParams); // <= FOUND
742: }
743: dexVariables2 = (dexVariables2_ << 1) >> 1;
744:
745: emit LogUnpauseSwapAndArbitrage();
746: }
[NonCritical-12] Private and internal state variables should have a preceding _ in their name unless they are constants
Add a preceding underscore to the state variable name, take care to refactor where there variables are read/wrote
Num of instances: 20
Click to show findings
['24']
24: address private immutable ADDRESS_THIS; // <= FOUND
['19']
19: address internal immutable TOKEN_0; // <= FOUND
['22']
22: address internal immutable TOKEN_1; // <= FOUND
['24']
24: uint256 internal immutable TOKEN_0_NUMERATOR_PRECISION; // <= FOUND
['25']
25: uint256 internal immutable TOKEN_0_DENOMINATOR_PRECISION; // <= FOUND
['26']
26: uint256 internal immutable TOKEN_1_NUMERATOR_PRECISION; // <= FOUND
['27']
27: uint256 internal immutable TOKEN_1_DENOMINATOR_PRECISION; // <= FOUND
['30']
30: IFluidLiquidity internal immutable LIQUIDITY; // <= FOUND
['33']
33: IFluidDexFactory internal immutable DEX_FACTORY; // <= FOUND
['36']
36: address internal immutable ADMIN_IMPLEMENTATION; // <= FOUND
['39']
39: address internal immutable DEPLOYER_CONTRACT; // <= FOUND
['42']
42: bytes32 internal immutable SUPPLY_TOKEN_0_SLOT; // <= FOUND
['43']
43: bytes32 internal immutable BORROW_TOKEN_0_SLOT; // <= FOUND
['44']
44: bytes32 internal immutable SUPPLY_TOKEN_1_SLOT; // <= FOUND
['45']
45: bytes32 internal immutable BORROW_TOKEN_1_SLOT; // <= FOUND
['46']
46: bytes32 internal immutable EXCHANGE_PRICE_TOKEN_0_SLOT; // <= FOUND
['47']
47: bytes32 internal immutable EXCHANGE_PRICE_TOKEN_1_SLOT; // <= FOUND
['48']
48: uint256 internal immutable TOTAL_ORACLE_MAPPING; // <= FOUND
['17']
17: uint internal dexVariables; // <= FOUND
['40']
40: uint internal dexVariables2; // <= FOUND
Consider spreading these lines over multiple lines to aid in readability and the support of VIM users everywhere.
Num of instances: 214
Click to show findings
['12']
12: /// Next 40 bits => 81-120 => center price. Center price from where the ranges will be calculated. BigNumber (32 bits precision, 8 bits exponent) // <= FOUND
['14']
14: /// Next 22 bits => 154-175 => max 4194303 seconds (~1165 hrs, ~48.5 days), time difference between last to last and last price stored // <= FOUND
['16']
16: /// Next 16 bits => 179-194 => current mapping or oracle, after every 8 transaction it will increase by 1. Max capacity is 65535 but it can be lower than that check dexVariables2 // <= FOUND
['22']
22: /// Next 7 bits => 19-25 => revenue cut from fee (1 = 1%, 100 = 100%). If fee is 1000 = 0.1% and revenue cut is 10 = 10% then governance get 0.01% of every swap // <= FOUND
['23']
23: /// Next 1 bit => 26 => percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time. // <= FOUND
['24']
24: /// Next 20 bits => 27-46 => upperPercent (1% = 10000, max value: 104.8575%) upperRange - upperRange * upperPercent = centerPrice. Hence, upperRange = centerPrice / (1 - upperPercent) // <= FOUND
['26']
26: /// Next 1 bit => 67 => threshold percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time. // <= FOUND
['27']
27: /// Next 10 bits => 68-77 => upper shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice > (centerPrice + (upperRange - centerPrice) * (1000 - upperShiftThresholdPercent) / 1000) then trigger shift // <= FOUND
['28']
28: /// Next 10 bits => 78-87 => lower shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice < (centerPrice - (centerPrice - lowerRange) * (1000 - lowerShiftThresholdPercent) / 1000) then trigger shift // <= FOUND
['30']
30: /// Next 30 bits => 112-131 => Address of center price if center price should be fetched externally, for example, for wstETH <> ETH pool, fetch wstETH exchange rate into stETH from wstETH contract. // <= FOUND
['31']
31: /// Why fetch it externally? Because let's say pool width is 0.1% and wstETH temporarily got depeg of 0.5% then pool will start to shift to newer pricing // <= FOUND
['36']
36: /// Next 10 bits => 228-237 => utilization limit of token0. Max value 1000 = 100%, if 100% then no need to check the utilization. // <= FOUND
['37']
37: /// Next 10 bits => 238-247 => utilization limit of token1. Max value 1000 = 100%, if 100% then no need to check the utilization. // <= FOUND
['39']
39: /// Last 1 bit => 255 => Pause swap & arbitrage (only perfect functions will be usable), if we need to pause entire DEX then that can be done through pausing DEX on Liquidity Layer // <= FOUND
['45']
45: /// Aside from 1st bit, entire bits here are same as liquidity layer _userSupplyData. Hence exact same supply & borrow limit library can be used // <= FOUND
['49']
49: /// Next 33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591) // <= FOUND
['50']
50: /// Next 14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383). // <= FOUND
['52']
52: /// Next 24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days) // <= FOUND
['53']
53: /// Next 18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (aka shares can be burned); BigMath: 10 | 8 // <= FOUND
['60']
60: /// Aside from 1st bit, entire bits here are same as liquidity layer _userBorrowData. Hence exact same supply & borrow limit library function can be used // <= FOUND
['67']
67: /// Next 24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days) // <= FOUND
['74']
74: /// If last swap happened at Block B - 4 and next swap happened after 4 blocks at Block B then it will store that difference // <= FOUND
['83']
83: /// Next 22 bits => 10- 31 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['86']
86: /// Next 22 bits => 42- 63 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['89']
89: /// Next 22 bits => 74- 95 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['92']
92: /// Next 22 bits => 106-127 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['95']
95: /// Next 22 bits => 138-159 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['98']
98: /// Next 22 bits => 170-191 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['101']
101: /// Next 22 bits => 202-223 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['104']
104: /// Next 22 bits => 234-255 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746% // <= FOUND
['76']
76: function _calcNumeratorAndDenominator(address token_) private view returns (uint256 numerator_, uint256 denominator_) { // <= FOUND
['62']
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
['80']
80: function _calcRangeShifting(uint upperRange_, uint lowerRange_, uint dexVariables2_) internal returns (uint, uint, uint) { // <= FOUND
['90']
90: // fetching from storage and storing in storage, aside from admin module dexVariables2 only updates from this function and _calcThresholdShifting. // <= FOUND
['110']
110: function _calcThresholdShifting(uint upperThreshold_, uint lowerThreshold_, uint thresholdTime_) internal returns (uint, uint, uint) { // <= FOUND
['121']
121: // fetching from storage and storing in storage, aside from admin module dexVariables2 only updates from this function and _calcRangeShifting. // <= FOUND
['146']
146: /// @notice The externally fetched new center price is expected to not differ significantly from the last externally fetched center price // <= FOUND
['158']
158: newCenterPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, ((dexVariables2_ >> 112) & X30))).centerPrice(); // <= FOUND
['170']
170: // fetching from storage and storing in storage, aside from admin module dexVariables2 only updates these shift function. // <= FOUND
['176']
176: // In case of oldCenterPrice_ ending up 0, which could happen when a lot of time has passed (pool has no swaps for many days or weeks) // <= FOUND
['179']
179: // not ideal that this would ever happen unless the pool is not in use and all/most users have left leaving not enough liquidity to trade on // <= FOUND
['262']
262: (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(upperThreshold_, lowerThreshold_, shiftingTime_); // <= FOUND
['265']
265: if (lastStoredPrice_ > (centerPrice_ + (upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_) / THREE_DECIMALS)) { // <= FOUND
['276']
276: } else if (lastStoredPrice_ < (centerPrice_ - (centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_) / THREE_DECIMALS)) { // <= FOUND
['313']
313: (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_); // <= FOUND
['375']
375: // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅4⋅(Pa - GP)⋅1e27) / 4*(Pa - GP)^2) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5) // <= FOUND
['376']
376: // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅1e27) / (Pa - GP)) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5) // <= FOUND
['382']
382: // note: part1 will almost always be < 1e28 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e29 // <= FOUND
['444']
444: (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(geometricMean_, upperRange_, token0Supply_, token1Supply_); // <= FOUND
['446']
446: // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x // <= FOUND
['1073']
1073: // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x // <= FOUND
['450']
450: (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange((1e54 / geometricMean_), (1e54 / lowerRange_), token1Supply_, token0Supply_); // <= FOUND
['522']
522: // note: part1 will almost always be < 1e27 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e28 // <= FOUND
['624']
624: (d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_); // <= FOUND
['630']
630: (d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_); // <= FOUND
['781']
781: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves + c_.token0ImaginaryReserves * newShares_ / totalOldShares_; // <= FOUND
['782']
782: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves + c_.token1ImaginaryReserves * newShares_ / totalOldShares_; // <= FOUND
['787']
787: c2_.token0ImaginaryReserves = c_.token0ImaginaryReserves - (c_.token0ImaginaryReserves * newShares_ / totalOldShares_); // <= FOUND
['788']
788: c2_.token1ImaginaryReserves = c_.token1ImaginaryReserves - (c_.token1ImaginaryReserves * newShares_ / totalOldShares_); // <= FOUND
['890']
890: // 6. tokenAxb = ((tokenAFinalImaginaryReserves + tokenAxb) * tokenBxb) / ((tokenBFinalImaginaryReserves - tokenBxb) + tokenBxb) // <= FOUND
['897']
897: // 7. (tokenAx - tokenAxa) = ((tokenAFinalImaginaryReserves + (tokenAx - tokenAxa)) * tokenBxb) / (tokenBFinalImaginaryReserves) // <= FOUND
['900']
900: // 8. (tokenAx - tokenAxa) * tokenBFinalImaginaryReserves = ((tokenAFinalImaginaryReserves + (tokenAx - tokenAxa)) * (tokenAxa * tokenBDebt / tokenADebt)) // <= FOUND
['968']
968: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves + d_.token0ImaginaryReserves * shares_ / totalShares_; // <= FOUND
['969']
969: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves + d_.token1ImaginaryReserves * shares_ / totalShares_; // <= FOUND
['975']
975: d2_.token0ImaginaryReserves = d_.token0ImaginaryReserves - d_.token0ImaginaryReserves * shares_ / totalShares_; // <= FOUND
['976']
976: d2_.token1ImaginaryReserves = d_.token1ImaginaryReserves - d_.token1ImaginaryReserves * shares_ / totalShares_; // <= FOUND
['1073']
1073: // 10. (tokenBDebt * tokenAxa) / (tokenADebt - tokenAx) = (imaginaryTokenBReserves * tokenAxb) / (imaginaryTokenAReserves + tokenAxb) // <= FOUND
['1074']
1074: // 10. (tokenBDebt * (tokenAx - tokenAxb)) / (tokenADebt - tokenAx) = (imaginaryTokenBReserves * tokenAxb) / (imaginaryTokenAReserves + tokenAxb) // <= FOUND
['1139']
1139: LIQUIDITY.operate{ value: amt_ }(token_, int(depositAmt_), -int(paybackAmt_), address(0), address(0), abi.encode(msg.sender)); // <= FOUND
['1141']
1141: LIQUIDITY.operate(token_, int(depositAmt_), -int(paybackAmt_), address(0), address(0), abi.encode(msg.sender)); // <= FOUND
['1262']
1262: // Ensure that the center price is within the acceptable range of the old center price if it's not the first swap in the same block // <= FOUND
['1289']
1289: // 2nd swap in same block no need to update anything around oracle, only need to update last swap price in dexVariables // <= FOUND
['1332']
1332: (newWithdrawalLimit_ << DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) | // converted to BigNumber can not overflow // <= FOUND
['1369']
1369: (newBorrowLimit_ << DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) | // converted to BigNumber can not overflow // <= FOUND
['1378']
1378: liquidityLayerUtilization_ = (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14; // <= FOUND
['1379']
1379: // Note: this can go slightly above the utilization limit if no update is written to storage at liquidity layer // <= FOUND
['1381']
1381: // so just to keep in mind when configuring the actual limit reachable can be utilizationLimit_ + storageUpdateThreshold at Liquidity // <= FOUND
['1382']
1382: if (liquidityLayerUtilization_ > utilizationLimit_) revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached); // <= FOUND
['1387']
1387: try IHook(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, hookAddress_)).dexPrice(mode_, swap0to1_, TOKEN_0, TOKEN_1, price_) returns (bool isOk_) { // <= FOUND
['25']
25: /// @dev if token0 reserves are too low w.r.t token1 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough // <= FOUND
['26']
26: function _verifyToken0Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
['32']
32: /// @dev if token1 reserves are too low w.r.t token0 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough // <= FOUND
['33']
33: function _verifyToken1Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
['70']
70: /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_ // <= FOUND
['130']
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice); // <= FOUND
['132']
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) = // <= FOUND
['133']
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves); // <= FOUND
['136']
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves); // <= FOUND
['144']
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice); // <= FOUND
['146']
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) = // <= FOUND
['149']
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) = // <= FOUND
['147']
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves); // <= FOUND
['150']
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves); // <= FOUND
['155']
155: // limiting amtInAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenIn reserves combined // <= FOUND
['156']
156: // basically, if this throws that means user is trying to swap 0.5x tokenIn if current tokenIn imaginary reserves is x // <= FOUND
['158']
158: // token1Reserve / x and new pool pricing will become token1Reserve / 1.5x (token1Reserve will decrease after swap but for simplicity ignoring that) // <= FOUND
['159']
159: // So pool price is decreased by ~33.33% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand) // <= FOUND
['166']
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves); // <= FOUND
['189']
189: // price can slightly differ from debt pool but difference will be very small. Probably <0.01% for active DEX pools. // <= FOUND
['194']
194: // price can slightly differ from collateral pool but difference will be very small. Probably <0.01% for active DEX pools. // <= FOUND
['203']
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves); // <= FOUND
['205']
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) : // <= FOUND
['206']
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP); // <= FOUND
['210']
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves); // <= FOUND
['212']
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) : // <= FOUND
['213']
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP); // <= FOUND
['216']
216: // from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same // <= FOUND
['249']
249: // (temp_ + temp3_) == amountIn_ == msg.value (for native token), if there is revenue cut then this statement is not true // <= FOUND
['284']
284: /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_ // <= FOUND
['368']
368: // limiting amtOutAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenOut reserves combined // <= FOUND
['369']
369: // basically, if this throws that means user is trying to swap 0.5x tokenOut if current tokenOut imaginary reserves is x // <= FOUND
['371']
371: // token1Reserve / x and new pool pricing will become token1Reserve / 0.5x (token1Reserve will decrease after swap but for simplicity ignoring that) // <= FOUND
['372']
372: // So pool price is increased by ~50% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand) // <= FOUND
['379']
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves); // <= FOUND
['419']
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) : // <= FOUND
['420']
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP); // <= FOUND
['427']
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) : // <= FOUND
['428']
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP); // <= FOUND
['538']
538: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_; // <= FOUND
['539']
539: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_; // <= FOUND
['584']
584: /// @param estimate_ If true, the function will revert with the estimated withdrawal amounts without actually performing the withdrawal // <= FOUND
['690']
690: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_; // <= FOUND
['691']
691: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_; // <= FOUND
['130']
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice); // <= FOUND
['835']
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1; // <= FOUND
['841']
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1; // <= FOUND
['850']
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) { // <= FOUND
['854']
854: } else if ((d_.token1AmtAdjusted > 0 && d_.token0AmtAdjusted == 0) && (c_.token1RealReserves > 0) && (c_.token0RealReserves == 0)) { // <= FOUND
['878']
878: // if equal then revert as swap will not be needed anymore which can create some issue, better to use depositPerfect in this case // <= FOUND
['882']
882: // User deposited in equal proportion here. Hence updating col reserves and the swap will happen on updated col reserves // <= FOUND
['937']
937: _verifyToken1Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['943']
943: _verifyToken0Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['976']
976: /// @param estimate_ If true, the function will revert with the estimated shares to burn without actually performing the withdrawal // <= FOUND
['1005']
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1011']
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1020']
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) { // <= FOUND
['1021']
1021: // only token0 liquidity exist and user wants to withdraw token0. Hence withdraw directly and burn shares. // <= FOUND
['1024']
1024: } else if ((w_.token1AmtAdjusted > 0 && w_.token0AmtAdjusted == 0) && (token1Reserves_ > 0) && (token0Reserves_ == 0)) { // <= FOUND
['1025']
1025: // only token1 liquidity exist and user wants to withdraw token1. Hence withdraw directly and burn shares. // <= FOUND
['1048']
1048: // if equal then revert as swap will not be needed anymore which can create some issue, better to use withdraw in perfect proportion for this // <= FOUND
['1052']
1052: // User withdrew in equal proportion here. Hence updating col reserves and the swap will happen on updated col reserves // <= FOUND
['1071']
1071: (token0ImaginaryReservesOutsideRangpex_, token1ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange(pex_.geometricMean, pex_.upperRange, (token0Reserves_ - temp_), (token1Reserves_ - temp2_)); // <= FOUND
['1077']
1077: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_)); // <= FOUND
['1137']
1137: _verifyToken0Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1144']
1144: _verifyToken1Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1192']
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1198']
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1211']
1211: } else if ((b_.token1AmtAdjusted > 0 && b_.token0AmtAdjusted == 0) && (token1Debt_ > 0) && (token0Debt_ == 0)) { // <= FOUND
['1235']
1235: // if equal then revert as swap will not be needed anymore which can create some issue, better to use perfect borrow in this case // <= FOUND
['1239']
1239: // User borrowed in equal proportion here. Hence updating col reserves and the swap will happen on updated col reserves // <= FOUND
['1259']
1259: _calculateDebtReserves(pex_.geometricMean, pex_.lowerRange, (token0Debt_ + temp_), (token1Debt_ + temp2_)); // <= FOUND
['1266']
1266: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_)); // <= FOUND
['1325']
1325: _verifyToken1Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1326']
1326: // assigning token0Amt_ to temp_ to avoid compilation error (I don't know why it's throwing when using token0Amt_ directly) // <= FOUND
['1334']
1334: _verifyToken0Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1335']
1335: // assigning token1Amt_ to temp_ to avoid compilation error (I don't know why it's throwing when using token0Amt_ directly) // <= FOUND
['144']
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice); // <= FOUND
['1385']
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1; // <= FOUND
['1391']
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1; // <= FOUND
['1400']
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) { // <= FOUND
['1404']
1404: } else if ((p_.token1AmtAdjusted > 0 && p_.token0AmtAdjusted == 0) && (d_.token1Debt > 0) && (d_.token0Debt == 0)) { // <= FOUND
['1428']
1428: // if equal then revert as swap will not be needed anymore which can create some issue, better to use perfect payback in this case // <= FOUND
['1432']
1432: // User paid back in equal proportion here. Hence updating debt reserves and the swap will happen on updated debt reserves // <= FOUND
['1492']
1492: _verifyToken0Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1500']
1500: _verifyToken1Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1533']
1533: /// @param estimate_ If true, the function will revert with the estimated withdrawal amount without executing the withdrawal // <= FOUND
['1578']
1578: _verifyToken0Reserves((c_.token0RealReserves - token0Amt_), c_.token1RealReserves, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1593']
1593: _verifyToken1Reserves(c_.token0RealReserves, (c_.token1RealReserves - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1644']
1644: /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback // <= FOUND
['1692']
1692: _verifyToken0Reserves((d_.token0Debt - token0Amt_), d_.token1Debt, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1714']
1714: _verifyToken1Reserves(d_.token0Debt, (d_.token1Debt - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS); // <= FOUND
['1765']
1765: c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice); // <= FOUND
['1768']
1768: d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice); // <= FOUND
['1791']
1791: int a_ = _swapRoutingIn(0, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves); // <= FOUND
['1811']
1811: LIQUIDITY.operate(TOKEN_1, -int(amtOut_), -int(amtIn_), address(this), address(0), abi.encode(SKIP_TRANSFERS, address(this))); // <= FOUND
['1831']
1831: LIQUIDITY.operate(TOKEN_1, int(amtIn_), int(amtOut_), address(0), address(this), abi.encode(SKIP_TRANSFERS, address(this))); // <= FOUND
['1863']
1863: // not checking if amountWithRevenueCut_ > amount_, because it will be and if it's less than liquidity layer will throw. // <= FOUND
['1871']
1871: /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration // <= FOUND
['1875']
1875: /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30] // <= FOUND
['1919']
1919: // last swap occured in this block, that means current price is active for 0 secs. Hence TWAP for it will be 0. // <= FOUND
['1962']
1962: // oracle data does not exist. Probably due to pool recently got initialized and not have much swaps. // <= FOUND
['1989']
1989: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0)); // <= FOUND
['2019']
2019: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0)); // <= FOUND
['2005']
2005: // if time_ comes out as 0 here then lowestPrice & highestPrice should not be price_, it should be next price_ that we will calculate // <= FOUND
['2043']
2043: /// @notice It checks if the caller is authorized, enables re-entrancy protection, delegates the call to the admin implementation, and then disables re-entrancy protection // <= FOUND
['2045']
2045: /// @notice This function uses assembly to perform a delegatecall to the admin implementation to update configs related to DEX // <= FOUND
['118']
118: _totalSupplyShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION); // <= FOUND
['141']
141: /// @dev Can only borrow if DEX pool address borrow config is added in Liquidity Layer for both the tokens else Liquidity Layer will revert // <= FOUND
['142']
142: /// governance will have access to _turnOnSmartDebt, technically governance here can borrow as much as limits are set // <= FOUND
['144']
144: /// Borrowing in 50:50 ratio (doesn't matter if pool configuration is set to 20:80, 30:70, etc, external swap will arbitrage & balance the pool) // <= FOUND
['166']
166: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION); // <= FOUND
['174']
174: /// @param revenueCut_ in 4 decimals, 100000 = 10%, 10% cut on fee_, so if fee is 1% and cut is 10% then cut in swap amount will be 10% of 1% = 0.1% // <= FOUND
['199']
199: function updateRangePercents(uint upperPercent_, uint lowerPercent_, uint shiftTime_) public _check _onlyDelegateCall { // <= FOUND
['221']
221: _rangeShift = uint128(oldUpperPercent_ | (oldLowerPercent_ << 20) | (shiftTime_ << 40) | (block.timestamp << 60)); // <= FOUND
['223']
223: // Note _rangeShift is reset when the previous shift is fully completed, which is forced to have happened through if check above // <= FOUND
['274']
274: // Note _thresholdShift is reset when the previous shift is fully completed, which is forced to have happened through if check above // <= FOUND
['276']
276: emit LogUpdateThresholdPercent(upperThresholdPercent_ * THREE_DECIMALS, lowerThresholdPercent_ * THREE_DECIMALS, thresholdShiftTime_, shiftTime_); // <= FOUND
['279']
279: /// @dev we are storing uint nonce from which we will calculate the contract address, to store an address we need 160 bits // <= FOUND
['282']
282: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall { // <= FOUND
['297']
297: // note: if address is made 0 then as well in the last swap currentPrice is updated on storage, so code will start using that automatically // <= FOUND
['352']
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall { // <= FOUND
['353']
353: if((token0UtilizationLimit_ != 0 && token0UtilizationLimit_ < THREE_DECIMALS) || (token1UtilizationLimit_ != 0 && token1UtilizationLimit_ < THREE_DECIMALS)){ // <= FOUND
['369']
369: emit LogUpdateUtilizationLimit(token0UtilizationLimit_ * THREE_DECIMALS, token1UtilizationLimit_ * THREE_DECIMALS); // <= FOUND
['450']
450: // if we were to set a limit that goes below max expansion limit, then after 1 deposit or 1 withdrawal it would // <= FOUND
['453']
453: // So limiting update to max. full expansion. If more is desired, this must be called again after some withdraws. // <= FOUND
['489']
489: // max debt ceiling must not be smaller than base debt ceiling. Also covers case where max = 0 but base > 0 // <= FOUND
['624']
624: /// note we have not added updateUtilizationLimit in the params here because struct of InitializeVariables already has 16 variables // <= FOUND
['40']
40: /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: // <= FOUND
['60']
60: /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place. // <= FOUND
['16']
16: function dexPrice(uint id_, bool swap0to1_, address token0_, address token1_, uint price_) external returns (bool isOk_); // <= FOUND
['23']
23: /// @dev This function is marked as non-constant (potentially state-changing) to allow flexibility in price fetching mechanisms. // <= FOUND
['24']
24: /// While typically used as a read-only operation, this design permits write operations if needed for certain token pairs // <= FOUND
['71']
71: /// after user operations (deposit, withdraw, borrow, payback) token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS // <= FOUND
['72']
72: /// after user operations (deposit, withdraw, borrow, payback) token1 reserves should not be less than token0InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS // <= FOUND
Try to index as much as three variables in event declarations as this is more gas efficient when done on value type variables (uint, address etc) however not for bytes and string variables
Num of instances: 26
Click to show findings
['10']
10: event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to); // <= FOUND
['16']
16: event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['22']
22: event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['28']
28: event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['34']
34: event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['40']
40: event LogDepositColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['46']
46: event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['52']
52: event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['58']
58: event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['64']
64: event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['70']
70: event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['75']
75: event LogArbitrage(int routing, uint amtOut); // <= FOUND
['9']
9: event LogTurnOnSmartCol(uint token0Amt); // <= FOUND
['13']
13: event LogTurnOnSmartDebt(uint token0Amt); // <= FOUND
['18']
18: event LogUpdateFeeAndRevenueCut(uint fee, uint revenueCut); // <= FOUND
['24']
24: event LogUpdateRangePercents(uint upperPercent, uint lowerPercent, uint shiftTime); // <= FOUND
['31']
31: event LogUpdateThresholdPercent( // <= FOUND
32: uint upperThresholdPercent,
33: uint lowerThresholdPercent,
34: uint thresholdShiftTime,
35: uint shiftTime
36: );
['42']
42: event LogUpdateCenterPriceAddress(uint centerPriceAddress, uint percent, uint time); // <= FOUND
['46']
46: event LogUpdateHookAddress(uint hookAddress); // <= FOUND
['51']
51: event LogUpdateCenterPriceLimits(uint maxCenterPrice, uint minCenterPrice); // <= FOUND
['56']
56: event LogUpdateUtilizationLimit(uint token0UtilizationLimit, uint token1UtilizationLimit); // <= FOUND
['70']
70: event LogPauseUser(address user, bool pauseSupply, bool pauseBorrow); // <= FOUND
['76']
76: event LogUnpauseUser(address user, bool unpauseSupply, bool unpauseBorrow); // <= FOUND
['87']
87: event LogInitializePoolConfig( // <= FOUND
88: bool smartCol,
89: bool smartDebt,
90: uint token0ColAmt,
91: uint token0DebtAmt,
92: uint fee,
93: uint revenueCut,
94: uint centerPriceAddress,
95: uint hookAddress
96: );
['106']
106: event LogInitializePriceParams( // <= FOUND
107: uint upperPercent,
108: uint lowerPercent,
109: uint upperShiftThreshold,
110: uint lowerShiftThreshold,
111: uint thresholdShiftTime,
112: uint maxCenterPrice,
113: uint minCenterPrice
114: );
['123']
123: event LogUpdateUserWithdrawalLimit(address user, uint256 newLimit); // <= FOUND
Contracts should expose all public and external functions through interfaces. This practice ensures a clear and consistent definition of how the contract can be interacted with, promoting better transparency and integration.
Num of instances: 36
Click to show findings
['1857']
1857: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external
['1878']
1878: function oraclePrice(
1879: uint[] memory secondsAgos_
1880: ) external view returns (
1881: Oracle[] memory twaps_,
1882: uint currentPrice_
1883: )
['51']
51: function constantsView() external view returns (ConstantViews memory constantsView_)
['69']
69: function constantsView2() external view returns (ConstantViews2 memory constantsView2_)
['372']
372: function updateUserSupplyConfigs(UserSupplyConfig[] memory userSupplyConfigs_) external _check _onlyDelegateCall
['431']
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall
['483']
483: function updateUserBorrowConfigs(UserBorrowConfig[] memory userBorrowConfigs_) external _check _onlyDelegateCall
['72']
72: function swapIn(
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_)
['286']
286: function swapOut(
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_)
['511']
511: function depositPerfect(
512: uint shares_,
513: uint maxToken0Deposit_,
514: uint maxToken1Deposit_,
515: bool estimate_
516: ) public payable returns (uint token0Amt_, uint token1Amt_)
['587']
587: function withdrawPerfect(
588: uint shares_,
589: uint minToken0Withdraw_,
590: uint minToken1Withdraw_,
591: bool estimate_
592: ) public returns (uint token0Amt_, uint token1Amt_)
['665']
665: function borrowPerfect(
666: uint shares_,
667: uint minToken0Borrow_,
668: uint minToken1Borrow_,
669: bool estimate_
670: ) public returns (uint token0Amt_, uint token1Amt_)
['742']
742: function paybackPerfect(
743: uint shares_,
744: uint maxToken0Payback_,
745: uint maxToken1Payback_,
746: bool estimate_
747: ) public payable returns (uint token0Amt_, uint token1Amt_)
['810']
810: function deposit(
811: uint token0Amt_,
812: uint token1Amt_,
813: uint minSharesAmt_,
814: bool estimate_
815: ) public payable returns (uint shares_)
['978']
978: function withdraw(
979: uint token0Amt_,
980: uint token1Amt_,
981: uint maxSharesAmt_,
982: bool estimate_
983: ) public returns (uint shares_)
['1165']
1165: function borrow(
1166: uint token0Amt_,
1167: uint token1Amt_,
1168: uint maxSharesAmt_,
1169: bool estimate_
1170: ) public returns (uint shares_)
['1359']
1359: function payback(
1360: uint token0Amt_,
1361: uint token1Amt_,
1362: uint minSharesAmt_,
1363: bool estimate_
1364: ) public payable returns (uint shares_)
['1535']
1535: function withdrawPerfectInOneToken(
1536: uint shares_,
1537: uint minToken0_,
1538: uint minToken1_,
1539: bool estimate_
1540: ) public returns (uint withdrawAmt_)
['1646']
1646: function paybackPerfectInOneToken(
1647: uint shares_,
1648: uint maxToken0_,
1649: uint maxToken1_,
1650: bool estimate_
1651: ) public payable returns (uint paybackAmt_)
['2028']
2028: function getPricesAndExchangePrices() public
['433']
433: function getCollateralReserves(
434: uint geometricMean_,
435: uint upperRange_,
436: uint lowerRange_,
437: uint token0SupplyExchangePrice_,
438: uint token1SupplyExchangePrice_
439: ) public view returns (CollateralReserves memory c_)
['610']
610: function getDebtReserves(
611: uint geometricMean_,
612: uint upperRange_,
613: uint lowerRange_,
614: uint token0BorrowExchangePrice_,
615: uint token1BorrowExchangePrice_
616: ) public view returns (DebtReserves memory d_)
['61']
61: function turnOnSmartCol(
62: uint token0Amt_
63: ) public payable _check _onlyDelegateCall
['126']
126: function turnOnSmartDebt(
127: uint token0Amt_
128: ) public payable _check _onlyDelegateCall
['175']
175: function updateFeeAndRevenueCut(uint fee_, uint revenueCut_) public _check _onlyDelegateCall
['199']
199: function updateRangePercents(uint upperPercent_, uint lowerPercent_, uint shiftTime_) public _check _onlyDelegateCall
['232']
232: function updateThresholdPercent(
233: uint upperThresholdPercent_,
234: uint lowerThresholdPercent_,
235: uint thresholdShiftTime_,
236: uint shiftTime_
237: ) public _check _onlyDelegateCall
['282']
282: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall
['315']
315: function updateHookAddress(uint hookAddress_) public _check _onlyDelegateCall
['332']
332: function updateCenterPriceLimits(uint maxCenterPrice_, uint minCenterPrice_) public _check _onlyDelegateCall
['352']
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall
['546']
546: function pauseUser(
547: address user_,
548: bool pauseSupply_,
549: bool pauseBorrow_
550: ) public _onlyDelegateCall
['584']
584: function unpauseUser(
585: address user_,
586: bool unpauseSupply_,
587: bool unpauseBorrow_
588: ) public _onlyDelegateCall
['626']
626: function initialize(InitializeVariables memory i_) public payable _onlyDelegateCall
['726']
726: function pauseSwapAndArbitrage() public _onlyDelegateCall
['737']
737: function unpauseSwapAndArbitrage() public _onlyDelegateCall
Instead of using uint to declare uint258, explicitly define uint258 to ensure there is no confusion
Num of instances: 258
Click to show findings
['18']
18: function _check(uint dexVariables_, uint dexVariables2_) internal { // <= FOUND
['26']
26:
27: function _verifyToken0Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
['33']
33:
34: function _verifyToken1Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
['39']
39: function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure { // <= FOUND
['50']
50: function _verifyMint(uint amt_, uint totalAmt_) internal pure { // <= FOUND
['59']
59: function _verifyRedeem(uint amt_, uint totalAmt_) internal pure { // <= FOUND
['78']
78: uint dexVariables_ = dexVariables; // <= FOUND
['79']
79: uint dexVariables2_ = dexVariables2; // <= FOUND
['107']
107:
108: uint temp_ = dexVariables2_ & 1; // <= FOUND
['109']
109:
110: uint temp2_ = (dexVariables2_ >> 1) & 1; // <= FOUND
['1155']
1155: uint temp3_; // <= FOUND
['112']
112: uint temp4_; // <= FOUND
['511']
511:
518: function depositPerfect(
519: uint shares_, // <= FOUND
520: uint maxToken0Deposit_, // <= FOUND
521: uint maxToken1Deposit_, // <= FOUND
522: bool estimate_
523: ) public payable returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
['522']
522: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
['532']
532:
533: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
['556']
556: uint userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64; // <= FOUND
['587']
587:
594: function withdrawPerfect(
595: uint shares_, // <= FOUND
596: uint minToken0Withdraw_, // <= FOUND
597: uint minToken1Withdraw_, // <= FOUND
598: bool estimate_
599: ) public returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
['532']
532: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
['665']
665:
672: function borrowPerfect(
673: uint shares_, // <= FOUND
674: uint minToken0Borrow_, // <= FOUND
675: uint minToken1Borrow_, // <= FOUND
676: bool estimate_
677: ) public returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
['676']
676: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
['685']
685:
686: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
['742']
742:
749: function paybackPerfect(
750: uint shares_, // <= FOUND
751: uint maxToken0Payback_, // <= FOUND
752: uint maxToken1Payback_, // <= FOUND
753: bool estimate_
754: ) public payable returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
['685']
685: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
['810']
810:
816: function deposit(
817: uint token0Amt_, // <= FOUND
818: uint token1Amt_, // <= FOUND
819: uint minSharesAmt_, // <= FOUND
820: bool estimate_
821: ) public payable returns (uint shares_) {
['846']
846: uint temp_; // <= FOUND
['847']
847: uint temp2_; // <= FOUND
['978']
978:
984: function withdraw(
985: uint token0Amt_, // <= FOUND
986: uint token1Amt_, // <= FOUND
987: uint maxSharesAmt_, // <= FOUND
988: bool estimate_
989: ) public returns (uint shares_) {
['999']
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true); // <= FOUND
['1000']
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false); // <= FOUND
['1067']
1067: uint token0ImaginaryReservesOutsideRangpex_; // <= FOUND
['1068']
1068: uint token1ImaginaryReservesOutsideRangpex_; // <= FOUND
['1165']
1165:
1171: function borrow(
1172: uint token0Amt_, // <= FOUND
1173: uint token1Amt_, // <= FOUND
1174: uint maxSharesAmt_, // <= FOUND
1175: bool estimate_
1176: ) public returns (uint shares_) {
['1186']
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true); // <= FOUND
['1187']
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false); // <= FOUND
['1254']
1254: uint token0FinalImaginaryReserves_; // <= FOUND
['1255']
1255: uint token1FinalImaginaryReserves_; // <= FOUND
['1359']
1359:
1365: function payback(
1366: uint token0Amt_, // <= FOUND
1367: uint token1Amt_, // <= FOUND
1368: uint minSharesAmt_, // <= FOUND
1369: bool estimate_
1370: ) public payable returns (uint shares_) {
['676']
676:
677: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
['1535']
1535:
1541: function withdrawPerfectInOneToken(
1542: uint shares_, // <= FOUND
1543: uint minToken0_, // <= FOUND
1544: uint minToken1_, // <= FOUND
1545: bool estimate_
1546: ) public returns (uint withdrawAmt_) {
['1565']
1565: uint token0Amt_; // <= FOUND
['1566']
1566: uint token1Amt_; // <= FOUND
['1646']
1646:
1652: function paybackPerfectInOneToken(
1653: uint shares_, // <= FOUND
1654: uint maxToken0_, // <= FOUND
1655: uint maxToken1_, // <= FOUND
1656: bool estimate_
1657: ) public payable returns (uint paybackAmt_) {
['1758']
1758:
1765: function _arbitrage(uint dexVariables_, uint dexVariables2_, PricesAndExchangePrice memory pex_) private { // <= FOUND
['1763']
1763: uint price_; // <= FOUND
['1153']
1153: uint temp_; // <= FOUND
['1785']
1785: uint amtOut_; // <= FOUND
['1786']
1786: uint amtIn_; // <= FOUND
['1840']
1840: uint lastPrice_ = (dexVariables_ >> 41) & X40; // <= FOUND
['1857']
1857:
1859: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external { // <= FOUND
['1878']
1878:
1886: function oraclePrice(
1887: uint[] memory secondsAgos_
1888: ) external view returns (
1889: Oracle[] memory twaps_,
1890: uint currentPrice_ // <= FOUND
1891: ) {
['1889']
1889: uint totalTime_; // <= FOUND
['1890']
1890: uint time_; // <= FOUND
['1892']
1892: uint i; // <= FOUND
['1893']
1893: uint secondsAgo_ = secondsAgos_[0]; // <= FOUND
['1897']
1897: uint price_ = currentPrice_; // <= FOUND
['1901']
1901: uint twap1by0_; // <= FOUND
['1902']
1902: uint twap0by1_; // <= FOUND
['1904']
1904: uint j; // <= FOUND
['1911']
1911: uint slotData_; // <= FOUND
['1912']
1912: uint percentDiff_; // <= FOUND
['26']
26:
30: function _getAmountOut(
31: uint256 amountIn_,
32: uint iReserveIn_, // <= FOUND
33: uint iReserveOut_ // <= FOUND
34: ) internal pure returns (uint256 amountOut_) {
['43']
43:
48: function _getAmountIn(
49: uint256 amountOut_,
50: uint iReserveIn_, // <= FOUND
51: uint iReserveOut_ // <= FOUND
52: ) internal pure returns (uint256 amountIn_) {
['62']
62:
68: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
['64']
64: uint diff_ = current_ - old_; // <= FOUND
['67']
67: uint diff_ = old_ - current_; // <= FOUND
['80']
80:
87: function _calcRangeShifting(uint upperRange_, uint lowerRange_, uint dexVariables2_) internal returns (uint, uint, uint) { // <= FOUND
['81']
81: uint rangeShift_ = _rangeShift; // <= FOUND
['82']
82: uint oldUpperRange_ = rangeShift_ & X20; // <= FOUND
['83']
83: uint oldLowerRange_ = (rangeShift_ >> 20) & X20; // <= FOUND
['84']
84: uint shiftDuration_ = (rangeShift_ >> 40) & X20; // <= FOUND
['85']
85: uint startTimeStamp_ = ((rangeShift_ >> 60) & X33); // <= FOUND
['95']
95: uint timePassed_ = block.timestamp - startTimeStamp_; // <= FOUND
['110']
110:
117: function _calcThresholdShifting(uint upperThreshold_, uint lowerThreshold_, uint thresholdTime_) internal returns (uint, uint, uint) { // <= FOUND
['111']
111: uint thresholdShift_ = _thresholdShift; // <= FOUND
['112']
112: uint oldUpperThreshold_ = thresholdShift_ & X20; // <= FOUND
['113']
113: uint oldLowerThreshold_ = (thresholdShift_ >> 20) & X20; // <= FOUND
['114']
114: uint shiftDuration_ = (thresholdShift_ >> 40) & X20; // <= FOUND
['115']
115: uint startTimeStamp_ = ((thresholdShift_ >> 60) & X33); // <= FOUND
['116']
116: uint oldThresholdTime_ = (thresholdShift_ >> 93) & X24; // <= FOUND
['125']
125: uint timePassed_ = block.timestamp - startTimeStamp_; // <= FOUND
['147']
147:
161: function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) { // <= FOUND
['148']
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40; // <= FOUND
['150']
150: uint centerPriceShift_ = _centerPriceShift; // <= FOUND
['151']
151: uint startTimeStamp_ = centerPriceShift_ & X33; // <= FOUND
['152']
152: uint percent_ = (centerPriceShift_ >> 33) & X20; // <= FOUND
['153']
153: uint time_ = (centerPriceShift_ >> 53) & X20; // <= FOUND
['155']
155: uint fromTimeStamp_ = (dexVariables_ >> 121) & X33; // <= FOUND
['159']
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS); // <= FOUND
['214']
214:
236: function _getPricesAndExchangePrices(
237: uint dexVariables_, // <= FOUND
238: uint dexVariables2_ // <= FOUND
239: ) internal returns (
240: PricesAndExchangePrice memory pex_
241: ) {
['220']
220: uint centerPrice_; // <= FOUND
['238']
238: uint lastStoredPrice_ = (dexVariables_ >> 41) & X40; // <= FOUND
['241']
241: uint upperRange_ = ((dexVariables2_ >> 27) & X20); // <= FOUND
['242']
242: uint lowerRange_ = ((dexVariables2_ >> 47) & X20); // <= FOUND
['257']
257: uint upperThreshold_ = (dexVariables2_ >> 68) & X10; // <= FOUND
['258']
258: uint lowerThreshold_ = (dexVariables2_ >> 78) & X10; // <= FOUND
['259']
259: uint shiftingTime_ = (dexVariables2_ >> 88) & X24; // <= FOUND
['266']
266: uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33); // <= FOUND
['291']
291:
292: uint temp_ = (dexVariables2 >> 172) & X28; // <= FOUND
['350']
350:
355: function _calculateReservesOutsideRange(
356: uint gp_, // <= FOUND
357: uint pa_, // <= FOUND
358: uint rx_, // <= FOUND
359: uint ry_ // <= FOUND
360: ) internal pure returns (
361: uint xa_, // <= FOUND
362: uint yb_ // <= FOUND
363: ) {
['383']
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407: uint p1_ = pa_ - gp_; // <= FOUND
['384']
384: uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_); // <= FOUND
['385']
385: uint p3_ = rx_ * ry_; // <= FOUND
['400']
400:
405: function _getLiquidityCollateral(
406: bytes32 supplyTokenSlot_,
407: uint tokenExchangePrice_, // <= FOUND
408: bool isToken0_
409: ) internal view returns (uint tokenSupply_) {
['405']
405: uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_); // <= FOUND
['433']
433:
447: function getCollateralReserves(
448: uint geometricMean_, // <= FOUND
449: uint upperRange_, // <= FOUND
450: uint lowerRange_, // <= FOUND
451: uint token0SupplyExchangePrice_, // <= FOUND
452: uint token1SupplyExchangePrice_ // <= FOUND
453: ) public view returns (CollateralReserves memory c_) {
['440']
440: uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true); // <= FOUND
['441']
441: uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false); // <= FOUND
['470']
470:
481: function _calculateDebtReserves(
482: uint gp_, // <= FOUND
483: uint pb_, // <= FOUND
484: uint dx_, // <= FOUND
485: uint dy_ // <= FOUND
486: ) internal pure returns (
487: uint rx_, // <= FOUND
488: uint ry_, // <= FOUND
489: uint irx_, // <= FOUND
490: uint iry_ // <= FOUND
491: ) {
['535']
535: uint p2_ = (dx_ * dy_); // <= FOUND
['577']
577:
582: function _getLiquidityDebt(
583: bytes32 borrowTokenSlot_,
584: uint tokenExchangePrice_, // <= FOUND
585: bool isToken0_
586: ) internal view returns (uint tokenDebt_) {
['582']
582: uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_); // <= FOUND
['610']
610:
623: function getDebtReserves(
624: uint geometricMean_, // <= FOUND
625: uint upperRange_, // <= FOUND
626: uint lowerRange_, // <= FOUND
627: uint token0BorrowExchangePrice_, // <= FOUND
628: uint token1BorrowExchangePrice_ // <= FOUND
629: ) public view returns (DebtReserves memory d_) {
['617']
617: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true); // <= FOUND
['618']
618: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false); // <= FOUND
['644']
644:
653: function _swapRoutingIn(
654: uint t, // <= FOUND
655: uint x, // <= FOUND
656: uint y, // <= FOUND
657: uint x2, // <= FOUND
658: uint y2 // <= FOUND
659: ) internal pure returns (
660: int a_ // <= FOUND
661: ) {
['661']
661:
662:
663:
664:
665:
666:
667:
668:
669: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18); // <= FOUND
['662']
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18); // <= FOUND
['676']
676:
685: function _swapRoutingOut(
686: uint t, // <= FOUND
687: uint x, // <= FOUND
688: uint y, // <= FOUND
689: uint x2, // <= FOUND
690: uint y2 // <= FOUND
691: ) internal pure returns (
692: int a_ // <= FOUND
693: ) {
['705']
705:
710: function _getSwapAndDeposit(
711: uint c_, // <= FOUND
712: uint d_, // <= FOUND
713: uint e_, // <= FOUND
714: uint f_, // <= FOUND
715: uint i_ // <= FOUND
716: ) internal pure returns (
717: uint shares_ // <= FOUND
718: ) {
['736']
736:
737:
738:
739:
740:
741:
742:
743:
744:
745:
746:
747:
748:
749:
750:
751:
752:
753:
754:
755:
756:
757:
758: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_; // <= FOUND
['737']
737: uint temp2_ = 4 * c_ * e_; // <= FOUND
['738']
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2; // <= FOUND
['769']
769:
775: function _getUpdatedColReserves(
776: uint newShares_, // <= FOUND
777: uint totalOldShares_, // <= FOUND
778: CollateralReserves memory c_,
779: bool mintOrBurn_
780: ) internal pure returns (
781: CollateralReserves memory c2_
782: ) {
['798']
798:
803: function _getWithdrawAndSwap(
804: uint c_, // <= FOUND
805: uint d_, // <= FOUND
806: uint e_, // <= FOUND
807: uint f_, // <= FOUND
808: uint g_ // <= FOUND
809: ) internal pure returns (
810: uint shares_ // <= FOUND
811: ) {
['847']
847:
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_); // <= FOUND
['850']
850:
851:
852: uint temp2_ = (((c_ * f_) / d_) + c_) * g_; // <= FOUND
['853']
853:
854: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_); // <= FOUND
['872']
872:
877: function _getBorrowAndSwap(
878: uint c_, // <= FOUND
879: uint d_, // <= FOUND
880: uint e_, // <= FOUND
881: uint f_, // <= FOUND
882: uint g_ // <= FOUND
883: ) internal pure returns (
884: uint shares_ // <= FOUND
885: ) {
['920']
920:
921:
922:
923:
924:
925:
926:
927:
928:
929:
930:
931:
932:
933:
934:
935:
936:
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
949:
950:
951:
952:
953:
954:
955:
956:
957:
958:
959: uint temp_ = (c_ * f_ + d_ * e_ + d_ * g_) / (2 * d_); // <= FOUND
['924']
924:
925:
926: uint temp2_ = (c_ * f_ * g_) / d_; // <= FOUND
['955']
955:
969: function _getUpdateDebtReserves(
970: uint shares_, // <= FOUND
971: uint totalShares_, // <= FOUND
972: DebtReserves memory d_,
973: bool mintOrBurn_
974: ) internal pure returns (
975: DebtReserves memory d2_
976: ) {
['988']
988:
994: function _getSwapAndPaybackOneTokenPerfectShares(
995: uint a_, // <= FOUND
996: uint b_, // <= FOUND
997: uint c_, // <= FOUND
998: uint d_, // <= FOUND
999: uint i_, // <= FOUND
1000: uint j_ // <= FOUND
1001: ) internal pure returns (uint tokenAmt_) {
['997']
997:
998: uint l_ = a_ - i_; // <= FOUND
['999']
999:
1000: uint m_ = b_ - j_; // <= FOUND
['1001']
1001:
1002: uint w_ = a_ * b_; // <= FOUND
['1003']
1003:
1004: uint z_ = w_ / l_; // <= FOUND
['1005']
1005:
1006: uint y_ = w_ / m_; // <= FOUND
['1007']
1007:
1008: uint v_ = z_ - m_ - d_; // <= FOUND
['1009']
1009:
1010: uint x_ = (v_ * y_) / (m_ + v_); // <= FOUND
['1028']
1028:
1033: function _getSwapAndPayback(
1034: uint c_, // <= FOUND
1035: uint d_, // <= FOUND
1036: uint e_, // <= FOUND
1037: uint f_, // <= FOUND
1038: uint g_ // <= FOUND
1039: ) internal pure returns (
1040: uint shares_ // <= FOUND
1041: ) {
['1091']
1091:
1092:
1093:
1094:
1095:
1096:
1097:
1098:
1099:
1100:
1101:
1102:
1103:
1104:
1105:
1106:
1107:
1108:
1109:
1110:
1111:
1112:
1113:
1114:
1115:
1116:
1117:
1118:
1119:
1120:
1121:
1122:
1123:
1124:
1125:
1126:
1127:
1128:
1129:
1130:
1131:
1132:
1133:
1134:
1135:
1136:
1137:
1138:
1139:
1140:
1141:
1142:
1143:
1144:
1145: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_; // <= FOUND
['1094']
1094:
1095: uint temp2_ = 4 * e_ * g_; // <= FOUND
['1125']
1125:
1129: function _depositOrPaybackInLiquidity(address token_, uint depositAmt_, uint paybackAmt_) internal { // <= FOUND
['1131']
1131: uint amt_ = depositAmt_ > 0 ? depositAmt_ : paybackAmt_; // <= FOUND
['1145']
1145: function _updateOracle(
1146: uint newPrice_, // <= FOUND
1147: uint centerPrice_, // <= FOUND
1148: uint dexVariables_ // <= FOUND
1149: ) internal returns (uint) {
['1151']
1151:
1152: uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33); // <= FOUND
['1154']
1154: uint temp2_; // <= FOUND
['1200']
1200: uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3); // <= FOUND
['1201']
1201: uint oracleMap_ = (dexVariables_ >> 179) & X16; // <= FOUND
['1297']
1297: function _updatingUserSupplyDataOnStorage(
1298: uint userSupplyData_, // <= FOUND
1299: uint userSupply_, // <= FOUND
1300: uint newWithdrawalLimit_ // <= FOUND
1301: ) internal {
['1336']
1336: function _updatingUserBorrowDataOnStorage(
1337: uint userBorrowData_, // <= FOUND
1338: uint userBorrow_, // <= FOUND
1339: uint newBorrowLimit_ // <= FOUND
1340: ) internal {
['1377']
1377:
1378: uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_); // <= FOUND
['1386']
1386: function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal { // <= FOUND
['7']
7: uint lastStoredPrice; // <= FOUND
['8']
8: uint centerPrice; // <= FOUND
['9']
9: uint upperRange; // <= FOUND
['10']
10: uint lowerRange; // <= FOUND
['11']
11: uint geometricMean; // <= FOUND
['12']
12: uint supplyToken0ExchangePrice; // <= FOUND
['13']
13: uint borrowToken0ExchangePrice; // <= FOUND
['14']
14: uint supplyToken1ExchangePrice; // <= FOUND
['15']
15: uint borrowToken1ExchangePrice; // <= FOUND
['19']
19: uint token0RealReserves; // <= FOUND
['20']
20: uint token1RealReserves; // <= FOUND
['21']
21: uint token0ImaginaryReserves; // <= FOUND
['22']
22: uint token1ImaginaryReserves; // <= FOUND
['26']
26: uint tokenInRealReserves; // <= FOUND
['27']
27: uint tokenOutRealReserves; // <= FOUND
['28']
28: uint tokenInImaginaryReserves; // <= FOUND
['29']
29: uint tokenOutImaginaryReserves; // <= FOUND
['33']
33: uint token0Debt; // <= FOUND
['34']
34: uint token1Debt; // <= FOUND
['42']
42: uint tokenInDebt; // <= FOUND
['43']
43: uint tokenOutDebt; // <= FOUND
['56']
56: uint price; // <= FOUND
['57']
57: uint fee; // <= FOUND
['58']
58: uint revenueCut; // <= FOUND
['57']
57: uint fee; // <= FOUND
['76']
76: uint msgValue; // <= FOUND
['108']
108: uint lowestPrice1by0; // <= FOUND
['109']
109: uint highestPrice1by0; // <= FOUND
['110']
110: uint oracleSlot; // <= FOUND
['111']
111: uint oracleMap; // <= FOUND
['112']
112: uint oracle; // <= FOUND
['116']
116: uint twap1by0; // <= FOUND
['117']
117: uint lowestPrice1by0; // <= FOUND
['118']
118: uint highestPrice1by0; // <= FOUND
['119']
119: uint twap0by1; // <= FOUND
['120']
120: uint lowestPrice0by1; // <= FOUND
['121']
121: uint highestPrice0by1; // <= FOUND
['142']
142: uint token0NumeratorPrecision; // <= FOUND
['143']
143: uint token0DenominatorPrecision; // <= FOUND
['144']
144: uint token1NumeratorPrecision; // <= FOUND
['145']
145: uint token1DenominatorPrecision; // <= FOUND
['16']
16:
20: event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['22']
22:
26: event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['28']
28:
32: event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['34']
34:
38: event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['40']
40:
44: event LogDepositColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['46']
46:
50: event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['52']
52:
56: event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['58']
58:
62: event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
['64']
64:
68: event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['70']
70:
74: event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
['75']
75:
78: event LogArbitrage(int routing, uint amtOut); // <= FOUND
['17']
17:
29: uint internal dexVariables; // <= FOUND
['40']
40:
61: uint internal dexVariables2; // <= FOUND
['42']
42: uint internal _totalSupplyShares; // <= FOUND
['57']
57: uint internal _totalBorrowShares; // <= FOUND
['16']
16:
27: function dexPrice(uint id_, bool swap0to1_, address token0_, address token1_, uint price_) external returns (bool isOk_); // <= FOUND
['61']
61: function turnOnSmartCol(
62: uint token0Amt_ // <= FOUND
63: ) public payable _check _onlyDelegateCall {
['67']
67: uint centerPrice_ = (dexVariables >> 81) & X40; // <= FOUND
['76']
76: function _turnOnSmartCol(
77: uint token0Amt_, // <= FOUND
78: uint centerPrice_ // <= FOUND
79: ) internal {
['83']
83: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision; // <= FOUND
['85']
85: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27; // <= FOUND
['87']
87: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision; // <= FOUND
['92']
92: uint amt_; // <= FOUND
['126']
126: function turnOnSmartDebt(
127: uint token0Amt_ // <= FOUND
128: ) public payable _check _onlyDelegateCall {
['145']
145:
149: function _turnOnSmartDebt(
150: uint token0Amt_, // <= FOUND
151: uint centerPrice_ // <= FOUND
152: ) internal {
['87']
87: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision; // <= FOUND
['175']
175:
177: function updateFeeAndRevenueCut(uint fee_, uint revenueCut_) public _check _onlyDelegateCall { // <= FOUND
['199']
199:
202: function updateRangePercents(uint upperPercent_, uint lowerPercent_, uint shiftTime_) public _check _onlyDelegateCall { // <= FOUND
['217']
217: uint oldUpperPercent_ = (dexVariables2_ >> 27) & X20; // <= FOUND
['218']
218: uint oldLowerPercent_ = (dexVariables2_ >> 47) & X20; // <= FOUND
['232']
232:
236: function updateThresholdPercent(
237: uint upperThresholdPercent_, // <= FOUND
238: uint lowerThresholdPercent_, // <= FOUND
239: uint thresholdShiftTime_, // <= FOUND
240: uint shiftTime_ // <= FOUND
241: ) public _check _onlyDelegateCall {
['263']
263: uint oldUpperThresholdPercent_ = (dexVariables2_ >> 68) & X10; // <= FOUND
['264']
264: uint oldLowerThresholdPercent_ = (dexVariables2_ >> 78) & X10; // <= FOUND
['265']
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24; // <= FOUND
['282']
282:
285: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall { // <= FOUND
['332']
332: function updateCenterPriceLimits(uint maxCenterPrice_, uint minCenterPrice_) public _check _onlyDelegateCall { // <= FOUND
['352']
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall { // <= FOUND
['668']
668: uint dexVariables2_; // <= FOUND
['8']
8: uint token0ColAmt; // <= FOUND
['10']
10: uint token0DebtAmt; // <= FOUND
['8']
8: uint centerPrice; // <= FOUND
['58']
58: uint revenueCut; // <= FOUND
['14']
14: uint upperPercent; // <= FOUND
['15']
15: uint lowerPercent; // <= FOUND
['16']
16: uint upperShiftThreshold; // <= FOUND
['17']
17: uint lowerShiftThreshold; // <= FOUND
['18']
18: uint thresholdShiftTime; // <= FOUND
['19']
19: uint centerPriceAddress; // <= FOUND
['20']
20: uint hookAddress; // <= FOUND
['21']
21: uint maxCenterPrice; // <= FOUND
['22']
22: uint minCenterPrice; // <= FOUND
['18']
18:
21: event LogUpdateFeeAndRevenueCut(uint fee, uint revenueCut); // <= FOUND
['24']
24:
28: event LogUpdateRangePercents(uint upperPercent, uint lowerPercent, uint shiftTime); // <= FOUND
['31']
31:
36: event LogUpdateThresholdPercent(
37: uint upperThresholdPercent, // <= FOUND
38: uint lowerThresholdPercent, // <= FOUND
39: uint thresholdShiftTime, // <= FOUND
40: uint shiftTime // <= FOUND
41: );
['42']
42:
46: event LogUpdateCenterPriceAddress(uint centerPriceAddress, uint percent, uint time); // <= FOUND
['51']
51:
54: event LogUpdateCenterPriceLimits(uint maxCenterPrice, uint minCenterPrice); // <= FOUND
['56']
56:
59: event LogUpdateUtilizationLimit(uint token0UtilizationLimit, uint token1UtilizationLimit); // <= FOUND
['87']
87:
96: event LogInitializePoolConfig(
97: bool smartCol,
98: bool smartDebt,
99: uint token0ColAmt, // <= FOUND
100: uint token0DebtAmt, // <= FOUND
101: uint fee, // <= FOUND
102: uint revenueCut, // <= FOUND
103: uint centerPriceAddress, // <= FOUND
104: uint hookAddress // <= FOUND
105: );
['106']
106:
114: event LogInitializePriceParams(
115: uint upperPercent, // <= FOUND
116: uint lowerPercent, // <= FOUND
117: uint upperShiftThreshold, // <= FOUND
118: uint lowerShiftThreshold, // <= FOUND
119: uint thresholdShiftTime, // <= FOUND
120: uint maxCenterPrice, // <= FOUND
121: uint minCenterPrice // <= FOUND
122: );
['1791']
1791:
1792:
1793:
1794: int a_ = _swapRoutingIn(0, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves); // <= FOUND
['534']
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587: int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27); // <= FOUND
['1170']
1170:
1171:
1172: int priceDiff_ = int(ORACLE_PRECISION) - int((temp2_ * ORACLE_PRECISION) / newPrice_); // <= FOUND
['1276']
1276:
1277:
1278: int priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / newPrice_); // <= FOUND
['60']
60: int swapRoutingAmt; // <= FOUND
The following order should be used within contracts
constructor
receive function (if exists)
fallback function (if exists)
external
public
internal
private
Rearrange the contract functions and contructors to fit this ordering
Num of instances: 4
Click to show findings
['15']
15: contract FluidDexT1 is Helpers // <= FOUND
['21']
21: contract FluidDexT1Admin is ConstantVariables, Variables, Structs, Events, Error // <= FOUND
['19']
19: abstract contract Helpers is Variables, ImmutableVariables, Events // <= FOUND
['11']
11: abstract contract ImmutableVariables is ConstantVariables, Structs, Error // <= FOUND
In Solidity, when msg.sender
plays a crucial role in a function's logic, it's important for transparency and auditability that any events emitted by this function include msg.sender
as a parameter. This practice enhances the traceability and accountability of transactions, allowing users and external observers to easily track who initiated a particular action. Including msg.sender
in event logs helps in creating a clear and verifiable record of interactions with the contract, thereby increasing user trust and facilitating easier debugging and analysis of contract behavior. It's a key aspect of writing clear, transparent, and user-friendly smart contracts.
Num of instances: 10
Click to show findings
['511']
511: function depositPerfect(
512: uint shares_,
513: uint maxToken0Deposit_,
514: uint maxToken1Deposit_,
515: bool estimate_
516: ) public payable returns (uint token0Amt_, uint token1Amt_) {
517: uint dexVariables_ = dexVariables;
518: uint dexVariables2_ = dexVariables2;
519:
520: _check(dexVariables_, dexVariables2_);
521:
522: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
523:
524:
525: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
526:
527:
528: if ((dexVariables2_ & 1) == 1) {
529: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
530:
531:
532: uint totalSupplyShares_ = _totalSupplyShares;
533:
534: _verifyMint(shares_, totalSupplyShares_);
535:
536:
537:
538: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
539: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
540:
541:
542:
543: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
544: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
545:
546: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
547:
548: if (token0Amt_ > maxToken0Deposit_ || token1Amt_ > maxToken1Deposit_) {
549: revert FluidDexError(ErrorTypes.DexT1__AboveDepositMax);
550: }
551:
552: _depositOrPaybackInLiquidity(TOKEN_0, token0Amt_, 0);
553:
554: _depositOrPaybackInLiquidity(TOKEN_1, token1Amt_, 0);
555:
556: uint userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
557:
558: userSupply_ = ((userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK));
559:
560:
561: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
562:
563: userSupply_ += shares_;
564:
565:
566: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
567:
568:
569: _totalSupplyShares = totalSupplyShares_ + shares_;
570: } else {
571: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
572: }
573:
574:
575: dexVariables = dexVariables_;
576:
577: emit LogDepositPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
578: }
['587']
587: function withdrawPerfect(
588: uint shares_,
589: uint minToken0Withdraw_,
590: uint minToken1Withdraw_,
591: bool estimate_
592: ) public returns (uint token0Amt_, uint token1Amt_) {
593: uint dexVariables_ = dexVariables;
594: uint dexVariables2_ = dexVariables2;
595:
596: _check(dexVariables_, dexVariables2_);
597:
598: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
599:
600: if (userSupplyData_ & 1 == 0 && !estimate_) {
601: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
602: }
603:
604:
605: if ((dexVariables2_ & 1) == 1) {
606: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
607:
608: uint totalSupplyShares_ = _totalSupplyShares;
609:
610: _verifyRedeem(shares_, totalSupplyShares_);
611:
612:
613:
614: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
615: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
616:
617:
618: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
619: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
620:
621: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
622:
623: if (token0Amt_ < minToken0Withdraw_ || token1Amt_ < minToken1Withdraw_) {
624: revert FluidDexError(ErrorTypes.DexT1__BelowWithdrawMin);
625: }
626:
627: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
628: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
629:
630:
631: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
632: userSupply_ -= shares_;
633:
634:
635: if (userSupply_ < newWithdrawalLimit_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
636:
637: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
638:
639: _totalSupplyShares = totalSupplyShares_ - shares_;
640:
641:
642:
643: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
644:
645:
646:
647: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
648: } else {
649: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
650: }
651:
652:
653: dexVariables = dexVariables_;
654:
655: emit LogWithdrawPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
656: }
['665']
665: function borrowPerfect(
666: uint shares_,
667: uint minToken0Borrow_,
668: uint minToken1Borrow_,
669: bool estimate_
670: ) public returns (uint token0Amt_, uint token1Amt_) {
671: uint dexVariables_ = dexVariables;
672: uint dexVariables2_ = dexVariables2;
673:
674: _check(dexVariables_, dexVariables2_);
675:
676: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
677:
678:
679: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
680:
681:
682: if (((dexVariables2_ >> 1) & 1) == 1) {
683: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
684:
685: uint totalBorrowShares_ = _totalBorrowShares;
686:
687: _verifyMint(shares_, totalBorrowShares_);
688:
689:
690: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
691: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
692:
693: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
694: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
695:
696: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
697:
698: if (token0Amt_ < minToken0Borrow_ || token1Amt_ < minToken1Borrow_) {
699: revert FluidDexError(ErrorTypes.DexT1__BelowBorrowMin);
700: }
701:
702:
703: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
704: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
705:
706:
707: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
708:
709: userBorrow_ += shares_;
710:
711:
712: if (userBorrow_ > newBorrowLimit_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached);
713:
714:
715:
716: LIQUIDITY.operate(TOKEN_0, 0, int(token0Amt_), address(0), msg.sender, new bytes(0)); // <= FOUND
717:
718:
719:
720: LIQUIDITY.operate(TOKEN_1, 0, int(token1Amt_), address(0), msg.sender, new bytes(0)); // <= FOUND
721:
722: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
723:
724: _totalBorrowShares = totalBorrowShares_ + shares_;
725: } else {
726: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
727: }
728:
729:
730: dexVariables = dexVariables_;
731:
732: emit LogBorrowPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
733: }
['742']
742: function paybackPerfect(
743: uint shares_,
744: uint maxToken0Payback_,
745: uint maxToken1Payback_,
746: bool estimate_
747: ) public payable returns (uint token0Amt_, uint token1Amt_) {
748: uint dexVariables_ = dexVariables;
749: uint dexVariables2_ = dexVariables2;
750:
751: _check(dexVariables_, dexVariables2_);
752:
753: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
754:
755: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
756:
757:
758: if (((dexVariables2_ >> 1) & 1) == 1) {
759: uint totalBorrowShares_ = _totalBorrowShares;
760:
761: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
762:
763: _verifyRedeem(shares_, totalBorrowShares_);
764:
765:
766: token0Amt_ = (_getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true) * shares_) / totalBorrowShares_;
767: token1Amt_ = (_getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false) * shares_) / totalBorrowShares_;
768:
769: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
770: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
771:
772: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
773:
774: if (token0Amt_ > maxToken0Payback_ || token1Amt_ > maxToken1Payback_) {
775: revert FluidDexError(ErrorTypes.DexT1__AbovePaybackMax);
776: }
777:
778: _depositOrPaybackInLiquidity(TOKEN_0, 0, token0Amt_);
779:
780: _depositOrPaybackInLiquidity(TOKEN_1, 0, token1Amt_);
781:
782:
783: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
784: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
785:
786:
787: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
788:
789: userBorrow_ -= shares_;
790:
791: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, newBorrowLimit_);
792:
793: _totalBorrowShares = totalBorrowShares_ - shares_;
794: } else {
795: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
796: }
797:
798:
799: dexVariables = dexVariables_;
800:
801: emit LogPaybackPerfectDebtLiquidity(shares_, token0Amt_, token1Amt_);
802: }
['810']
810: function deposit(
811: uint token0Amt_,
812: uint token1Amt_,
813: uint minSharesAmt_,
814: bool estimate_
815: ) public payable returns (uint shares_) {
816: uint dexVariables_ = dexVariables;
817: uint dexVariables2_ = dexVariables2;
818:
819: _check(dexVariables_, dexVariables2_);
820:
821: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
822:
823: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
824:
825:
826: if ((dexVariables2_ & 1) == 1) {
827: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
828:
829: DepositColMemory memory d_;
830:
831: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
832: CollateralReserves memory c2_ = c_;
833:
834: if (token0Amt_ > 0) {
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
836: _verifySwapAndNonPerfectActions(d_.token0AmtAdjusted, token0Amt_);
837: _verifyMint(d_.token0AmtAdjusted, c_.token0RealReserves);
838: }
839:
840: if (token1Amt_ > 0) {
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
842: _verifySwapAndNonPerfectActions(d_.token1AmtAdjusted, token1Amt_);
843: _verifyMint(d_.token1AmtAdjusted, c_.token1RealReserves);
844: }
845:
846: uint temp_;
847: uint temp2_;
848:
849: uint totalSupplyShares_ = _totalSupplyShares;
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) {
851:
852: shares_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
853: totalSupplyShares_ += shares_;
854: } else if ((d_.token1AmtAdjusted > 0 && d_.token0AmtAdjusted == 0) && (c_.token1RealReserves > 0) && (c_.token0RealReserves == 0)) {
855:
856: shares_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
857: totalSupplyShares_ += shares_;
858: } else {
859: if (d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted > 0) {
860:
861:
862: temp_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
863:
864: temp2_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
865: if (temp_ > temp2_) {
866:
867: shares_ = (temp2_ * totalSupplyShares_) / 1e18;
868:
869: temp_ = ((temp_ - temp2_) * c_.token0RealReserves) / 1e18;
870: temp2_ = 0;
871: } else if (temp2_ > temp_) {
872:
873: shares_ = (temp_ * totalSupplyShares_) / 1e18;
874:
875: temp2_ = ((temp2_ - temp_) * c_.token1RealReserves) / 1e18;
876: temp_ = 0;
877: } else {
878:
879: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
880: }
881:
882:
883: c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, true);
884:
885: totalSupplyShares_ += shares_;
886: } else if (d_.token0AmtAdjusted > 0) {
887: temp_ = d_.token0AmtAdjusted;
888: temp2_ = 0;
889: } else if (d_.token1AmtAdjusted > 0) {
890: temp_ = 0;
891: temp2_ = d_.token1AmtAdjusted;
892: } else {
893:
894: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
895: }
896:
897: if (temp_ > 0) {
898:
899: temp_ = _getSwapAndDeposit(
900: temp_,
901: c2_.token1ImaginaryReserves,
902: c2_.token0ImaginaryReserves,
903: c2_.token0RealReserves,
904: c2_.token1RealReserves
905: );
906: } else if (temp2_ > 0) {
907:
908: temp_ = _getSwapAndDeposit(
909: temp2_,
910: c2_.token0ImaginaryReserves,
911: c2_.token1ImaginaryReserves,
912: c2_.token1RealReserves,
913: c2_.token0RealReserves
914: );
915: } else {
916:
917: revert FluidDexError(ErrorTypes.DexT1__DepositAmtsZero);
918: }
919:
920:
921: temp_ = temp_ * totalSupplyShares_ / 1e18;
922:
923:
924:
925: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
926:
927: shares_ += temp_;
928:
929: totalSupplyShares_ += temp_;
930: }
931:
932: if (estimate_) revert FluidDexLiquidityOutput(shares_);
933:
934: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__SharesMintedLess);
935:
936: if (token0Amt_ > 0) {
937: _verifyToken1Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
938: temp_ = token0Amt_;
939: _depositOrPaybackInLiquidity(TOKEN_0, temp_, 0);
940: }
941:
942: if (token1Amt_ > 0) {
943: _verifyToken0Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
944: temp_ = token1Amt_;
945: _depositOrPaybackInLiquidity(TOKEN_1, temp_, 0);
946: }
947:
948:
949: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
950:
951: temp_ = ((temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK));
952:
953:
954:
955: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
956:
957: temp_ += shares_;
958:
959: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
960:
961:
962: _totalSupplyShares = totalSupplyShares_;
963:
964: emit LogDepositColLiquidity(token0Amt_, token1Amt_, shares_);
965:
966: _arbitrage(dexVariables_, dexVariables2_, pex_);
967: } else {
968: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
969: }
970: }
['978']
978: function withdraw(
979: uint token0Amt_,
980: uint token1Amt_,
981: uint maxSharesAmt_,
982: bool estimate_
983: ) public returns (uint shares_) {
984: uint dexVariables_ = dexVariables;
985: uint dexVariables2_ = dexVariables2;
986:
987: _check(dexVariables_, dexVariables2_);
988:
989: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
990:
991: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
992:
993:
994: if ((dexVariables2_ & 1) == 1) {
995: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
996:
997: WithdrawColMemory memory w_;
998:
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true);
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false);
1001: w_.token0ReservesInitial = token0Reserves_;
1002: w_.token1ReservesInitial = token1Reserves_;
1003:
1004: if (token0Amt_ > 0) {
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1006: _verifySwapAndNonPerfectActions(w_.token0AmtAdjusted, token0Amt_);
1007: _verifyRedeem(w_.token0AmtAdjusted, token0Reserves_);
1008: }
1009:
1010: if (token1Amt_ > 0) {
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1012: _verifySwapAndNonPerfectActions(w_.token1AmtAdjusted, token1Amt_);
1013: _verifyRedeem(w_.token1AmtAdjusted, token1Reserves_);
1014: }
1015:
1016: uint temp_;
1017: uint temp2_;
1018:
1019: uint totalSupplyShares_ = _totalSupplyShares;
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) {
1021:
1022: shares_ = (w_.token0AmtAdjusted * 1e18 / token0Reserves_);
1023: totalSupplyShares_ -= shares_;
1024: } else if ((w_.token1AmtAdjusted > 0 && w_.token0AmtAdjusted == 0) && (token1Reserves_ > 0) && (token0Reserves_ == 0)) {
1025:
1026: shares_ = (w_.token1AmtAdjusted * 1e18 / token1Reserves_);
1027: totalSupplyShares_ -= shares_;
1028: } else {
1029: if (w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted > 0) {
1030:
1031:
1032: temp_ = w_.token0AmtAdjusted * 1e18 / token0Reserves_;
1033:
1034: temp2_ = w_.token1AmtAdjusted * 1e18 / token1Reserves_;
1035: if (temp_ > temp2_) {
1036:
1037: shares_ = ((temp2_ * totalSupplyShares_) / 1e18);
1038:
1039: temp_ = ((temp_ - temp2_) * token0Reserves_) / 1e18;
1040: temp2_ = 0;
1041: } else if (temp2_ > temp_) {
1042:
1043: shares_ = ((temp_ * totalSupplyShares_) / 1e18);
1044:
1045: temp2_ = ((temp2_ - temp_) * token1Reserves_) / 1e18;
1046: temp_ = 0;
1047: } else {
1048:
1049: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1050: }
1051:
1052:
1053: token0Reserves_ = token0Reserves_ - (token0Reserves_ * shares_ / totalSupplyShares_);
1054: token1Reserves_ = token1Reserves_ - (token1Reserves_ * shares_ / totalSupplyShares_);
1055: totalSupplyShares_ -= shares_;
1056: } else if (w_.token0AmtAdjusted > 0) {
1057: temp_ = w_.token0AmtAdjusted;
1058: temp2_ = 0;
1059: } else if (w_.token1AmtAdjusted > 0) {
1060: temp_ = 0;
1061: temp2_ = w_.token1AmtAdjusted;
1062: } else {
1063:
1064: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1065: }
1066:
1067: uint token0ImaginaryReservesOutsideRangpex_;
1068: uint token1ImaginaryReservesOutsideRangpex_;
1069:
1070: if (pex_.geometricMean < 1e27) {
1071: (token0ImaginaryReservesOutsideRangpex_, token1ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange(pex_.geometricMean, pex_.upperRange, (token0Reserves_ - temp_), (token1Reserves_ - temp2_));
1072: } else {
1073:
1074:
1075:
1076:
1077: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_));
1078: }
1079:
1080: if (temp_ > 0) {
1081:
1082: temp_ = _getWithdrawAndSwap(
1083: token0Reserves_,
1084: token1Reserves_,
1085: token0ImaginaryReservesOutsideRangpex_,
1086: token1ImaginaryReservesOutsideRangpex_,
1087: temp_
1088: );
1089: } else if (temp2_ > 0) {
1090:
1091: temp_ = _getWithdrawAndSwap(
1092: token1Reserves_,
1093: token0Reserves_,
1094: token1ImaginaryReservesOutsideRangpex_,
1095: token0ImaginaryReservesOutsideRangpex_,
1096: temp2_
1097: );
1098: } else {
1099:
1100: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1101: }
1102:
1103:
1104: temp_ = (temp_ * totalSupplyShares_ / 1e18);
1105:
1106:
1107: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1108:
1109: shares_ += temp_;
1110:
1111: totalSupplyShares_ -= temp_;
1112: }
1113:
1114: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1115:
1116: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__WithdrawExcessSharesBurn);
1117:
1118:
1119: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1120: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1121:
1122:
1123:
1124: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
1125:
1126: temp_ -= shares_;
1127:
1128:
1129: if (temp_ < temp2_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1130:
1131: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
1132:
1133:
1134: _totalSupplyShares = totalSupplyShares_;
1135:
1136: if (w_.token0AmtAdjusted > 0) {
1137: _verifyToken0Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1138:
1139: temp_ = token0Amt_;
1140: LIQUIDITY.operate(TOKEN_0, -int(temp_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1141: }
1142:
1143: if (w_.token1AmtAdjusted > 0) {
1144: _verifyToken1Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1145:
1146: temp_ = token1Amt_;
1147: LIQUIDITY.operate(TOKEN_1, -int(temp_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1148: }
1149:
1150: emit LogWithdrawColLiquidity(token0Amt_, token1Amt_, shares_);
1151:
1152: _arbitrage(dexVariables_, dexVariables2_, pex_);
1153: } else {
1154: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1155: }
1156:
1157: }
['1165']
1165: function borrow(
1166: uint token0Amt_,
1167: uint token1Amt_,
1168: uint maxSharesAmt_,
1169: bool estimate_
1170: ) public returns (uint shares_) {
1171: uint dexVariables_ = dexVariables;
1172: uint dexVariables2_ = dexVariables2;
1173:
1174: _check(dexVariables_, dexVariables2_);
1175:
1176: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1177:
1178: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1179:
1180:
1181: if (((dexVariables2_ >> 1) & 1) == 1) {
1182: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1183:
1184: BorrowDebtMemory memory b_;
1185:
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true);
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false);
1188: b_.token0DebtInitial = token0Debt_;
1189: b_.token1DebtInitial = token1Debt_;
1190:
1191: if (token0Amt_ > 0) {
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1193: _verifySwapAndNonPerfectActions(b_.token0AmtAdjusted, token0Amt_);
1194: _verifyMint(b_.token0AmtAdjusted, token0Debt_);
1195: }
1196:
1197: if (token1Amt_ > 0) {
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1199: _verifySwapAndNonPerfectActions(b_.token1AmtAdjusted, token1Amt_);
1200: _verifyMint(b_.token1AmtAdjusted, token1Debt_);
1201: }
1202:
1203: uint temp_;
1204: uint temp2_;
1205:
1206: uint totalBorrowShares_ = _totalBorrowShares;
1207: if ((b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted == 0) && (token0Debt_ > 0) && (token1Debt_ == 0)) {
1208:
1209: shares_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1210: totalBorrowShares_ += shares_;
1211: } else if ((b_.token1AmtAdjusted > 0 && b_.token0AmtAdjusted == 0) && (token1Debt_ > 0) && (token0Debt_ == 0)) {
1212:
1213: shares_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1214: totalBorrowShares_ += shares_;
1215: } else {
1216: if (b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted > 0) {
1217:
1218:
1219: temp_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1220:
1221: temp2_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1222: if (temp_ > temp2_) {
1223:
1224: shares_ = (temp2_ * totalBorrowShares_) / 1e18;
1225:
1226: temp_ = ((temp_ - temp2_) * token0Debt_) / 1e18;
1227: temp2_ = 0;
1228: } else if (temp2_ > temp_) {
1229:
1230: shares_ = (temp_ * totalBorrowShares_) / 1e18;
1231:
1232: temp2_ = ((temp2_ - temp_) * token1Debt_) / 1e18;
1233: temp_ = 0;
1234: } else {
1235:
1236: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1237: }
1238:
1239:
1240: token0Debt_ = token0Debt_ + token0Debt_ * shares_ / totalBorrowShares_;
1241: token1Debt_ = token1Debt_ + token1Debt_ * shares_ / totalBorrowShares_;
1242: totalBorrowShares_ += shares_;
1243: } else if (b_.token0AmtAdjusted > 0) {
1244: temp_ = b_.token0AmtAdjusted;
1245: temp2_ = 0;
1246: } else if (b_.token1AmtAdjusted > 0) {
1247: temp_ = 0;
1248: temp2_ = b_.token1AmtAdjusted;
1249: } else {
1250:
1251: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1252: }
1253:
1254: uint token0FinalImaginaryReserves_;
1255: uint token1FinalImaginaryReserves_;
1256:
1257: if (pex_.geometricMean < 1e27) {
1258: (, , token0FinalImaginaryReserves_, token1FinalImaginaryReserves_) =
1259: _calculateDebtReserves(pex_.geometricMean, pex_.lowerRange, (token0Debt_ + temp_), (token1Debt_ + temp2_));
1260: } else {
1261:
1262:
1263:
1264:
1265: (, , token1FinalImaginaryReserves_, token0FinalImaginaryReserves_) =
1266: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_));
1267: }
1268:
1269: if (temp_ > 0) {
1270:
1271: temp_ = _getBorrowAndSwap(
1272: token0Debt_,
1273: token1Debt_,
1274: token0FinalImaginaryReserves_,
1275: token1FinalImaginaryReserves_,
1276: temp_
1277: );
1278: } else if (temp2_ > 0) {
1279:
1280: temp_ = _getBorrowAndSwap(
1281: token1Debt_,
1282: token0Debt_,
1283: token1FinalImaginaryReserves_,
1284: token0FinalImaginaryReserves_,
1285: temp2_
1286: );
1287: } else {
1288:
1289: revert FluidDexError(ErrorTypes.DexT1__BorrowAmtsZero);
1290: }
1291:
1292:
1293: temp_ = temp_ * totalBorrowShares_ / 1e18;
1294:
1295:
1296: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1297:
1298: shares_ += temp_;
1299:
1300: totalBorrowShares_ += temp_;
1301: }
1302:
1303: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1304:
1305: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__BorrowExcessSharesMinted);
1306:
1307:
1308:
1309: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1310: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1311:
1312:
1313:
1314: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1315:
1316: temp_ += shares_;
1317:
1318:
1319: if (temp_ > temp2_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached);
1320:
1321: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1322:
1323: if (b_.token0AmtAdjusted > 0) {
1324:
1325: _verifyToken1Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1326:
1327: temp_ = token0Amt_;
1328:
1329: LIQUIDITY.operate(TOKEN_0, 0, int(temp_), address(0), msg.sender, new bytes(0)); // <= FOUND
1330: }
1331:
1332: if (b_.token1AmtAdjusted > 0) {
1333:
1334: _verifyToken0Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1335:
1336: temp_ = token1Amt_;
1337:
1338: LIQUIDITY.operate(TOKEN_1, 0, int(temp_), address(0), msg.sender, new bytes(0)); // <= FOUND
1339: }
1340:
1341:
1342: _totalBorrowShares = totalBorrowShares_;
1343:
1344: emit LogBorrowDebtLiquidity(token0Amt_, token1Amt_, shares_);
1345:
1346: _arbitrage(dexVariables_, dexVariables2_, pex_);
1347: } else {
1348: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1349: }
1350:
1351: }
['1359']
1359: function payback(
1360: uint token0Amt_,
1361: uint token1Amt_,
1362: uint minSharesAmt_,
1363: bool estimate_
1364: ) public payable returns (uint shares_) {
1365: uint dexVariables_ = dexVariables;
1366: uint dexVariables2_ = dexVariables2;
1367:
1368: _check(dexVariables_, dexVariables2_);
1369:
1370: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1371:
1372: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1373:
1375:
1376: if (((dexVariables2_ >> 1) & 1) == 1) {
1377: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1378:
1379: PaybackDebtMemory memory p_;
1380:
1381: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1382: DebtReserves memory d2_ = d_;
1383:
1384: if (token0Amt_ > 0) {
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
1386: _verifySwapAndNonPerfectActions(p_.token0AmtAdjusted, token0Amt_);
1387: _verifyRedeem(p_.token0AmtAdjusted, d_.token0Debt);
1388: }
1389:
1390: if (token1Amt_ > 0) {
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
1392: _verifySwapAndNonPerfectActions(p_.token1AmtAdjusted, token1Amt_);
1393: _verifyRedeem(p_.token1AmtAdjusted, d_.token1Debt);
1394: }
1395:
1396: uint temp_;
1397: uint temp2_;
1398:
1399: uint totalBorrowShares_ = _totalBorrowShares;
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) {
1401:
1402: shares_ = (p_.token0AmtAdjusted * 1e18 / d_.token0Debt);
1403: totalBorrowShares_ -= shares_;
1404: } else if ((p_.token1AmtAdjusted > 0 && p_.token0AmtAdjusted == 0) && (d_.token1Debt > 0) && (d_.token0Debt == 0)) {
1405:
1406: shares_ = (p_.token1AmtAdjusted * 1e18 / d_.token1Debt);
1407: totalBorrowShares_ -= shares_;
1408: } else {
1409: if (p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted > 0) {
1410:
1411:
1412: temp_ = p_.token0AmtAdjusted * 1e18 / d_.token0Debt;
1413:
1414: temp2_ = p_.token1AmtAdjusted * 1e18 / d_.token1Debt;
1415: if (temp_ > temp2_) {
1416:
1417: shares_ = ((temp2_ * totalBorrowShares_) / 1e18);
1418:
1419: temp_ = p_.token0AmtAdjusted - (temp2_ * p_.token0AmtAdjusted) / temp_;
1420: temp2_ = 0;
1421: } else if (temp2_ > temp_) {
1422:
1423: shares_ = ((temp_ * totalBorrowShares_) / 1e18);
1424:
1425: temp2_ = p_.token1AmtAdjusted - ((temp_ * p_.token1AmtAdjusted) / temp2_);
1426: temp_ = 0;
1427: } else {
1428:
1429: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1430: }
1431:
1432:
1433: d2_ = _getUpdateDebtReserves(
1434: shares_,
1435: totalBorrowShares_,
1436: d_,
1437: false
1438: );
1439: totalBorrowShares_ -= shares_;
1440: } else if (p_.token0AmtAdjusted > 0) {
1441: temp_ = p_.token0AmtAdjusted;
1442: temp2_ = 0;
1443: } else if (p_.token1AmtAdjusted > 0) {
1444: temp_ = 0;
1445: temp2_ = p_.token1AmtAdjusted;
1446: } else {
1447:
1448: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1449: }
1450:
1451: if (temp_ > 0) {
1452:
1453: temp_ = _getSwapAndPayback(
1454: d2_.token0Debt,
1455: d2_.token1Debt,
1456: d2_.token0ImaginaryReserves,
1457: d2_.token1ImaginaryReserves,
1458: temp_
1459: );
1460: } else if (temp2_ > 0) {
1461:
1462: temp_ = _getSwapAndPayback(
1463: d2_.token1Debt,
1464: d2_.token0Debt,
1465: d2_.token1ImaginaryReserves,
1466: d2_.token0ImaginaryReserves,
1467: temp2_
1468: );
1469: } else {
1470:
1471: revert FluidDexError(ErrorTypes.DexT1__PaybackAmtsZero);
1472: }
1473:
1474:
1475: temp_ = (temp_ * totalBorrowShares_ / 1e18);
1476:
1477:
1478:
1479: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1480:
1481: shares_ += temp_;
1482:
1483: totalBorrowShares_ -= temp_;
1484: }
1485:
1486: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1487:
1488: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__PaybackSharedBurnedLess);
1489:
1490: if (token0Amt_ > 0) {
1491:
1492: _verifyToken0Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1493:
1494: temp_ = token0Amt_;
1495: _depositOrPaybackInLiquidity(TOKEN_0, 0, temp_);
1496: }
1497:
1498: if (token1Amt_ > 0) {
1499:
1500: _verifyToken1Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1501:
1502: temp_ = token1Amt_;
1503: _depositOrPaybackInLiquidity(TOKEN_1, 0, temp_);
1504: }
1505:
1506:
1507:
1508: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1509: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1510:
1511:
1512:
1513: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1514:
1515: temp_ -= shares_;
1516:
1517: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1518:
1519: _totalBorrowShares = totalBorrowShares_;
1520:
1521: emit LogPaybackDebtLiquidity(token0Amt_, token1Amt_, shares_);
1522:
1523: _arbitrage(dexVariables_, dexVariables2_, pex_);
1524: } else {
1525: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1526: }
1527: }
['1535']
1535: function withdrawPerfectInOneToken(
1536: uint shares_,
1537: uint minToken0_,
1538: uint minToken1_,
1539: bool estimate_
1540: ) public returns (uint withdrawAmt_) {
1541: uint dexVariables_ = dexVariables;
1542: uint dexVariables2_ = dexVariables2;
1543:
1544: _check(dexVariables_, dexVariables2_);
1545:
1546: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
1547:
1548: if (userSupplyData_ & 1 == 0 && !estimate_) {
1549: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
1550: }
1551:
1552: if ((minToken0_ > 0 && minToken1_ > 0) || (minToken0_ == 0 && minToken1_ == 0)) {
1553:
1554: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1555: }
1556:
1557:
1558: if ((dexVariables2_ & 1) == 1) {
1559: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1560:
1561: uint totalSupplyShares_ = _totalSupplyShares;
1562:
1563: _verifyRedeem(shares_, totalSupplyShares_);
1564:
1565: uint token0Amt_;
1566: uint token1Amt_;
1567:
1568: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1569: CollateralReserves memory c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, false);
1570:
1571: token0Amt_ = c_.token0RealReserves - c2_.token0RealReserves - 1;
1572: token1Amt_ = c_.token1RealReserves - c2_.token1RealReserves - 1;
1573:
1574: if (minToken0_ > 0) {
1575:
1576: token0Amt_ += _getAmountOut(token1Amt_, c2_.token1ImaginaryReserves, c2_.token0ImaginaryReserves);
1577: token1Amt_ = 0;
1578: _verifyToken0Reserves((c_.token0RealReserves - token0Amt_), c_.token1RealReserves, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1579:
1580:
1581: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
1582:
1583:
1584: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1585:
1586: withdrawAmt_ = token0Amt_;
1587: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1588: if (withdrawAmt_ < minToken0_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1589: } else {
1590:
1591: token1Amt_ += _getAmountOut(token0Amt_, c2_.token0ImaginaryReserves, c2_.token1ImaginaryReserves);
1592: token0Amt_ = 0;
1593: _verifyToken1Reserves(c_.token0RealReserves, (c_.token1RealReserves - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1594:
1595:
1596: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
1597:
1598:
1599: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1600:
1601: withdrawAmt_ = token1Amt_;
1602: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1603: if (withdrawAmt_ < minToken1_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1604: }
1605:
1606: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1607: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
1608:
1609:
1610:
1611: uint256 temp_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
1612:
1613: userSupply_ -= shares_;
1614:
1615:
1616: if (userSupply_ < temp_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1617:
1618: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, temp_);
1619:
1620: _totalSupplyShares = totalSupplyShares_ - shares_;
1621:
1622: if (minToken0_ > 0) {
1623:
1624: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1625: } else {
1626:
1627: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0)); // <= FOUND
1628: }
1629:
1630:
1631: temp_ = shares_;
1632: emit LogWithdrawColInOneToken(temp_, token0Amt_, token1Amt_);
1633:
1634: _arbitrage(dexVariables_, dexVariables2_, pex_);
1635: } else {
1636: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1637: }
1638: }
['1646']
1646: function paybackPerfectInOneToken(
1647: uint shares_,
1648: uint maxToken0_,
1649: uint maxToken1_,
1650: bool estimate_
1651: ) public payable returns (uint paybackAmt_) {
1652: uint dexVariables_ = dexVariables;
1653: uint dexVariables2_ = dexVariables2;
1654:
1655: _check(dexVariables_, dexVariables2_);
1656:
1657: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1658:
1659: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1660:
1661: if ((maxToken0_ > 0 && maxToken1_ > 0) || (maxToken0_ == 0 && maxToken1_ == 0)) {
1662:
1663: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1664: }
1665:
1666:
1667: if (((dexVariables2_ >> 1) & 1) == 1) {
1668: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1669:
1670: uint totalBorrowShares_ = _totalBorrowShares;
1671:
1672: _verifyRedeem(shares_, totalBorrowShares_);
1673:
1674: uint token0Amt_;
1675: uint token1Amt_;
1676:
1677:
1678: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1679:
1680: DebtReserves memory d2_ = _getUpdateDebtReserves(shares_, totalBorrowShares_, d_, false);
1681:
1682: if (maxToken0_ > 0) {
1683:
1684: token0Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1685: d2_.token0ImaginaryReserves,
1686: d2_.token1ImaginaryReserves,
1687: d_.token0Debt,
1688: d_.token1Debt,
1689: d2_.token0RealReserves,
1690: d2_.token1RealReserves
1691: );
1692: _verifyToken0Reserves((d_.token0Debt - token0Amt_), d_.token1Debt, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1693:
1694:
1695: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
1696:
1697:
1698: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1699:
1700: paybackAmt_ = token0Amt_;
1701: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1702: if (paybackAmt_ > maxToken0_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1703: _depositOrPaybackInLiquidity(TOKEN_0, 0, paybackAmt_);
1704: } else {
1705:
1706: token1Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1707: d2_.token1ImaginaryReserves,
1708: d2_.token0ImaginaryReserves,
1709: d_.token1Debt,
1710: d_.token0Debt,
1711: d2_.token1RealReserves,
1712: d2_.token0RealReserves
1713: );
1714: _verifyToken1Reserves(d_.token0Debt, (d_.token1Debt - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1715:
1716:
1717: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
1718:
1719:
1720: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1721:
1722: paybackAmt_ = token1Amt_;
1723: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1724: if (paybackAmt_ > maxToken1_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1725: _depositOrPaybackInLiquidity(TOKEN_1, 0, paybackAmt_);
1726: }
1727:
1728:
1729: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1730: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
1731:
1732:
1733:
1734: uint256 temp_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
1735: userBorrow_ -= shares_;
1736:
1737: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, temp_);
1738:
1739: _totalBorrowShares = totalBorrowShares_ - shares_;
1740:
1741:
1742: temp_ = shares_;
1743: emit LogPaybackDebtInOneToken(temp_, token0Amt_, token1Amt_);
1744:
1745: _arbitrage(dexVariables_, dexVariables2_, pex_);
1746: } else {
1747: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1748: }
1749: }
If these serve no purpose, they should be safely removed
Num of instances: 4
Click to show findings
['30']
30: uint256 internal constant X5 = 0x1f; // <= FOUND
['35']
35: uint256 internal constant X11 = 0x7ff; // <= FOUND
['42']
42: uint256 internal constant X23 = 0x7fffff; // <= FOUND
['61']
61: uint256 internal constant PRICE_PRECISION = 1e27; // <= FOUND
Putting constants on the left side of a comparison operator like ==
or <
is a best practice known as "Yoda conditions", which can help prevent accidental assignment instead of comparison. In some programming languages, if a variable is mistakenly put on the left with a single =
instead of ==
, it assigns the constant's value to the variable without any compiler error. However, doing this with the constant on the left would generate an error, as constants cannot be assigned values. Although Solidity's static typing system prevents accidental assignments within conditionals, adopting this practice enhances code readability and consistency, especially when developers are working across multiple languages that support this convention.
Num of instances: 102
Click to show findings
['525']
525: if (userSupplyData_ & 1 == 0 && !estimate_) // <= FOUND
['1552']
1552: if ((minToken0_ > 0 && minToken1_ > 0) || (minToken0_ == 0 && minToken1_ == 0)) // <= FOUND
['1661']
1661: if ((maxToken0_ > 0 && maxToken1_ > 0) || (maxToken0_ == 0 && maxToken1_ == 0)) // <= FOUND
['2069']
2069: if (msg.sig != 0x00000000) // <= FOUND
['222']
222: if (((dexVariables2_ >> 248) & 1) == 0) // <= FOUND
['40']
40: if ((dexVariables2 & X3) == 0) // <= FOUND
['49']
49: if (value_.code.length == 0 && value_ != NATIVE_TOKEN) // <= FOUND
['56']
56: if (value_.code.length == 0) // <= FOUND
['201']
201: if (
202: (upperPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
203: (lowerPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
204: (upperPercent_ == 0) || // <= FOUND
205: (lowerPercent_ == 0) || // <= FOUND
206: (shiftTime_ > X20) ||
207: (((dexVariables2_ >> 26) & 1) == 1) // <= FOUND
208: )
['244']
244: if (
245: (upperThresholdPercent_ > THREE_DECIMALS) ||
246: (lowerThresholdPercent_ > THREE_DECIMALS) ||
247: (thresholdShiftTime_ == 0) || // <= FOUND
248: (thresholdShiftTime_ > X24) ||
249: (upperThresholdPercent_ == 0) || // <= FOUND
250: (lowerThresholdPercent_ == 0) || // <= FOUND
251: (shiftTime_ > X20) ||
252: (((dexVariables2_ >> 67) & 1) == 1) // <= FOUND
253: )
['283']
283: if (
284: (centerPriceAddress_ > X30) ||
285: (percent_ == 0) || // <= FOUND
286: (percent_ > X20) ||
287: (time_ == 0) || // <= FOUND
288: (time_ > X20)
289: )
['336']
336: if (
337: (maxCenterPrice_ <= minCenterPrice_) ||
338: (centerPrice_ <= minCenterPrice_) ||
339: (centerPrice_ >= maxCenterPrice_) ||
340: (minCenterPrice_ == 0) // <= FOUND
341: )
['436']
436: if (userSupplyData_ == 0) // <= FOUND
['448']
448: if (newLimit_ == 0 || newLimit_ < maxExpansionLimit_) // <= FOUND
['558']
558: if (userData_ == 0) // <= FOUND
['646']
646: if (
647: (i_.fee > FIVE_DECIMALS) ||
648: (i_.revenueCut > TWO_DECIMALS) ||
649: (i_.upperPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
650: (i_.lowerPercent > (SIX_DECIMALS - FOUR_DECIMALS)) ||
651: (i_.upperPercent == 0) || // <= FOUND
652: (i_.lowerPercent == 0) || // <= FOUND
653: (i_.upperShiftThreshold > THREE_DECIMALS) ||
654: (i_.lowerShiftThreshold > THREE_DECIMALS) ||
655: (i_.upperShiftThreshold == 0) || // <= FOUND
656: (i_.lowerShiftThreshold == 0) || // <= FOUND
657: (i_.thresholdShiftTime == 0) || // <= FOUND
658: (i_.thresholdShiftTime > X24) ||
659: (i_.centerPriceAddress > X30) ||
660: (i_.hookAddress > X30) ||
661: (i_.centerPrice <= i_.minCenterPrice) ||
662: (i_.centerPrice >= i_.maxCenterPrice) ||
663: (i_.minCenterPrice == 0) // <= FOUND
664: )
['739']
739: if ((dexVariables2_ >> 255) == 0) // <= FOUND
['850']
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) // <= FOUND
['1020']
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) // <= FOUND
['1207']
1207: if ((b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted == 0) && (token0Debt_ > 0) && (token1Debt_ == 0)) // <= FOUND
['1400']
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) // <= FOUND
['225']
225: if (centerPrice_ == 0) // <= FOUND
['390']
390: if (userSupplyConfigs_[i].baseWithdrawalLimit == 0) // <= FOUND
['506']
506: if (userBorrowConfigs_[i].baseDebtCeiling == 0 || userBorrowConfigs_[i].maxDebtCeiling == 0) // <= FOUND
['558']
558: if (userData_ == 0) // <= FOUND
['561']
561: if (userData_ & 1 == 0) // <= FOUND
['1927']
1927: if (o_.oracleMap == 0) // <= FOUND
['1942']
1942: if (o_.oracleMap == 0) // <= FOUND
['2006']
2006: if (time_ == 0) // <= FOUND
['164']
164: if (temp_ == 1 && temp2_ == 1) // <= FOUND
['164']
164: if (temp_ == 1 && temp2_ == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['682']
682: if (((dexVariables2_ >> 1) & 1) == 1) // <= FOUND
['682']
682: if (((dexVariables2_ >> 1) & 1) == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['682']
682: if (((dexVariables2_ >> 1) & 1) == 1) // <= FOUND
['682']
682: if (((dexVariables2_ >> 1) & 1) == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['243']
243: if (((dexVariables2_ >> 26) & 1) == 1) // <= FOUND
['312']
312: if (((dexVariables2_ >> 26) & 1) == 1) // <= FOUND
['409']
409: if (tokenSupplyData_ & 1 == 1) // <= FOUND
['587']
587: if (tokenBorrowData_ & 1 == 1) // <= FOUND
['64']
64: if (dexVariables2 & 1 == 1) // <= FOUND
['81']
81: if ((dexVariables2_ >> 255) == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['528']
528: if ((dexVariables2_ & 1) == 1) // <= FOUND
['682']
682: if (((dexVariables2_ >> 1) & 1) == 1) // <= FOUND
['260']
260: if (((dexVariables2_ >> 67) & 1) == 1) // <= FOUND
['599']
599: if (userData_ & 1 == 1) // <= FOUND
['127']
127: if (temp_ == 1) // <= FOUND
['141']
141: if (temp2_ == 1) // <= FOUND
['1767']
1767: if ((dexVariables2_ & 2) == 2) // <= FOUND
['1924']
1924: if (j == 2) // <= FOUND
['129']
129: if (dexVariables2 & 2 == 2) // <= FOUND
['1861']
1861: if (data_.length == 64) // <= FOUND
['1925']
1925: if (++o_.oracleSlot == 8) // <= FOUND
['101']
101: if (msg.value > 0) // <= FOUND
['174']
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) // <= FOUND
['201']
201: if (temp_ > 0) // <= FOUND
['208']
208: if (temp3_ > 0) // <= FOUND
['201']
201: if (temp_ > 0) // <= FOUND
['101']
101: if (msg.value > 0) // <= FOUND
['387']
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) // <= FOUND
['201']
201: if (temp_ > 0) // <= FOUND
['208']
208: if (temp3_ > 0) // <= FOUND
['1574']
1574: if (minToken0_ > 0) // <= FOUND
['1682']
1682: if (maxToken0_ > 0) // <= FOUND
['1792']
1792: if (a_ > 0) // <= FOUND
['201']
201: if (temp_ > 0) // <= FOUND
['256']
256: if (((dexVariables2_ >> 68) & X20) > 0) // <= FOUND
['1157']
1157: if (timeDiff_ > 0) // <= FOUND
['220']
220: if (shiftTime_ > 0) // <= FOUND
['220']
220: if (shiftTime_ > 0) // <= FOUND
['293']
293: if (centerPriceAddress_ > 0) // <= FOUND
['320']
320: if (hookAddress_ > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['1136']
1136: if (w_.token0AmtAdjusted > 0) // <= FOUND
['1143']
1143: if (w_.token1AmtAdjusted > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['1323']
1323: if (b_.token0AmtAdjusted > 0) // <= FOUND
['1332']
1332: if (b_.token1AmtAdjusted > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['834']
834: if (token0Amt_ > 0) // <= FOUND
['840']
840: if (token1Amt_ > 0) // <= FOUND
['1574']
1574: if (minToken0_ > 0) // <= FOUND
['1208']
1208: if (nextOracleSlot_ > 0) // <= FOUND
['1203']
1203: if (nextOracleSlot_ > 0) // <= FOUND
['1914']
1914: if (((dexVariables_ >> 121) & X33) < block.timestamp) // <= FOUND
['1185']
1185: if (priceDiff_ < 0) // <= FOUND
['326']
326: if (upperRange_ < 1e38) // <= FOUND
['443']
443: if (geometricMean_ < 1e27) // <= FOUND
['552']
552: if (ry_ < 1e25) // <= FOUND
['443']
443: if (geometricMean_ < 1e27) // <= FOUND
['1770']
1770: if ((dexVariables2_ & 3) < 3) // <= FOUND
To maintain readability in code, particularly in Solidity which can involve complex mathematical operations, it is often recommended to limit the number of arithmetic operations to a maximum of 2-3 per line. Too many operations in a single line can make the code difficult to read and understand, increase the likelihood of mistakes, and complicate the process of debugging and reviewing the code. Consider splitting such operations over more than one line, take special care when dealing with division however. Try to limit the number of arithmetic operations to a maximum of 3 per line.
Num of instances: 55
Click to show findings
['120']
120:
121:
122:
123:
124: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100); // <= FOUND
['219']
219:
220: s_.price = swap0to1_ ?
221: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) : // <= FOUND
222: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
['224']
224:
225: s_.price = swap0to1_ ?
226: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) : // <= FOUND
227: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
['434']
434:
435: s_.price = swap0to1_ ?
436: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) : // <= FOUND
437: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
['439']
439:
440: s_.price = swap0to1_ ?
441: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) : // <= FOUND
442: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
['543']
543:
544:
545: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['543']
543:
544: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['1695']
1695:
1696: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1; // <= FOUND
['544']
544: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1; // <= FOUND
['1717']
1717:
1718:
1719: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1; // <= FOUND
['618']
618:
619: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1; // <= FOUND
['1581']
1581:
1582: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1; // <= FOUND
['619']
619: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1; // <= FOUND
['1596']
1596:
1597: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1; // <= FOUND
['835']
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1; // <= FOUND
['841']
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1; // <= FOUND
['925']
925:
926:
927:
928: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['925']
925:
926:
927: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1005']
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1011']
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1077']
1077:
1078:
1079:
1080:
1081: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_)); // <= FOUND
['1107']
1107:
1108:
1109: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1192']
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1198']
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1; // <= FOUND
['1265']
1265:
1266:
1267:
1268:
1269: (, , token1FinalImaginaryReserves_, token0FinalImaginaryReserves_) =
1270: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_)); // <= FOUND
['1385']
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1; // <= FOUND
['1391']
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1; // <= FOUND
['1584']
1584:
1585: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1599']
1599:
1600: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1698']
1698:
1699: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1720']
1720:
1721: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS; // <= FOUND
['1801']
1801:
1802:
1803:
1804: price_ = ((c_.token1ImaginaryReserves - amtOut_) * 1e27) / (c_.token0ImaginaryReserves + temp_); // <= FOUND
['1821']
1821:
1822:
1823:
1824: price_ = ((d_.token1ImaginaryReserves - amtOut_) * 1e27) / (d_.token0ImaginaryReserves + temp_); // <= FOUND
['159']
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS); // <= FOUND
['265']
265:
266: if (lastStoredPrice_ > (centerPrice_ + (upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_) / THREE_DECIMALS)) { // <= FOUND
['269']
269: centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_; // <= FOUND
['276']
276: } else if (lastStoredPrice_ < (centerPrice_ - (centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_) / THREE_DECIMALS)) { // <= FOUND
['280']
280: centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_; // <= FOUND
['331']
331:
332: pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18; // <= FOUND
['384']
384: uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_); // <= FOUND
['387']
387:
388: p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27; // <= FOUND
['534']
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587: int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27); // <= FOUND
['536']
536: p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_; // <= FOUND
['664']
664: a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
['697']
697:
698: a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_); // <= FOUND
['736']
736:
737:
738:
739:
740:
741:
742:
743:
744:
745:
746:
747:
748:
749:
750:
751:
752:
753:
754:
755:
756:
757:
758: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_; // <= FOUND
['738']
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2; // <= FOUND
['847']
847:
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_); // <= FOUND
['850']
850:
851:
852: uint temp2_ = (((c_ * f_) / d_) + c_) * g_; // <= FOUND
['920']
920:
921:
922:
923:
924:
925:
926:
927:
928:
929:
930:
931:
932:
933:
934:
935:
936:
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
949:
950:
951:
952:
953:
954:
955:
956:
957:
958:
959: uint temp_ = (c_ * f_ + d_ * e_ + d_ * g_) / (2 * d_); // <= FOUND
['1091']
1091:
1092:
1093:
1094:
1095:
1096:
1097:
1098:
1099:
1100:
1101:
1102:
1103:
1104:
1105:
1106:
1107:
1108:
1109:
1110:
1111:
1112:
1113:
1114:
1115:
1116:
1117:
1118:
1119:
1120:
1121:
1122:
1123:
1124:
1125:
1126:
1127:
1128:
1129:
1130:
1131:
1132:
1133:
1134:
1135:
1136:
1137:
1138:
1139:
1140:
1141:
1142:
1143:
1144:
1145: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_; // <= FOUND
['1186']
1186: temp3_ = (uint(-priceDiff_) * X22 / ORACLE_LIMIT) << 1; // <= FOUND
['1207']
1207: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32)); // <= FOUND
['118']
118:
119:
120:
121: _totalSupplyShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION); // <= FOUND
['166']
166:
167:
168:
169: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION); // <= FOUND
Magic numbers should be avoided in Solidity code to enhance readability, maintainability, and reduce the likelihood of errors. Magic numbers are hard-coded values with no clear meaning or context, which can create confusion and make the code harder to understand for developers. Using well-defined constants or variables with descriptive names instead of magic numbers not only clarifies the purpose and significance of the value but also simplifies code updates and modifications.
Num of instances: 114
Click to show findings
['120']
120:
121:
122:
123:
124: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
['260']
260:
261: temp_ = (dexVariables2_ >> 142) & X30;
['1906']
1906: o_.oracleSlot = (dexVariables_ >> 176) & X3;
['1907']
1907: o_.oracleMap = (dexVariables_ >> 179) & X16;
['1952']
1952: percentDiff_ = slotData_ >> 10;
['1969']
1969: time_ = (dexVariables_ >> 154) & X22;
['158']
158: newCenterPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, ((dexVariables2_ >> 112) & X30))).centerPrice();
['224']
224:
225: centerPrice_ = (dexVariables2_ >> 112) & X30;
['291']
291:
292: uint temp_ = (dexVariables2 >> 172) & X28;
['1199']
1199:
1200: temp_ = (dexVariables_ >> 154) & X22;
['1200']
1200: uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);
['1201']
1201: uint oracleMap_ = (dexVariables_ >> 179) & X16;
['1375']
1375: utilizationLimit_ = utilizationLimit_ * 10;
['118']
118:
119:
120:
121: _totalSupplyShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
['166']
166:
167:
168:
169: _totalBorrowShares = (token0AmtAdjusted_ > token1AmtAdjusted_) ? token0AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION) : token1AmtAdjusted_ * 10 **(18 - TOKENS_DECIMALS_PRECISION);
['189']
189:
190: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000003) |
191: (fee_ << 2) |
192: (revenueCut_ << 19);
['326']
326: dexVariables2 = (dexVariables2 & 0xFFFFFFFFFFFFFFFFFFFFF00000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
327: (hookAddress_ << 142);
['345']
345: dexVariables2 = (dexVariables2 & 0xFFFFFFF00000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
346: (maxCenterPrice_.toBigNumber(20, 8, BigMathMinified.ROUND_UP) << 172) |
347: (minCenterPrice_.toBigNumber(20, 8, BigMathMinified.ROUND_DOWN) << 200);
['689']
689: dexVariables2 = dexVariables2_ |
690: (i_.fee << 2) |
691: (i_.revenueCut << 19) |
692: (i_.upperPercent << 27) |
693: (i_.lowerPercent << 47) |
694: (i_.upperShiftThreshold << 68) |
695: (i_.lowerShiftThreshold << 78) |
696: (i_.thresholdShiftTime << 88) |
697: (i_.centerPriceAddress << 112) |
698: (i_.hookAddress << 142) |
699: (i_.maxCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_UP) << 172) |
700: (i_.minCenterPrice.toBigNumber(20, 8, BigMathMinified.ROUND_DOWN) << 200) |
701: (THREE_DECIMALS << 228) |
702: (THREE_DECIMALS << 238);
['81']
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
['115']
115:
116: temp3_ = ((dexVariables2_ >> 2) & X17);
['160']
160:
161:
162:
163:
164:
165: if (
166: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
167: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
['266']
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
['373']
373:
374:
375:
376:
377:
378: if (
379: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
380: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
['925']
925:
926:
927:
928: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1107']
1107:
1108:
1109: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['925']
925:
926:
927: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1584']
1584:
1585: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1599']
1599:
1600: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1698']
1698:
1699: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1720']
1720:
1721: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
['1767']
1767: if ((dexVariables2_ & 2) == 2) {
['1842']
1842: _hookVerify(temp_, 2, lastPrice_ > price_, price_);
['1924']
1924: if (j == 2) {
['83']
83: uint oldLowerRange_ = (rangeShift_ >> 20) & X20;
['91']
91:
92:
93: dexVariables2_ = dexVariables2_ & ~uint(1 << 26);
['113']
113: uint oldLowerThreshold_ = (thresholdShift_ >> 20) & X20;
['171']
171:
172:
173: dexVariables2 = dexVariables2 & ~uint(1 << 248);
['222']
222: if (((dexVariables2_ >> 248) & 1) == 0) {
['241']
241: uint upperRange_ = ((dexVariables2_ >> 27) & X20);
['243']
243: if (((dexVariables2_ >> 26) & 1) == 1) {
['300']
300:
301:
302: temp_ = (dexVariables2 >> 200) & X28;
['310']
310: upperRange_ = ((dexVariables2_ >> 27) & X20);
['312']
312: if (((dexVariables2_ >> 26) & 1) == 1) {
['738']
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2;
['847']
847:
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_);
['93']
93: for (uint i = 0; i < 2; i++) {
['129']
129: if (dexVariables2 & 2 == 2) {
['136']
136: dexVariables2 = dexVariables2 | 2;
['201']
201: if (
202: (upperPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
203: (lowerPercent_ > (SIX_DECIMALS - FOUR_DECIMALS)) ||
204: (upperPercent_ == 0) ||
205: (lowerPercent_ == 0) ||
206: (shiftTime_ > X20) ||
207: (((dexVariables2_ >> 26) & 1) == 1)
208: ) {
['212']
212:
213: dexVariables2 = (dexVariables2_ & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000003FFFFFF) |
214: (uint((shiftTime_ > 0) ? 1 : 0) << 26) |
215: (upperPercent_ << 27) |
216: (lowerPercent_ << 47);
['217']
217: uint oldUpperPercent_ = (dexVariables2_ >> 27) & X20;
['221']
221: _rangeShift = uint128(oldUpperPercent_ | (oldLowerPercent_ << 20) | (shiftTime_ << 40) | (block.timestamp << 60));
['268']
268: _thresholdShift = uint128(oldUpperThresholdPercent_ |
269: (oldLowerThresholdPercent_ << 20) |
270: (shiftTime_ << 40) |
271: (block.timestamp << 60) |
272: (oldThresholdTime_ << 93));
['298']
298:
299: dexVariables2 = (dexVariables2 & 0xFeFFFFFFFFFFFFFFFFFFFFFFFFFFC0000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
300: (centerPriceAddress_ << 112) |
301: uint(1) << 248;
['365']
365: dexVariables2 = (dexVariables2 & 0xFF00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |
366: (token0UtilizationLimit_ << 228) |
367: (token1UtilizationLimit_ << 238);
['677']
677: dexVariables2_ = dexVariables2_ | 2;
['728']
728: if ((dexVariables2_ >> 255) == 1) {
['732']
732: dexVariables2 = dexVariables2_ | (uint(1) << 255);
['739']
739: if ((dexVariables2_ >> 255) == 0) {
['20']
20: if (dexVariables2_ & 3 == 0) revert FluidDexError(ErrorTypes.DexT1__PoolNotInitialized);
['1770']
1770: if ((dexVariables2_ & 3) < 3) {
['1933']
1933: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
['1949']
1949: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
['152']
152: uint percent_ = (centerPriceShift_ >> 33) & X20;
['1207']
1207: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));
['1226']
1226:
1227: _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);
['1231']
1231: _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));
['1233']
1233: _oracle[oracleMap_] = temp3_ << ((7 * 32));
['302']
302: _centerPriceShift = block.timestamp | (percent_ << 33) | (time_ << 53);
['1840']
1840: uint lastPrice_ = (dexVariables_ >> 41) & X40;
['1895']
1895: currentPrice_ = (dexVariables_ >> 41) & X40;
['84']
84: uint shiftDuration_ = (rangeShift_ >> 40) & X20;
['114']
114: uint shiftDuration_ = (thresholdShift_ >> 40) & X20;
['238']
238: uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;
['242']
242: uint lowerRange_ = ((dexVariables2_ >> 47) & X20);
['311']
311: lowerRange_ = ((dexVariables2_ >> 47) & X20);
['1165']
1165:
1166: temp2_ = (dexVariables_ >> 41) & X40;
['1206']
1206:
1207:
1208: temp3_ = (temp3_ << 41) | (temp_ << 9);
['1249']
1249:
1250: temp3_ = (temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |
1251: (((temp3_ >> 41) & X40) << 1) |
1252: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |
1253: (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |
1254: (block.timestamp << 121) |
1255: (timeDiff_ << 154) |
1256: (nextOracleSlot_ << 176) |
1257: (oracleMap_ << 179);
['1290']
1290:
1291: temp3_ = (temp3_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |
1292: (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41);
['218']
218: uint oldLowerPercent_ = (dexVariables2_ >> 47) & X20;
['682']
682:
683: dexVariables = (i_.centerPrice << 1) |
684: (i_.centerPrice << 41) |
685: (i_.centerPrice << 81) |
686: (block.timestamp << 121) |
687: (60 << 154) |
688: (7 << 176);
['153']
153: uint time_ = (centerPriceShift_ >> 53) & X20;
['1861']
1861: if (data_.length == 64) {
['85']
85: uint startTimeStamp_ = ((rangeShift_ >> 60) & X33);
['115']
115: uint startTimeStamp_ = ((thresholdShift_ >> 60) & X33);
['122']
122:
123:
124: dexVariables2 = dexVariables2 & ~uint(1 << 67);
['256']
256:
257:
258: if (((dexVariables2_ >> 68) & X20) > 0) {
['257']
257: uint upperThreshold_ = (dexVariables2_ >> 68) & X10;
['260']
260: if (((dexVariables2_ >> 67) & 1) == 1) {
['244']
244: if (
245: (upperThresholdPercent_ > THREE_DECIMALS) ||
246: (lowerThresholdPercent_ > THREE_DECIMALS) ||
247: (thresholdShiftTime_ == 0) ||
248: (thresholdShiftTime_ > X24) ||
249: (upperThresholdPercent_ == 0) ||
250: (lowerThresholdPercent_ == 0) ||
251: (shiftTime_ > X20) ||
252: (((dexVariables2_ >> 67) & 1) == 1)
253: ) {
['257']
257: dexVariables2 = (dexVariables2_ & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000007FFFFFFFFFFFFFFFF) |
258: (uint((shiftTime_ > 0) ? 1 : 0) << 67) |
259: (upperThresholdPercent_ << 68) |
260: (lowerThresholdPercent_ << 78) |
261: (thresholdShiftTime_ << 88);
['263']
263: uint oldUpperThresholdPercent_ = (dexVariables2_ >> 68) & X10;
['1909']
1909:
1910: o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;
['1940']
1940:
1941: if (o_.oracleSlot == 7) {
['258']
258: uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;
['1230']
1230: if (nextOracleSlot_ < 7) {
['264']
264: uint oldLowerThresholdPercent_ = (dexVariables2_ >> 78) & X10;
['1925']
1925: if (++o_.oracleSlot == 8) {
['148']
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40;
['226']
226: centerPrice_ = (dexVariables_ >> 81) & X40;
['259']
259: uint shiftingTime_ = (dexVariables2_ >> 88) & X24;
['585']
585: tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);
['1259']
1259:
1260: temp_ = (dexVariables_ >> 81) & X40;
['67']
67: uint centerPrice_ = (dexVariables >> 81) & X40;
['265']
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24;
['680']
680: i_.centerPrice = i_.centerPrice.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN);
['61']
61:
62: if (amt_ > (totalAmt_ * 9999 / FOUR_DECIMALS)) {
['1938']
1938:
1939: time_ = slotData_ >> 9;
['1954']
1954: if (((slotData_ >> 9) & 1 == 1)) {
['116']
116: uint oldThresholdTime_ = (thresholdShift_ >> 93) & X24;
['1221']
1221:
1222:
1223:
1224:
1225: temp3_ = temp3_ << 9;
['1229']
1229: temp3_ = (temp3_ << 9) | temp_;
[NonCritical-23] Inconsistent usage of int/uint with int256/uint256 in contract/abstract/library/interface
Use uint256/int256 consistently in place of uint/int to prevent ambiguity rather than using both within the same contract/abstract/library/interface
Num of instances: 8
Click to show findings
['15']
15: contract FluidDexT1 is Helpers {
16: using BigMathMinified for uint256; // <= FOUND
18: function _check(uint dexVariables_, uint dexVariables2_) internal { // <= FOUND
26: function _verifyToken0Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
33: function _verifyToken1Reserves(uint token0Reserves_, uint token1Reserves_, uint centerPrice_, uint minLiquidity_) internal pure { // <= FOUND
39: function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure { // <= FOUND
50: function _verifyMint(uint amt_, uint totalAmt_) internal pure { // <= FOUND
59: function _verifyRedeem(uint amt_, uint totalAmt_) internal pure { // <= FOUND
74: uint256 amountIn_, // <= FOUND
75: uint256 amountOutMin_, // <= FOUND
77: ) public payable returns (uint256 amountOut_) { // <= FOUND
78: uint dexVariables_ = dexVariables; // <= FOUND
79: uint dexVariables2_ = dexVariables2; // <= FOUND
107: uint temp_ = dexVariables2_ & 1; // <= FOUND
109: uint temp2_ = (dexVariables2_ >> 1) & 1; // <= FOUND
111: uint temp3_; // <= FOUND
112: uint temp4_; // <= FOUND
288: uint256 amountOut_, // <= FOUND
289: uint256 amountInMax_, // <= FOUND
291: ) public payable returns (uint256 amountIn_) { // <= FOUND
292: uint dexVariables_ = dexVariables; // <= FOUND
293: uint dexVariables2_ = dexVariables2; // <= FOUND
321: uint temp_ = dexVariables2_ & 1; // <= FOUND
323: uint temp2_ = (dexVariables2_ >> 1) & 1; // <= FOUND
324: uint temp3_; // <= FOUND
325: uint temp4_; // <= FOUND
512: uint shares_, // <= FOUND
513: uint maxToken0Deposit_, // <= FOUND
514: uint maxToken1Deposit_, // <= FOUND
516: ) public payable returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
517: uint dexVariables_ = dexVariables; // <= FOUND
518: uint dexVariables2_ = dexVariables2; // <= FOUND
522: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
532: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
556: uint userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64; // <= FOUND
561: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_); // <= FOUND
588: uint shares_, // <= FOUND
589: uint minToken0Withdraw_, // <= FOUND
590: uint minToken1Withdraw_, // <= FOUND
592: ) public returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
593: uint dexVariables_ = dexVariables; // <= FOUND
594: uint dexVariables2_ = dexVariables2; // <= FOUND
598: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
608: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
627: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64; // <= FOUND
631: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_); // <= FOUND
666: uint shares_, // <= FOUND
667: uint minToken0Borrow_, // <= FOUND
668: uint minToken1Borrow_, // <= FOUND
670: ) public returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
671: uint dexVariables_ = dexVariables; // <= FOUND
672: uint dexVariables2_ = dexVariables2; // <= FOUND
676: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
685: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
703: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64; // <= FOUND
707: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_); // <= FOUND
743: uint shares_, // <= FOUND
744: uint maxToken0Payback_, // <= FOUND
745: uint maxToken1Payback_, // <= FOUND
747: ) public payable returns (uint token0Amt_, uint token1Amt_) { // <= FOUND
748: uint dexVariables_ = dexVariables; // <= FOUND
749: uint dexVariables2_ = dexVariables2; // <= FOUND
753: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
759: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
783: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64; // <= FOUND
787: uint256 newBorrowLimit_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_); // <= FOUND
811: uint token0Amt_, // <= FOUND
812: uint token1Amt_, // <= FOUND
813: uint minSharesAmt_, // <= FOUND
815: ) public payable returns (uint shares_) { // <= FOUND
816: uint dexVariables_ = dexVariables; // <= FOUND
817: uint dexVariables2_ = dexVariables2; // <= FOUND
821: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
846: uint temp_; // <= FOUND
847: uint temp2_; // <= FOUND
849: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
979: uint token0Amt_, // <= FOUND
980: uint token1Amt_, // <= FOUND
981: uint maxSharesAmt_, // <= FOUND
983: ) public returns (uint shares_) { // <= FOUND
984: uint dexVariables_ = dexVariables; // <= FOUND
985: uint dexVariables2_ = dexVariables2; // <= FOUND
989: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true); // <= FOUND
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false); // <= FOUND
1016: uint temp_; // <= FOUND
1017: uint temp2_; // <= FOUND
1019: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
1067: uint token0ImaginaryReservesOutsideRangpex_; // <= FOUND
1068: uint token1ImaginaryReservesOutsideRangpex_; // <= FOUND
1166: uint token0Amt_, // <= FOUND
1167: uint token1Amt_, // <= FOUND
1168: uint maxSharesAmt_, // <= FOUND
1170: ) public returns (uint shares_) { // <= FOUND
1171: uint dexVariables_ = dexVariables; // <= FOUND
1172: uint dexVariables2_ = dexVariables2; // <= FOUND
1176: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true); // <= FOUND
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false); // <= FOUND
1203: uint temp_; // <= FOUND
1204: uint temp2_; // <= FOUND
1206: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
1254: uint token0FinalImaginaryReserves_; // <= FOUND
1255: uint token1FinalImaginaryReserves_; // <= FOUND
1360: uint token0Amt_, // <= FOUND
1361: uint token1Amt_, // <= FOUND
1362: uint minSharesAmt_, // <= FOUND
1364: ) public payable returns (uint shares_) { // <= FOUND
1365: uint dexVariables_ = dexVariables; // <= FOUND
1366: uint dexVariables2_ = dexVariables2; // <= FOUND
1370: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1396: uint temp_; // <= FOUND
1397: uint temp2_; // <= FOUND
1399: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
1536: uint shares_, // <= FOUND
1537: uint minToken0_, // <= FOUND
1538: uint minToken1_, // <= FOUND
1540: ) public returns (uint withdrawAmt_) { // <= FOUND
1541: uint dexVariables_ = dexVariables; // <= FOUND
1542: uint dexVariables2_ = dexVariables2; // <= FOUND
1546: uint userSupplyData_ = _userSupplyData[msg.sender]; // <= FOUND
1561: uint totalSupplyShares_ = _totalSupplyShares; // <= FOUND
1565: uint token0Amt_; // <= FOUND
1566: uint token1Amt_; // <= FOUND
1606: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64; // <= FOUND
1611: uint256 temp_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_); // <= FOUND
1647: uint shares_, // <= FOUND
1648: uint maxToken0_, // <= FOUND
1649: uint maxToken1_, // <= FOUND
1651: ) public payable returns (uint paybackAmt_) { // <= FOUND
1652: uint dexVariables_ = dexVariables; // <= FOUND
1653: uint dexVariables2_ = dexVariables2; // <= FOUND
1657: uint userBorrowData_ = _userBorrowData[msg.sender]; // <= FOUND
1670: uint totalBorrowShares_ = _totalBorrowShares; // <= FOUND
1674: uint token0Amt_; // <= FOUND
1675: uint token1Amt_; // <= FOUND
1729: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64; // <= FOUND
1734: uint256 temp_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_); // <= FOUND
1758: function _arbitrage(uint dexVariables_, uint dexVariables2_, PricesAndExchangePrice memory pex_) private { // <= FOUND
1763: uint price_; // <= FOUND
1784: uint temp_; // <= FOUND
1785: uint amtOut_; // <= FOUND
1786: uint amtIn_; // <= FOUND
1840: uint lastPrice_ = (dexVariables_ >> 41) & X40; // <= FOUND
1857: function liquidityCallback(address token_, uint amount_, bytes calldata data_) external { // <= FOUND
1862: (uint amountWithRevenueCut_, address from_) = abi.decode(data_, (uint, address)); // <= FOUND
1882: uint currentPrice_ // <= FOUND
1886: uint dexVariables_ = dexVariables; // <= FOUND
1889: uint totalTime_; // <= FOUND
1890: uint time_; // <= FOUND
1892: uint i; // <= FOUND
1893: uint secondsAgo_ = secondsAgos_[0]; // <= FOUND
1897: uint price_ = currentPrice_; // <= FOUND
1901: uint twap1by0_; // <= FOUND
1902: uint twap0by1_; // <= FOUND
1904: uint j; // <= FOUND
1911: uint slotData_; // <= FOUND
1912: uint percentDiff_; // <= FOUND
2029: uint dexVariables_ = dexVariables; // <= FOUND
2030: uint dexVariables2_ = dexVariables2; // <= FOUND
2051: uint dexVariables_ = dexVariables; // <= FOUND
['21']
21: contract FluidDexT1Admin is ConstantVariables, Variables, Structs, Events, Error {
22: using BigMathMinified for uint256; // <= FOUND
62: uint token0Amt_ // <= FOUND
67: uint centerPrice_ = (dexVariables >> 81) & X40; // <= FOUND
77: uint token0Amt_, // <= FOUND
78: uint centerPrice_ // <= FOUND
83: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision; // <= FOUND
85: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27; // <= FOUND
87: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision; // <= FOUND
92: uint amt_; // <= FOUND
93: for (uint i = 0; i < 2; i++) { // <= FOUND
127: uint token0Amt_ // <= FOUND
132: uint centerPrice_ = (dexVariables >> 81) & X40; // <= FOUND
146: uint token0Amt_, // <= FOUND
147: uint centerPrice_ // <= FOUND
152: uint token0AmtAdjusted_ = token0Amt_ * c2_.token0NumeratorPrecision / c2_.token0DenominatorPrecision; // <= FOUND
154: uint token1AmtAdjusted_ = centerPrice_ * token0AmtAdjusted_ / 1e27; // <= FOUND
156: uint token1Amt_ = token1AmtAdjusted_ * c2_.token1DenominatorPrecision / c2_.token1NumeratorPrecision; // <= FOUND
175: function updateFeeAndRevenueCut(uint fee_, uint revenueCut_) public _check _onlyDelegateCall { // <= FOUND
199: function updateRangePercents(uint upperPercent_, uint lowerPercent_, uint shiftTime_) public _check _onlyDelegateCall { // <= FOUND
200: uint dexVariables2_ = dexVariables2; // <= FOUND
217: uint oldUpperPercent_ = (dexVariables2_ >> 27) & X20; // <= FOUND
218: uint oldLowerPercent_ = (dexVariables2_ >> 47) & X20; // <= FOUND
233: uint upperThresholdPercent_, // <= FOUND
234: uint lowerThresholdPercent_, // <= FOUND
235: uint thresholdShiftTime_, // <= FOUND
236: uint shiftTime_ // <= FOUND
238: uint dexVariables2_ = dexVariables2; // <= FOUND
263: uint oldUpperThresholdPercent_ = (dexVariables2_ >> 68) & X10; // <= FOUND
264: uint oldLowerThresholdPercent_ = (dexVariables2_ >> 78) & X10; // <= FOUND
265: uint oldThresholdTime_ = (dexVariables2_ >> 88) & X24; // <= FOUND
282: function updateCenterPriceAddress(uint centerPriceAddress_, uint percent_, uint time_) public _check _onlyDelegateCall { // <= FOUND
315: function updateHookAddress(uint hookAddress_) public _check _onlyDelegateCall { // <= FOUND
332: function updateCenterPriceLimits(uint maxCenterPrice_, uint minCenterPrice_) public _check _onlyDelegateCall { // <= FOUND
333: uint centerPrice_ = (dexVariables >> 81) & X40; // <= FOUND
352: function updateUtilizationLimit(uint token0UtilizationLimit_, uint token1UtilizationLimit_) public _check _onlyDelegateCall { // <= FOUND
373: uint256 userSupplyData_; // <= FOUND
375: for (uint256 i; i < userSupplyConfigs_.length; ) { // <= FOUND
431: function updateUserWithdrawalLimit(address user_, uint256 newLimit_) external _check _onlyDelegateCall { // <= FOUND
435: uint256 userSupplyData_ = _userSupplyData[user_]; // <= FOUND
441: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64; // <= FOUND
445: uint256 maxExpansionLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14; // <= FOUND
455: } else if (newLimit_ == type(uint256).max || newLimit_ > userSupply_) { // <= FOUND
463: uint256 baseLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18; // <= FOUND
484: uint256 userBorrowData_; // <= FOUND
486: for (uint256 i; i < userBorrowConfigs_.length; ) { // <= FOUND
553: uint256 userData_; // <= FOUND
591: uint256 userData_; // <= FOUND
668: uint dexVariables2_; // <= FOUND
727: uint dexVariables2_ = dexVariables2; // <= FOUND
738: uint dexVariables2_ = dexVariables2; // <= FOUND
['19']
19: abstract contract Helpers is Variables, ImmutableVariables, Events {
20: using BigMathMinified for uint256; // <= FOUND
27: uint256 amountIn_, // <= FOUND
28: uint iReserveIn_, // <= FOUND
29: uint iReserveOut_ // <= FOUND
30: ) internal pure returns (uint256 amountOut_) { // <= FOUND
32: uint256 numerator_ = amountIn_ * iReserveOut_; // <= FOUND
33: uint256 denominator_ = iReserveIn_ + amountIn_; // <= FOUND
44: uint256 amountOut_, // <= FOUND
45: uint iReserveIn_, // <= FOUND
46: uint iReserveOut_ // <= FOUND
47: ) internal pure returns (uint256 amountIn_) { // <= FOUND
49: uint256 numerator_ = amountOut_ * iReserveIn_; // <= FOUND
50: uint256 denominator_ = iReserveOut_ - amountOut_; // <= FOUND
62: function _calcShiftingDone(uint current_, uint old_, uint timePassed_, uint shiftDuration_) internal pure returns (uint) { // <= FOUND
64: uint diff_ = current_ - old_; // <= FOUND
67: uint diff_ = old_ - current_; // <= FOUND
80: function _calcRangeShifting(uint upperRange_, uint lowerRange_, uint dexVariables2_) internal returns (uint, uint, uint) { // <= FOUND
81: uint rangeShift_ = _rangeShift; // <= FOUND
82: uint oldUpperRange_ = rangeShift_ & X20; // <= FOUND
83: uint oldLowerRange_ = (rangeShift_ >> 20) & X20; // <= FOUND
84: uint shiftDuration_ = (rangeShift_ >> 40) & X20; // <= FOUND
85: uint startTimeStamp_ = ((rangeShift_ >> 60) & X33); // <= FOUND
95: uint timePassed_ = block.timestamp - startTimeStamp_; // <= FOUND
110: function _calcThresholdShifting(uint upperThreshold_, uint lowerThreshold_, uint thresholdTime_) internal returns (uint, uint, uint) { // <= FOUND
111: uint thresholdShift_ = _thresholdShift; // <= FOUND
112: uint oldUpperThreshold_ = thresholdShift_ & X20; // <= FOUND
113: uint oldLowerThreshold_ = (thresholdShift_ >> 20) & X20; // <= FOUND
114: uint shiftDuration_ = (thresholdShift_ >> 40) & X20; // <= FOUND
115: uint startTimeStamp_ = ((thresholdShift_ >> 60) & X33); // <= FOUND
116: uint oldThresholdTime_ = (thresholdShift_ >> 93) & X24; // <= FOUND
125: uint timePassed_ = block.timestamp - startTimeStamp_; // <= FOUND
147: function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) { // <= FOUND
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40; // <= FOUND
150: uint centerPriceShift_ = _centerPriceShift; // <= FOUND
151: uint startTimeStamp_ = centerPriceShift_ & X33; // <= FOUND
152: uint percent_ = (centerPriceShift_ >> 33) & X20; // <= FOUND
153: uint time_ = (centerPriceShift_ >> 53) & X20; // <= FOUND
155: uint fromTimeStamp_ = (dexVariables_ >> 121) & X33; // <= FOUND
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS); // <= FOUND
215: uint dexVariables_, // <= FOUND
216: uint dexVariables2_ // <= FOUND
220: uint centerPrice_; // <= FOUND
238: uint lastStoredPrice_ = (dexVariables_ >> 41) & X40; // <= FOUND
241: uint upperRange_ = ((dexVariables2_ >> 27) & X20); // <= FOUND
242: uint lowerRange_ = ((dexVariables2_ >> 47) & X20); // <= FOUND
257: uint upperThreshold_ = (dexVariables2_ >> 68) & X10; // <= FOUND
258: uint lowerThreshold_ = (dexVariables2_ >> 78) & X10; // <= FOUND
259: uint shiftingTime_ = (dexVariables2_ >> 88) & X24; // <= FOUND
266: uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33); // <= FOUND
277: uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33); // <= FOUND
291: uint temp_ = (dexVariables2 >> 172) & X28; // <= FOUND
351: uint gp_, // <= FOUND
352: uint pa_, // <= FOUND
353: uint rx_, // <= FOUND
354: uint ry_ // <= FOUND
356: uint xa_, // <= FOUND
357: uint yb_ // <= FOUND
383: uint p1_ = pa_ - gp_; // <= FOUND
384: uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_); // <= FOUND
385: uint p3_ = rx_ * ry_; // <= FOUND
402: uint tokenExchangePrice_, // <= FOUND
404: ) internal view returns (uint tokenSupply_) { // <= FOUND
405: uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_); // <= FOUND
434: uint geometricMean_, // <= FOUND
435: uint upperRange_, // <= FOUND
436: uint lowerRange_, // <= FOUND
437: uint token0SupplyExchangePrice_, // <= FOUND
438: uint token1SupplyExchangePrice_ // <= FOUND
440: uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true); // <= FOUND
441: uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false); // <= FOUND
471: uint gp_, // <= FOUND
472: uint pb_, // <= FOUND
473: uint dx_, // <= FOUND
474: uint dy_ // <= FOUND
476: uint rx_, // <= FOUND
477: uint ry_, // <= FOUND
478: uint irx_, // <= FOUND
479: uint iry_ // <= FOUND
535: uint p2_ = (dx_ * dy_); // <= FOUND
579: uint tokenExchangePrice_, // <= FOUND
581: ) internal view returns (uint tokenDebt_) { // <= FOUND
582: uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_); // <= FOUND
611: uint geometricMean_, // <= FOUND
612: uint upperRange_, // <= FOUND
613: uint lowerRange_, // <= FOUND
614: uint token0BorrowExchangePrice_, // <= FOUND
615: uint token1BorrowExchangePrice_ // <= FOUND
617: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true); // <= FOUND
618: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false); // <= FOUND
645: uint t, // <= FOUND
646: uint x, // <= FOUND
647: uint y, // <= FOUND
648: uint x2, // <= FOUND
649: uint y2 // <= FOUND
661: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18); // <= FOUND
662: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18); // <= FOUND
677: uint t, // <= FOUND
678: uint x, // <= FOUND
679: uint y, // <= FOUND
680: uint x2, // <= FOUND
681: uint y2 // <= FOUND
693: uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18); // <= FOUND
694: uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18); // <= FOUND
706: uint c_, // <= FOUND
707: uint d_, // <= FOUND
708: uint e_, // <= FOUND
709: uint f_, // <= FOUND
710: uint i_ // <= FOUND
712: uint shares_ // <= FOUND
736: uint temp_ = (c_ * d_ + d_ * f_ + e_ * i_ - c_ * i_) / i_; // <= FOUND
737: uint temp2_ = 4 * c_ * e_; // <= FOUND
738: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2; // <= FOUND
770: uint newShares_, // <= FOUND
771: uint totalOldShares_, // <= FOUND
799: uint c_, // <= FOUND
800: uint d_, // <= FOUND
801: uint e_, // <= FOUND
802: uint f_, // <= FOUND
803: uint g_ // <= FOUND
805: uint shares_ // <= FOUND
847: uint temp_ = (d_ * e_ + 2 * c_ * d_ + c_ * f_) / (2 * d_); // <= FOUND
850: uint temp2_ = (((c_ * f_) / d_) + c_) * g_; // <= FOUND
853: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_); // <= FOUND
873: uint c_, // <= FOUND
874: uint d_, // <= FOUND
875: uint e_, // <= FOUND
876: uint f_, // <= FOUND
877: uint g_ // <= FOUND
879: uint shares_ // <= FOUND
920: uint temp_ = (c_ * f_ + d_ * e_ + d_ * g_) / (2 * d_); // <= FOUND
924: uint temp2_ = (c_ * f_ * g_) / d_; // <= FOUND
927: uint tokenAxa_ = temp_ - FixedPointMathLib.sqrt((temp_ * temp_) - temp2_); // <= FOUND
956: uint shares_, // <= FOUND
957: uint totalShares_, // <= FOUND
989: uint a_, // <= FOUND
990: uint b_, // <= FOUND
991: uint c_, // <= FOUND
992: uint d_, // <= FOUND
993: uint i_, // <= FOUND
994: uint j_ // <= FOUND
995: ) internal pure returns (uint tokenAmt_) { // <= FOUND
997: uint l_ = a_ - i_; // <= FOUND
999: uint m_ = b_ - j_; // <= FOUND
1001: uint w_ = a_ * b_; // <= FOUND
1003: uint z_ = w_ / l_; // <= FOUND
1005: uint y_ = w_ / m_; // <= FOUND
1007: uint v_ = z_ - m_ - d_; // <= FOUND
1009: uint x_ = (v_ * y_) / (m_ + v_); // <= FOUND
1029: uint c_, // <= FOUND
1030: uint d_, // <= FOUND
1031: uint e_, // <= FOUND
1032: uint f_, // <= FOUND
1033: uint g_ // <= FOUND
1035: uint shares_ // <= FOUND
1091: uint temp_ = (c_ * f_ + d_ * e_ - f_ * g_ - d_ * g_) / d_; // <= FOUND
1094: uint temp2_ = 4 * e_ * g_; // <= FOUND
1096: uint amtToSwap_ = (FixedPointMathLib.sqrt((temp2_ + (temp_ * temp_))) - temp_) / 2; // <= FOUND
1125: function _depositOrPaybackInLiquidity(address token_, uint depositAmt_, uint paybackAmt_) internal { // <= FOUND
1131: uint amt_ = depositAmt_ > 0 ? depositAmt_ : paybackAmt_; // <= FOUND
1146: uint newPrice_, // <= FOUND
1147: uint centerPrice_, // <= FOUND
1148: uint dexVariables_ // <= FOUND
1151: uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33); // <= FOUND
1153: uint temp_; // <= FOUND
1154: uint temp2_; // <= FOUND
1155: uint temp3_; // <= FOUND
1200: uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3); // <= FOUND
1201: uint oracleMap_ = (dexVariables_ >> 179) & X16; // <= FOUND
1298: uint userSupplyData_, // <= FOUND
1299: uint userSupply_, // <= FOUND
1300: uint newWithdrawalLimit_ // <= FOUND
1337: uint userBorrowData_, // <= FOUND
1338: uint userBorrow_, // <= FOUND
1339: uint newBorrowLimit_ // <= FOUND
1373: function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view { // <= FOUND
1377: uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_); // <= FOUND
1386: function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal { // <= FOUND
['4']
4: abstract contract Structs {
5:
7: uint lastStoredPrice; // <= FOUND
8: uint centerPrice; // <= FOUND
9: uint upperRange; // <= FOUND
10: uint lowerRange; // <= FOUND
11: uint geometricMean; // <= FOUND
12: uint supplyToken0ExchangePrice; // <= FOUND
13: uint borrowToken0ExchangePrice; // <= FOUND
14: uint supplyToken1ExchangePrice; // <= FOUND
15: uint borrowToken1ExchangePrice; // <= FOUND
19: uint token0RealReserves; // <= FOUND
20: uint token1RealReserves; // <= FOUND
21: uint token0ImaginaryReserves; // <= FOUND
22: uint token1ImaginaryReserves; // <= FOUND
26: uint tokenInRealReserves; // <= FOUND
27: uint tokenOutRealReserves; // <= FOUND
28: uint tokenInImaginaryReserves; // <= FOUND
29: uint tokenOutImaginaryReserves; // <= FOUND
33: uint token0Debt; // <= FOUND
34: uint token1Debt; // <= FOUND
35: uint token0RealReserves; // <= FOUND
36: uint token1RealReserves; // <= FOUND
37: uint token0ImaginaryReserves; // <= FOUND
38: uint token1ImaginaryReserves; // <= FOUND
42: uint tokenInDebt; // <= FOUND
43: uint tokenOutDebt; // <= FOUND
44: uint tokenInRealReserves; // <= FOUND
45: uint tokenOutRealReserves; // <= FOUND
46: uint tokenInImaginaryReserves; // <= FOUND
47: uint tokenOutImaginaryReserves; // <= FOUND
53: uint256 amtInAdjusted; // <= FOUND
56: uint price; // <= FOUND
57: uint fee; // <= FOUND
58: uint revenueCut; // <= FOUND
67: uint256 amtOutAdjusted; // <= FOUND
70: uint price; // <= FOUND
71: uint fee; // <= FOUND
72: uint revenueCut; // <= FOUND
76: uint msgValue; // <= FOUND
80: uint256 token0AmtAdjusted; // <= FOUND
81: uint256 token1AmtAdjusted; // <= FOUND
82: uint256 token0ReservesInitial; // <= FOUND
83: uint256 token1ReservesInitial; // <= FOUND
87: uint256 token0AmtAdjusted; // <= FOUND
88: uint256 token1AmtAdjusted; // <= FOUND
89: uint256 token0ReservesInitial; // <= FOUND
90: uint256 token1ReservesInitial; // <= FOUND
94: uint256 token0AmtAdjusted; // <= FOUND
95: uint256 token1AmtAdjusted; // <= FOUND
96: uint256 token0DebtInitial; // <= FOUND
97: uint256 token1DebtInitial; // <= FOUND
101: uint256 token0AmtAdjusted; // <= FOUND
102: uint256 token1AmtAdjusted; // <= FOUND
103: uint256 token0DebtInitial; // <= FOUND
104: uint256 token1DebtInitial; // <= FOUND
108: uint lowestPrice1by0; // <= FOUND
109: uint highestPrice1by0; // <= FOUND
110: uint oracleSlot; // <= FOUND
111: uint oracleMap; // <= FOUND
112: uint oracle; // <= FOUND
116: uint twap1by0; // <= FOUND
117: uint lowestPrice1by0; // <= FOUND
118: uint highestPrice1by0; // <= FOUND
119: uint twap0by1; // <= FOUND
120: uint lowestPrice0by1; // <= FOUND
121: uint highestPrice0by1; // <= FOUND
125: uint256 dexId; // <= FOUND
138: uint256 oracleMapping; // <= FOUND
142: uint token0NumeratorPrecision; // <= FOUND
143: uint token0DenominatorPrecision; // <= FOUND
144: uint token1NumeratorPrecision; // <= FOUND
145: uint token1DenominatorPrecision; // <= FOUND
['4']
4: abstract contract Events {
5:
10: event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to); // <= FOUND
16: event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
22: event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
28: event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
34: event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
40: event LogDepositColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
46: event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
52: event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
58: event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares); // <= FOUND
64: event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
70: event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt); // <= FOUND
75: event LogArbitrage(int routing, uint amtOut); // <= FOUND
['4']
4: abstract contract Variables {
5:
17: uint internal dexVariables; // <= FOUND
40: uint internal dexVariables2; // <= FOUND
42: uint internal _totalSupplyShares; // <= FOUND
57: uint internal _totalBorrowShares; // <= FOUND
105: mapping(uint => uint) internal _oracle; // <= FOUND
126: uint256 internal _centerPriceShift; // <= FOUND
['4']
4: abstract contract Structs {
5:
8: uint token0ColAmt; // <= FOUND
10: uint token0DebtAmt; // <= FOUND
11: uint centerPrice; // <= FOUND
12: uint fee; // <= FOUND
13: uint revenueCut; // <= FOUND
14: uint upperPercent; // <= FOUND
15: uint lowerPercent; // <= FOUND
16: uint upperShiftThreshold; // <= FOUND
17: uint lowerShiftThreshold; // <= FOUND
18: uint thresholdShiftTime; // <= FOUND
19: uint centerPriceAddress; // <= FOUND
20: uint hookAddress; // <= FOUND
21: uint maxCenterPrice; // <= FOUND
22: uint minCenterPrice; // <= FOUND
33: uint256 expandPercent; // <= FOUND
37: uint256 expandDuration; // <= FOUND
42: uint256 baseWithdrawalLimit; // <= FOUND
53: uint256 expandPercent; // <= FOUND
57: uint256 expandDuration; // <= FOUND
63: uint256 baseDebtCeiling; // <= FOUND
68: uint256 maxDebtCeiling; // <= FOUND
['6']
6: abstract contract Events is Structs {
7:
9: event LogTurnOnSmartCol(uint token0Amt); // <= FOUND
13: event LogTurnOnSmartDebt(uint token0Amt); // <= FOUND
18: event LogUpdateFeeAndRevenueCut(uint fee, uint revenueCut); // <= FOUND
24: event LogUpdateRangePercents(uint upperPercent, uint lowerPercent, uint shiftTime); // <= FOUND
32: uint upperThresholdPercent, // <= FOUND
33: uint lowerThresholdPercent, // <= FOUND
34: uint thresholdShiftTime, // <= FOUND
35: uint shiftTime // <= FOUND
42: event LogUpdateCenterPriceAddress(uint centerPriceAddress, uint percent, uint time); // <= FOUND
46: event LogUpdateHookAddress(uint hookAddress); // <= FOUND
51: event LogUpdateCenterPriceLimits(uint maxCenterPrice, uint minCenterPrice); // <= FOUND
56: event LogUpdateUtilizationLimit(uint token0UtilizationLimit, uint token1UtilizationLimit); // <= FOUND
90: uint token0ColAmt, // <= FOUND
91: uint token0DebtAmt, // <= FOUND
92: uint fee, // <= FOUND
93: uint revenueCut, // <= FOUND
94: uint centerPriceAddress, // <= FOUND
95: uint hookAddress // <= FOUND
107: uint upperPercent, // <= FOUND
108: uint lowerPercent, // <= FOUND
109: uint upperShiftThreshold, // <= FOUND
110: uint lowerShiftThreshold, // <= FOUND
111: uint thresholdShiftTime, // <= FOUND
112: uint maxCenterPrice, // <= FOUND
113: uint minCenterPrice // <= FOUND
123: event LogUpdateUserWithdrawalLimit(address user, uint256 newLimit); // <= FOUND
It's crucial to leverage the right features for the appropriate contexts in Solidity, despite the compiler's ability to correct common developer mistakes. Both constant
and immutable
variables have distinct uses. Constant
variables are best suited for hard-coded, literal values within your contract, where the value doesn't need to be computed or modified.
On the other hand, immutable
variables are ideal for situations where the value might be the result of an expression or received from a constructor. While both serve to define unchanging variables, they function differently and their proper utilization contributes to clearer, more efficient code. Remember, even if the compiler can correct certain mistakes, best practices dictate using the correct feature for the task at hand.
Num of instances: 1
Click to show findings
['76']
76: bytes32 internal constant SKIP_TRANSFERS = keccak256(bytes("SKIP_TRANSFERS")); // <= FOUND
Events in Solidity offer valuable insight into the contract's execution as they log specific instances of state changes or value transfers. However, if events do not include any parameters, their usefulness can be significantly reduced. Events without parameters can provide limited information, mainly signaling that a specific operation occurred, but lacking the context of what exactly changed. It's generally recommended to include relevant parameters, such as state changes or value modifications, in the emitted events.
Num of instances: 2
Click to show findings
['734']
734: emit LogPauseSwapAndArbitrage(); // <= FOUND
['745']
745: emit LogUnpauseSwapAndArbitrage(); // <= FOUND
When developing smart contracts in Solidity, it's crucial to validate the inputs of your functions. This includes ensuring that the bytes parameters are not empty, especially when they represent crucial data such as addresses, identifiers, or raw data that the contract needs to process.
Missing empty bytes checks can lead to unexpected behaviour in your contract. For instance, certain operations might fail, produce incorrect results, or consume unnecessary gas when performed with empty bytes. Moreover, missing input validation can potentially expose your contract to malicious activity, including exploitation of unhandled edge cases.
To mitigate these issues, always validate that bytes parameters are not empty when the logic of your contract requires it.
Num of instances: 3
Click to show findings
['400']
400: function _getLiquidityCollateral(
401: bytes32 supplyTokenSlot_,
402: uint tokenExchangePrice_,
403: bool isToken0_
404: ) internal view returns (uint tokenSupply_) {
405: uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);
406: tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
407: tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);
408:
409: if (tokenSupplyData_ & 1 == 1) {
410:
411: tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;
412: }
413:
414: tokenSupply_ = isToken0_ ?
415: ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) :
416: ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);
417: }
['577']
577: function _getLiquidityDebt(
578: bytes32 borrowTokenSlot_,
579: uint tokenExchangePrice_,
580: bool isToken0_
581: ) internal view returns (uint tokenDebt_) {
582: uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);
583:
584: tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
585: tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);
586:
587: if (tokenBorrowData_ & 1 == 1) {
588:
589: tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;
590: }
591:
592: tokenDebt_ = isToken0_ ?
593: ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) :
594: ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);
595: }
['1373']
1373: function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view {
1374: if (utilizationLimit_ < THREE_DECIMALS) {
1375: utilizationLimit_ = utilizationLimit_ * 10;
1376:
1377: uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);
1378: liquidityLayerUtilization_ = (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14;
1379:
1380:
1381:
1382: if (liquidityLayerUtilization_ > utilizationLimit_) revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);
1383: }
1384: }
Manipulating data directly at the free memory pointer location without subsequently adjusting the pointer can lead to unwanted data remnants, or "dirty bits", in that memory spot. This can cause challenges for the Solidity optimizer, making it difficult to determine if memory cleaning is required before reuse, potentially resulting in less efficient optimization. To mitigate this issue, it's advised to always update the free memory pointer following any data write operation. Furthermore, using the assembly ("memory-safe") { ... }
annotation will clearly indicate to the optimizer the sections of your code that are memory-safe, improving code efficiency and reducing the potential for errors.
Num of instances: 1
Click to show findings
['2078']
2078: assembly {
2079: let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)
2080: let size := returndatasize()
2081:
2082: response_ := mload(0x40) // <= FOUND
2083: mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))
2084: mstore(response_, size)
2085: returndatacopy(add(response_, 0x20), 0, size)
2086:
2087: if iszero(succeeded) {
2088:
2089: returndatacopy(0x00, 0x00, size)
2090: revert(0x00, size)
2091: }
2092: }
Cyclomatic complexity is a software metric used to measure the complexity of a program. It quantifies the number of linearly independent paths through a program's source code, giving an idea of how complex the control flow is. High cyclomatic complexity may indicate a higher risk of defects and can make the code harder to understand, test, and maintain. It often suggests that a function or method is trying to do too much, and a refactor might be needed. By breaking down complex functions into smaller, more focused pieces, you can improve readability, ease of testing, and overall maintainability.
Num of instances: 22
Click to show findings
['72']
72: function swapIn(
73: bool swap0to1_,
74: uint256 amountIn_,
75: uint256 amountOutMin_,
76: address to_
77: ) public payable returns (uint256 amountOut_) {
78: uint dexVariables_ = dexVariables;
79: uint dexVariables2_ = dexVariables2;
80:
81: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
82:
83: _check(dexVariables_, dexVariables2_);
84:
85: if (to_ == address(0)) to_ = msg.sender;
86:
87: SwapInMemory memory s_;
88:
89: if (swap0to1_) {
90: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
91: s_.amtInAdjusted = amountIn_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
92: } else {
93: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
94: s_.amtInAdjusted = amountIn_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
95: }
96:
97: _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);
98:
99: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
100:
101: if (msg.value > 0) {
102: if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
103: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
104: }
105:
106:
107: uint temp_ = dexVariables2_ & 1;
108:
109: uint temp2_ = (dexVariables2_ >> 1) & 1;
110:
111: uint temp3_;
112: uint temp4_;
113:
114:
115: temp3_ = ((dexVariables2_ >> 2) & X17);
116:
117:
118:
119:
120: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
121:
122:
123: s_.fee = SIX_DECIMALS - temp3_;
124:
125: CollateralReservesSwap memory cs_;
126: DebtReservesSwap memory ds_;
127: if (temp_ == 1) {
128:
129: {
130: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
131: if (swap0to1_) {
132: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
133: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
134: } else {
135: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
136: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
137: }
138: }
139: }
140:
141: if (temp2_ == 1) {
142:
143: {
144: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
145: if (swap0to1_) {
146: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
147: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
148: } else {
149: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
150: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
151: }
152: }
153: }
154:
155:
156:
157:
158:
159:
160: if (
161: s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2)
162: ) revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);
163:
164: if (temp_ == 1 && temp2_ == 1) {
165:
166: s_.swapRoutingAmt = _swapRoutingIn(s_.amtInAdjusted, cs_.tokenOutImaginaryReserves, cs_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves);
167: }
168:
169:
170:
171:
172:
173:
174: if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
175:
176:
177: temp_ = uint(s_.swapRoutingAmt);
178:
179: temp3_ = s_.amtInAdjusted - temp_;
180:
181: (temp2_, temp4_) = (0, 0);
182:
183:
184: s_.withdrawTo = to_;
185: s_.borrowTo = to_;
186: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {
187:
188: (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);
189:
190: s_.withdrawTo = to_;
191: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
192:
193: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);
194:
195: s_.borrowTo = to_;
196: } else {
197:
198: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
199: }
200:
201: if (temp_ > 0) {
202:
203: temp2_ = _getAmountOut(((temp_ * s_.fee) / SIX_DECIMALS), cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
204: swap0to1_ ?
205: _verifyToken1Reserves((cs_.tokenInRealReserves + temp_), (cs_.tokenOutRealReserves - temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
206: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp2_), (cs_.tokenInRealReserves + temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
207: }
208: if (temp3_ > 0) {
209:
210: temp4_ = _getAmountOut(((temp3_ * s_.fee) / SIX_DECIMALS), ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
211: swap0to1_ ?
212: _verifyToken1Reserves((ds_.tokenInRealReserves + temp3_), (ds_.tokenOutRealReserves - temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
213: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp4_), (ds_.tokenInRealReserves + temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
214: }
215:
216:
217: if (temp_ > temp3_) {
218:
219: s_.price = swap0to1_ ?
220: ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_) :
221: ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);
222: } else {
223:
224: s_.price = swap0to1_ ?
225: ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_) :
226: ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);
227: }
228:
229:
230: if (swap0to1_) {
231: temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
232: temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
233: temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
234: temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
235: } else {
236: temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
237: temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
238: temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
239: temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);
240: }
241:
242: amountOut_ = temp2_ + temp4_;
243:
244:
245: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);
246:
247: if (amountOut_ < amountOutMin_) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);
248:
249:
250: temp_ = (temp_ * s_.revenueCut) / SIX_DECIMALS;
251: temp3_ = (temp3_ * s_.revenueCut) / SIX_DECIMALS;
252:
253: s_.data = abi.encode(amountIn_, msg.sender);
254:
255: LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);
256:
257: LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));
258:
259:
260: temp_ = (dexVariables2_ >> 142) & X30;
261: if (temp_ > 0) {
262: s_.swap0to1 = swap0to1_;
263: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
264: }
265:
266: swap0to1_ ?
267: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
268: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
269:
271: dexVariables = _updateOracle(
272: s_.price,
273: pex_.centerPrice,
274: dexVariables_
275: );
276:
277: emit Swap(swap0to1_, amountIn_, amountOut_, to_);
278: }
['286']
286: function swapOut(
287: bool swap0to1_,
288: uint256 amountOut_,
289: uint256 amountInMax_,
290: address to_
291: ) public payable returns (uint256 amountIn_) {
292: uint dexVariables_ = dexVariables;
293: uint dexVariables2_ = dexVariables2;
294:
295: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
296:
297: _check(dexVariables_, dexVariables2_);
298:
299: if (to_ == address(0)) to_ = msg.sender;
300:
301: SwapOutMemory memory s_;
302:
303: if (swap0to1_) {
304: (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);
305: s_.amtOutAdjusted = amountOut_ * TOKEN_1_NUMERATOR_PRECISION / TOKEN_1_DENOMINATOR_PRECISION;
306: } else {
307: (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);
308: s_.amtOutAdjusted = amountOut_ * TOKEN_0_NUMERATOR_PRECISION / TOKEN_0_DENOMINATOR_PRECISION;
309: }
310:
311: _verifySwapAndNonPerfectActions(s_.amtOutAdjusted, amountOut_);
312:
313: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
314:
315: if (msg.value > 0) {
316: if (msg.value != amountInMax_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);
317: if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);
318: }
319:
320:
321: uint temp_ = dexVariables2_ & 1;
322:
323: uint temp2_ = (dexVariables2_ >> 1) & 1;
324: uint temp3_;
325: uint temp4_;
326:
327:
328: temp3_ = ((dexVariables2_ >> 2) & X17);
329:
330:
331:
332:
333: s_.revenueCut = SIX_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_) / 100);
334:
335:
336: s_.fee = SIX_DECIMALS - temp3_;
337:
338: CollateralReservesSwap memory cs_;
339: DebtReservesSwap memory ds_;
340: if (temp_ == 1) {
341:
342: {
343: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
344: if (swap0to1_) {
345: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
346: (c_.token0RealReserves, c_.token1RealReserves, c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
347: } else {
348: (cs_.tokenInRealReserves, cs_.tokenOutRealReserves, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves) =
349: (c_.token1RealReserves, c_.token0RealReserves, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
350: }
351: }
352: }
353:
354: if (temp2_ == 1) {
355:
356: {
357: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
358: if (swap0to1_) {
359: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
360: (d_.token0Debt, d_.token1Debt, d_.token0RealReserves, d_.token1RealReserves, d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
361: } else {
362: (ds_.tokenInDebt, ds_.tokenOutDebt, ds_.tokenInRealReserves, ds_.tokenOutRealReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves) =
363: (d_.token1Debt, d_.token0Debt, d_.token1RealReserves, d_.token0RealReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
364: }
365: }
366: }
367:
368:
369:
370:
371:
372:
373: if (
374: s_.amtOutAdjusted > ((cs_.tokenOutImaginaryReserves + ds_.tokenOutImaginaryReserves) / 2)
375: ) revert FluidDexError(ErrorTypes.DexT1__SwapOutLimitingAmounts);
376:
377: if (temp_ == 1 && temp2_ == 1) {
378:
379: s_.swapRoutingAmt = _swapRoutingOut(s_.amtOutAdjusted, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
380: }
381:
382:
383:
384:
385:
386:
387: if (int(s_.amtOutAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {
388:
389:
390: temp_ = uint(s_.swapRoutingAmt);
391:
392: temp3_ = s_.amtOutAdjusted - temp_;
393:
394: (temp2_, temp4_) = (0, 0);
395:
396:
397: s_.withdrawTo = to_;
398: s_.borrowTo = to_;
399: } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtOutAdjusted))) {
400:
401: (temp_, temp2_, temp3_, temp4_) = (s_.amtOutAdjusted, 0, 0, 0);
402:
403: s_.withdrawTo = to_;
404: } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {
405:
406: (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtOutAdjusted, 0);
407:
408: s_.borrowTo = to_;
409: } else {
410:
411: revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);
412: }
413:
414: if (temp_ > 0) {
415:
416: temp2_ = _getAmountIn(temp_, cs_.tokenInImaginaryReserves, cs_.tokenOutImaginaryReserves);
417: temp2_ = (temp2_ * SIX_DECIMALS) / s_.fee;
418: swap0to1_ ?
419: _verifyToken1Reserves((cs_.tokenInRealReserves + temp2_), (cs_.tokenOutRealReserves - temp_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
420: _verifyToken0Reserves((cs_.tokenOutRealReserves - temp_), (cs_.tokenInRealReserves + temp2_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
421: }
422: if (temp3_ > 0) {
423:
424: temp4_ = _getAmountIn(temp3_, ds_.tokenInImaginaryReserves, ds_.tokenOutImaginaryReserves);
425: temp4_ = (temp4_ * SIX_DECIMALS) / s_.fee;
426: swap0to1_ ?
427: _verifyToken1Reserves((ds_.tokenInRealReserves + temp4_), (ds_.tokenOutRealReserves - temp3_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP) :
428: _verifyToken0Reserves((ds_.tokenOutRealReserves - temp3_), (ds_.tokenInRealReserves + temp4_), pex_.centerPrice, MINIMUM_LIQUIDITY_SWAP);
429: }
430:
431:
432: if (temp_ > temp3_) {
433:
434: s_.price = swap0to1_ ?
435: ((cs_.tokenOutImaginaryReserves - temp_) * 1e27) / (cs_.tokenInImaginaryReserves + temp2_) :
436: ((cs_.tokenInImaginaryReserves + temp2_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp_);
437: } else {
438:
439: s_.price = swap0to1_ ?
440: ((ds_.tokenOutImaginaryReserves - temp3_) * 1e27) / (ds_.tokenInImaginaryReserves + temp4_) :
441: ((ds_.tokenInImaginaryReserves + temp4_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp3_);
442: }
443:
444:
445: if (swap0to1_) {
446: temp_ = (temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
447: temp2_ = (temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
448: temp3_ = (temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
449: temp4_ = (temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
450: } else {
451: temp_ = (temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
452: temp2_ = (temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
453: temp3_ = (temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION;
454: temp4_ = (temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION;
455: }
456:
457: amountIn_ = temp2_ + temp4_;
458:
459:
460: if (to_ == ADDRESS_DEAD) revert FluidDexSwapResult(amountIn_);
461:
462: if (amountIn_ > amountInMax_) revert FluidDexError(ErrorTypes.DexT1__ExceedsAmountInMax);
463:
464:
465: temp2_ = (temp2_ * s_.revenueCut) / SIX_DECIMALS;
466: temp4_ = (temp4_ * s_.revenueCut) / SIX_DECIMALS;
467:
468: s_.data = abi.encode(amountIn_, msg.sender);
469:
470: s_.msgValue = (s_.tokenIn == NATIVE_TOKEN) ? amountIn_ : 0;
471:
472: LIQUIDITY.operate{ value: s_.msgValue }(s_.tokenIn, int(temp2_), -int(temp4_), address(0), address(0), s_.data);
473:
474: LIQUIDITY.operate(s_.tokenOut, -int(temp_), int(temp3_), s_.withdrawTo, s_.borrowTo, new bytes(0));
475:
476:
477: temp_ = (dexVariables2_ >> 142) & X30;
478: if (temp_ > 0) {
479: s_.swap0to1 = swap0to1_;
480: _hookVerify(temp_, 1, s_.swap0to1, s_.price);
481: }
482:
483: swap0to1_ ?
484: _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT) :
485: _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);
486:
487: dexVariables = _updateOracle(
488: s_.price,
489: pex_.centerPrice,
490: dexVariables_
491: );
492:
493: if (s_.tokenIn == NATIVE_TOKEN && amountIn_ < amountInMax_) {
494: unchecked {
495: SafeTransfer.safeTransferNative(msg.sender, amountInMax_ - amountIn_);
496: }
497: }
498:
499:
500: temp_ = amountOut_;
501: emit Swap(swap0to1_, amountIn_, temp_, to_);
502: }
['587']
587: function withdrawPerfect(
588: uint shares_,
589: uint minToken0Withdraw_,
590: uint minToken1Withdraw_,
591: bool estimate_
592: ) public returns (uint token0Amt_, uint token1Amt_) {
593: uint dexVariables_ = dexVariables;
594: uint dexVariables2_ = dexVariables2;
595:
596: _check(dexVariables_, dexVariables2_);
597:
598: uint userSupplyData_ = _userSupplyData[msg.sender];
599:
600: if (userSupplyData_ & 1 == 0 && !estimate_) {
601: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
602: }
603:
604:
605: if ((dexVariables2_ & 1) == 1) {
606: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
607:
608: uint totalSupplyShares_ = _totalSupplyShares;
609:
610: _verifyRedeem(shares_, totalSupplyShares_);
611:
612:
613:
614: token0Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true) * shares_) / totalSupplyShares_;
615: token1Amt_ = (_getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false) * shares_) / totalSupplyShares_;
616:
617:
618: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
619: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
620:
621: if (estimate_) revert FluidDexPerfectLiquidityOutput(token0Amt_, token1Amt_);
622:
623: if (token0Amt_ < minToken0Withdraw_ || token1Amt_ < minToken1Withdraw_) {
624: revert FluidDexError(ErrorTypes.DexT1__BelowWithdrawMin);
625: }
626:
627: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
628: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
629:
630:
631: uint256 newWithdrawalLimit_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
632: userSupply_ -= shares_;
633:
634:
635: if (userSupply_ < newWithdrawalLimit_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
636:
637: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, newWithdrawalLimit_);
638:
639: _totalSupplyShares = totalSupplyShares_ - shares_;
640:
641:
642:
643: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0));
644:
645:
646:
647: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
648: } else {
649: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
650: }
651:
652:
653: dexVariables = dexVariables_;
654:
655: emit LogWithdrawPerfectColLiquidity(shares_, token0Amt_, token1Amt_);
656: }
['810']
810: function deposit(
811: uint token0Amt_,
812: uint token1Amt_,
813: uint minSharesAmt_,
814: bool estimate_
815: ) public payable returns (uint shares_) {
816: uint dexVariables_ = dexVariables;
817: uint dexVariables2_ = dexVariables2;
818:
819: _check(dexVariables_, dexVariables2_);
820:
821: uint userSupplyData_ = _userSupplyData[msg.sender];
822:
823: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
824:
825:
826: if ((dexVariables2_ & 1) == 1) {
827: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
828:
829: DepositColMemory memory d_;
830:
831: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
832: CollateralReserves memory c2_ = c_;
833:
834: if (token0Amt_ > 0) {
835: d_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
836: _verifySwapAndNonPerfectActions(d_.token0AmtAdjusted, token0Amt_);
837: _verifyMint(d_.token0AmtAdjusted, c_.token0RealReserves);
838: }
839:
840: if (token1Amt_ > 0) {
841: d_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
842: _verifySwapAndNonPerfectActions(d_.token1AmtAdjusted, token1Amt_);
843: _verifyMint(d_.token1AmtAdjusted, c_.token1RealReserves);
844: }
845:
846: uint temp_;
847: uint temp2_;
848:
849: uint totalSupplyShares_ = _totalSupplyShares;
850: if ((d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted == 0) && (c_.token0RealReserves > 0) && (c_.token1RealReserves == 0)) {
851:
852: shares_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
853: totalSupplyShares_ += shares_;
854: } else if ((d_.token1AmtAdjusted > 0 && d_.token0AmtAdjusted == 0) && (c_.token1RealReserves > 0) && (c_.token0RealReserves == 0)) {
855:
856: shares_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
857: totalSupplyShares_ += shares_;
858: } else {
859: if (d_.token0AmtAdjusted > 0 && d_.token1AmtAdjusted > 0) {
860:
861:
862: temp_ = d_.token0AmtAdjusted * 1e18 / c_.token0RealReserves;
863:
864: temp2_ = d_.token1AmtAdjusted * 1e18 / c_.token1RealReserves;
865: if (temp_ > temp2_) {
866:
867: shares_ = (temp2_ * totalSupplyShares_) / 1e18;
868:
869: temp_ = ((temp_ - temp2_) * c_.token0RealReserves) / 1e18;
870: temp2_ = 0;
871: } else if (temp2_ > temp_) {
872:
873: shares_ = (temp_ * totalSupplyShares_) / 1e18;
874:
875: temp2_ = ((temp2_ - temp_) * c_.token1RealReserves) / 1e18;
876: temp_ = 0;
877: } else {
878:
879: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
880: }
881:
882:
883: c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, true);
884:
885: totalSupplyShares_ += shares_;
886: } else if (d_.token0AmtAdjusted > 0) {
887: temp_ = d_.token0AmtAdjusted;
888: temp2_ = 0;
889: } else if (d_.token1AmtAdjusted > 0) {
890: temp_ = 0;
891: temp2_ = d_.token1AmtAdjusted;
892: } else {
893:
894: revert FluidDexError(ErrorTypes.DexT1__InvalidDepositAmts);
895: }
896:
897: if (temp_ > 0) {
898:
899: temp_ = _getSwapAndDeposit(
900: temp_,
901: c2_.token1ImaginaryReserves,
902: c2_.token0ImaginaryReserves,
903: c2_.token0RealReserves,
904: c2_.token1RealReserves
905: );
906: } else if (temp2_ > 0) {
907:
908: temp_ = _getSwapAndDeposit(
909: temp2_,
910: c2_.token0ImaginaryReserves,
911: c2_.token1ImaginaryReserves,
912: c2_.token1RealReserves,
913: c2_.token0RealReserves
914: );
915: } else {
916:
917: revert FluidDexError(ErrorTypes.DexT1__DepositAmtsZero);
918: }
919:
920:
921: temp_ = temp_ * totalSupplyShares_ / 1e18;
922:
923:
924:
925: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
926:
927: shares_ += temp_;
928:
929: totalSupplyShares_ += temp_;
930: }
931:
932: if (estimate_) revert FluidDexLiquidityOutput(shares_);
933:
934: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__SharesMintedLess);
935:
936: if (token0Amt_ > 0) {
937: _verifyToken1Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
938: temp_ = token0Amt_;
939: _depositOrPaybackInLiquidity(TOKEN_0, temp_, 0);
940: }
941:
942: if (token1Amt_ > 0) {
943: _verifyToken0Reserves((c_.token0RealReserves + d_.token0AmtAdjusted), (c_.token1RealReserves + d_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
944: temp_ = token1Amt_;
945: _depositOrPaybackInLiquidity(TOKEN_1, temp_, 0);
946: }
947:
948:
949: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
950:
951: temp_ = ((temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK));
952:
953:
954:
955: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
956:
957: temp_ += shares_;
958:
959: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
960:
961:
962: _totalSupplyShares = totalSupplyShares_;
963:
964: emit LogDepositColLiquidity(token0Amt_, token1Amt_, shares_);
965:
966: _arbitrage(dexVariables_, dexVariables2_, pex_);
967: } else {
968: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
969: }
970: }
['978']
978: function withdraw(
979: uint token0Amt_,
980: uint token1Amt_,
981: uint maxSharesAmt_,
982: bool estimate_
983: ) public returns (uint shares_) {
984: uint dexVariables_ = dexVariables;
985: uint dexVariables2_ = dexVariables2;
986:
987: _check(dexVariables_, dexVariables2_);
988:
989: uint userSupplyData_ = _userSupplyData[msg.sender];
990:
991: if (userSupplyData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
992:
993:
994: if ((dexVariables2_ & 1) == 1) {
995: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
996:
997: WithdrawColMemory memory w_;
998:
999: uint token0Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, pex_.supplyToken0ExchangePrice, true);
1000: uint token1Reserves_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, pex_.supplyToken1ExchangePrice, false);
1001: w_.token0ReservesInitial = token0Reserves_;
1002: w_.token1ReservesInitial = token1Reserves_;
1003:
1004: if (token0Amt_ > 0) {
1005: w_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1006: _verifySwapAndNonPerfectActions(w_.token0AmtAdjusted, token0Amt_);
1007: _verifyRedeem(w_.token0AmtAdjusted, token0Reserves_);
1008: }
1009:
1010: if (token1Amt_ > 0) {
1011: w_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1012: _verifySwapAndNonPerfectActions(w_.token1AmtAdjusted, token1Amt_);
1013: _verifyRedeem(w_.token1AmtAdjusted, token1Reserves_);
1014: }
1015:
1016: uint temp_;
1017: uint temp2_;
1018:
1019: uint totalSupplyShares_ = _totalSupplyShares;
1020: if ((w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted == 0) && (token0Reserves_ > 0) && (token1Reserves_ == 0)) {
1021:
1022: shares_ = (w_.token0AmtAdjusted * 1e18 / token0Reserves_);
1023: totalSupplyShares_ -= shares_;
1024: } else if ((w_.token1AmtAdjusted > 0 && w_.token0AmtAdjusted == 0) && (token1Reserves_ > 0) && (token0Reserves_ == 0)) {
1025:
1026: shares_ = (w_.token1AmtAdjusted * 1e18 / token1Reserves_);
1027: totalSupplyShares_ -= shares_;
1028: } else {
1029: if (w_.token0AmtAdjusted > 0 && w_.token1AmtAdjusted > 0) {
1030:
1031:
1032: temp_ = w_.token0AmtAdjusted * 1e18 / token0Reserves_;
1033:
1034: temp2_ = w_.token1AmtAdjusted * 1e18 / token1Reserves_;
1035: if (temp_ > temp2_) {
1036:
1037: shares_ = ((temp2_ * totalSupplyShares_) / 1e18);
1038:
1039: temp_ = ((temp_ - temp2_) * token0Reserves_) / 1e18;
1040: temp2_ = 0;
1041: } else if (temp2_ > temp_) {
1042:
1043: shares_ = ((temp_ * totalSupplyShares_) / 1e18);
1044:
1045: temp2_ = ((temp2_ - temp_) * token1Reserves_) / 1e18;
1046: temp_ = 0;
1047: } else {
1048:
1049: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1050: }
1051:
1052:
1053: token0Reserves_ = token0Reserves_ - (token0Reserves_ * shares_ / totalSupplyShares_);
1054: token1Reserves_ = token1Reserves_ - (token1Reserves_ * shares_ / totalSupplyShares_);
1055: totalSupplyShares_ -= shares_;
1056: } else if (w_.token0AmtAdjusted > 0) {
1057: temp_ = w_.token0AmtAdjusted;
1058: temp2_ = 0;
1059: } else if (w_.token1AmtAdjusted > 0) {
1060: temp_ = 0;
1061: temp2_ = w_.token1AmtAdjusted;
1062: } else {
1063:
1064: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1065: }
1066:
1067: uint token0ImaginaryReservesOutsideRangpex_;
1068: uint token1ImaginaryReservesOutsideRangpex_;
1069:
1070: if (pex_.geometricMean < 1e27) {
1071: (token0ImaginaryReservesOutsideRangpex_, token1ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange(pex_.geometricMean, pex_.upperRange, (token0Reserves_ - temp_), (token1Reserves_ - temp2_));
1072: } else {
1073:
1074:
1075:
1076:
1077: (token1ImaginaryReservesOutsideRangpex_, token0ImaginaryReservesOutsideRangpex_) = _calculateReservesOutsideRange((1e54 / pex_.geometricMean), (1e54 / pex_.lowerRange), (token1Reserves_ - temp2_), (token0Reserves_ - temp_));
1078: }
1079:
1080: if (temp_ > 0) {
1081:
1082: temp_ = _getWithdrawAndSwap(
1083: token0Reserves_,
1084: token1Reserves_,
1085: token0ImaginaryReservesOutsideRangpex_,
1086: token1ImaginaryReservesOutsideRangpex_,
1087: temp_
1088: );
1089: } else if (temp2_ > 0) {
1090:
1091: temp_ = _getWithdrawAndSwap(
1092: token1Reserves_,
1093: token0Reserves_,
1094: token1ImaginaryReservesOutsideRangpex_,
1095: token0ImaginaryReservesOutsideRangpex_,
1096: temp2_
1097: );
1098: } else {
1099:
1100: revert FluidDexError(ErrorTypes.DexT1__WithdrawAmtsZero);
1101: }
1102:
1103:
1104: temp_ = (temp_ * totalSupplyShares_ / 1e18);
1105:
1106:
1107: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1108:
1109: shares_ += temp_;
1110:
1111: totalSupplyShares_ -= temp_;
1112: }
1113:
1114: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1115:
1116: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__WithdrawExcessSharesBurn);
1117:
1118:
1119: temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1120: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1121:
1122:
1123:
1124: temp2_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, temp_);
1125:
1126: temp_ -= shares_;
1127:
1128:
1129: if (temp_ < temp2_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1130:
1131: _updatingUserSupplyDataOnStorage(userSupplyData_, temp_, temp2_);
1132:
1133:
1134: _totalSupplyShares = totalSupplyShares_;
1135:
1136: if (w_.token0AmtAdjusted > 0) {
1137: _verifyToken0Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1138:
1139: temp_ = token0Amt_;
1140: LIQUIDITY.operate(TOKEN_0, -int(temp_), 0, msg.sender, address(0), new bytes(0));
1141: }
1142:
1143: if (w_.token1AmtAdjusted > 0) {
1144: _verifyToken1Reserves((w_.token0ReservesInitial - w_.token0AmtAdjusted), (w_.token1ReservesInitial - w_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1145:
1146: temp_ = token1Amt_;
1147: LIQUIDITY.operate(TOKEN_1, -int(temp_), 0, msg.sender, address(0), new bytes(0));
1148: }
1149:
1150: emit LogWithdrawColLiquidity(token0Amt_, token1Amt_, shares_);
1151:
1152: _arbitrage(dexVariables_, dexVariables2_, pex_);
1153: } else {
1154: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1155: }
1156:
1157: }
['1165']
1165: function borrow(
1166: uint token0Amt_,
1167: uint token1Amt_,
1168: uint maxSharesAmt_,
1169: bool estimate_
1170: ) public returns (uint shares_) {
1171: uint dexVariables_ = dexVariables;
1172: uint dexVariables2_ = dexVariables2;
1173:
1174: _check(dexVariables_, dexVariables2_);
1175:
1176: uint userBorrowData_ = _userBorrowData[msg.sender];
1177:
1178: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1179:
1180:
1181: if (((dexVariables2_ >> 1) & 1) == 1) {
1182: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1183:
1184: BorrowDebtMemory memory b_;
1185:
1186: uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, pex_.borrowToken0ExchangePrice, true);
1187: uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, pex_.borrowToken1ExchangePrice, false);
1188: b_.token0DebtInitial = token0Debt_;
1189: b_.token1DebtInitial = token1Debt_;
1190:
1191: if (token0Amt_ > 0) {
1192: b_.token0AmtAdjusted = (((token0Amt_ + 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) + 1;
1193: _verifySwapAndNonPerfectActions(b_.token0AmtAdjusted, token0Amt_);
1194: _verifyMint(b_.token0AmtAdjusted, token0Debt_);
1195: }
1196:
1197: if (token1Amt_ > 0) {
1198: b_.token1AmtAdjusted = (((token1Amt_ + 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) + 1;
1199: _verifySwapAndNonPerfectActions(b_.token1AmtAdjusted, token1Amt_);
1200: _verifyMint(b_.token1AmtAdjusted, token1Debt_);
1201: }
1202:
1203: uint temp_;
1204: uint temp2_;
1205:
1206: uint totalBorrowShares_ = _totalBorrowShares;
1207: if ((b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted == 0) && (token0Debt_ > 0) && (token1Debt_ == 0)) {
1208:
1209: shares_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1210: totalBorrowShares_ += shares_;
1211: } else if ((b_.token1AmtAdjusted > 0 && b_.token0AmtAdjusted == 0) && (token1Debt_ > 0) && (token0Debt_ == 0)) {
1212:
1213: shares_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1214: totalBorrowShares_ += shares_;
1215: } else {
1216: if (b_.token0AmtAdjusted > 0 && b_.token1AmtAdjusted > 0) {
1217:
1218:
1219: temp_ = b_.token0AmtAdjusted * 1e18 / token0Debt_;
1220:
1221: temp2_ = b_.token1AmtAdjusted * 1e18 / token1Debt_;
1222: if (temp_ > temp2_) {
1223:
1224: shares_ = (temp2_ * totalBorrowShares_) / 1e18;
1225:
1226: temp_ = ((temp_ - temp2_) * token0Debt_) / 1e18;
1227: temp2_ = 0;
1228: } else if (temp2_ > temp_) {
1229:
1230: shares_ = (temp_ * totalBorrowShares_) / 1e18;
1231:
1232: temp2_ = ((temp2_ - temp_) * token1Debt_) / 1e18;
1233: temp_ = 0;
1234: } else {
1235:
1236: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1237: }
1238:
1239:
1240: token0Debt_ = token0Debt_ + token0Debt_ * shares_ / totalBorrowShares_;
1241: token1Debt_ = token1Debt_ + token1Debt_ * shares_ / totalBorrowShares_;
1242: totalBorrowShares_ += shares_;
1243: } else if (b_.token0AmtAdjusted > 0) {
1244: temp_ = b_.token0AmtAdjusted;
1245: temp2_ = 0;
1246: } else if (b_.token1AmtAdjusted > 0) {
1247: temp_ = 0;
1248: temp2_ = b_.token1AmtAdjusted;
1249: } else {
1250:
1251: revert FluidDexError(ErrorTypes.DexT1__InvalidBorrowAmts);
1252: }
1253:
1254: uint token0FinalImaginaryReserves_;
1255: uint token1FinalImaginaryReserves_;
1256:
1257: if (pex_.geometricMean < 1e27) {
1258: (, , token0FinalImaginaryReserves_, token1FinalImaginaryReserves_) =
1259: _calculateDebtReserves(pex_.geometricMean, pex_.lowerRange, (token0Debt_ + temp_), (token1Debt_ + temp2_));
1260: } else {
1261:
1262:
1263:
1264:
1265: (, , token1FinalImaginaryReserves_, token0FinalImaginaryReserves_) =
1266: _calculateDebtReserves((1e54 / pex_.geometricMean), (1e54 / pex_.upperRange), (token1Debt_ + temp2_), (token0Debt_ + temp_));
1267: }
1268:
1269: if (temp_ > 0) {
1270:
1271: temp_ = _getBorrowAndSwap(
1272: token0Debt_,
1273: token1Debt_,
1274: token0FinalImaginaryReserves_,
1275: token1FinalImaginaryReserves_,
1276: temp_
1277: );
1278: } else if (temp2_ > 0) {
1279:
1280: temp_ = _getBorrowAndSwap(
1281: token1Debt_,
1282: token0Debt_,
1283: token1FinalImaginaryReserves_,
1284: token0FinalImaginaryReserves_,
1285: temp2_
1286: );
1287: } else {
1288:
1289: revert FluidDexError(ErrorTypes.DexT1__BorrowAmtsZero);
1290: }
1291:
1292:
1293: temp_ = temp_ * totalBorrowShares_ / 1e18;
1294:
1295:
1296: temp_ = temp_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1297:
1298: shares_ += temp_;
1299:
1300: totalBorrowShares_ += temp_;
1301: }
1302:
1303: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1304:
1305: if (shares_ > maxSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__BorrowExcessSharesMinted);
1306:
1307:
1308:
1309: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1310: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1311:
1312:
1313:
1314: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1315:
1316: temp_ += shares_;
1317:
1318:
1319: if (temp_ > temp2_) revert FluidDexError(ErrorTypes.DexT1__DebtLimitReached);
1320:
1321: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1322:
1323: if (b_.token0AmtAdjusted > 0) {
1324:
1325: _verifyToken1Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1326:
1327: temp_ = token0Amt_;
1328:
1329: LIQUIDITY.operate(TOKEN_0, 0, int(temp_), address(0), msg.sender, new bytes(0));
1330: }
1331:
1332: if (b_.token1AmtAdjusted > 0) {
1333:
1334: _verifyToken0Reserves((b_.token0DebtInitial + b_.token0AmtAdjusted), (b_.token1DebtInitial + b_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1335:
1336: temp_ = token1Amt_;
1337:
1338: LIQUIDITY.operate(TOKEN_1, 0, int(temp_), address(0), msg.sender, new bytes(0));
1339: }
1340:
1341:
1342: _totalBorrowShares = totalBorrowShares_;
1343:
1344: emit LogBorrowDebtLiquidity(token0Amt_, token1Amt_, shares_);
1345:
1346: _arbitrage(dexVariables_, dexVariables2_, pex_);
1347: } else {
1348: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1349: }
1350:
1351: }
['1359']
1359: function payback(
1360: uint token0Amt_,
1361: uint token1Amt_,
1362: uint minSharesAmt_,
1363: bool estimate_
1364: ) public payable returns (uint shares_) {
1365: uint dexVariables_ = dexVariables;
1366: uint dexVariables2_ = dexVariables2;
1367:
1368: _check(dexVariables_, dexVariables2_);
1369:
1370: uint userBorrowData_ = _userBorrowData[msg.sender];
1371:
1372: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1373:
1375:
1376: if (((dexVariables2_ >> 1) & 1) == 1) {
1377: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1378:
1379: PaybackDebtMemory memory p_;
1380:
1381: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1382: DebtReserves memory d2_ = d_;
1383:
1384: if (token0Amt_ > 0) {
1385: p_.token0AmtAdjusted = (((token0Amt_ - 1) * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION) - 1;
1386: _verifySwapAndNonPerfectActions(p_.token0AmtAdjusted, token0Amt_);
1387: _verifyRedeem(p_.token0AmtAdjusted, d_.token0Debt);
1388: }
1389:
1390: if (token1Amt_ > 0) {
1391: p_.token1AmtAdjusted = (((token1Amt_ - 1) * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION) - 1;
1392: _verifySwapAndNonPerfectActions(p_.token1AmtAdjusted, token1Amt_);
1393: _verifyRedeem(p_.token1AmtAdjusted, d_.token1Debt);
1394: }
1395:
1396: uint temp_;
1397: uint temp2_;
1398:
1399: uint totalBorrowShares_ = _totalBorrowShares;
1400: if ((p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted == 0) && (d_.token0Debt > 0) && (d_.token1Debt == 0)) {
1401:
1402: shares_ = (p_.token0AmtAdjusted * 1e18 / d_.token0Debt);
1403: totalBorrowShares_ -= shares_;
1404: } else if ((p_.token1AmtAdjusted > 0 && p_.token0AmtAdjusted == 0) && (d_.token1Debt > 0) && (d_.token0Debt == 0)) {
1405:
1406: shares_ = (p_.token1AmtAdjusted * 1e18 / d_.token1Debt);
1407: totalBorrowShares_ -= shares_;
1408: } else {
1409: if (p_.token0AmtAdjusted > 0 && p_.token1AmtAdjusted > 0) {
1410:
1411:
1412: temp_ = p_.token0AmtAdjusted * 1e18 / d_.token0Debt;
1413:
1414: temp2_ = p_.token1AmtAdjusted * 1e18 / d_.token1Debt;
1415: if (temp_ > temp2_) {
1416:
1417: shares_ = ((temp2_ * totalBorrowShares_) / 1e18);
1418:
1419: temp_ = p_.token0AmtAdjusted - (temp2_ * p_.token0AmtAdjusted) / temp_;
1420: temp2_ = 0;
1421: } else if (temp2_ > temp_) {
1422:
1423: shares_ = ((temp_ * totalBorrowShares_) / 1e18);
1424:
1425: temp2_ = p_.token1AmtAdjusted - ((temp_ * p_.token1AmtAdjusted) / temp2_);
1426: temp_ = 0;
1427: } else {
1428:
1429: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1430: }
1431:
1432:
1433: d2_ = _getUpdateDebtReserves(
1434: shares_,
1435: totalBorrowShares_,
1436: d_,
1437: false
1438: );
1439: totalBorrowShares_ -= shares_;
1440: } else if (p_.token0AmtAdjusted > 0) {
1441: temp_ = p_.token0AmtAdjusted;
1442: temp2_ = 0;
1443: } else if (p_.token1AmtAdjusted > 0) {
1444: temp_ = 0;
1445: temp2_ = p_.token1AmtAdjusted;
1446: } else {
1447:
1448: revert FluidDexError(ErrorTypes.DexT1__InvalidPaybackAmts);
1449: }
1450:
1451: if (temp_ > 0) {
1452:
1453: temp_ = _getSwapAndPayback(
1454: d2_.token0Debt,
1455: d2_.token1Debt,
1456: d2_.token0ImaginaryReserves,
1457: d2_.token1ImaginaryReserves,
1458: temp_
1459: );
1460: } else if (temp2_ > 0) {
1461:
1462: temp_ = _getSwapAndPayback(
1463: d2_.token1Debt,
1464: d2_.token0Debt,
1465: d2_.token1ImaginaryReserves,
1466: d2_.token0ImaginaryReserves,
1467: temp2_
1468: );
1469: } else {
1470:
1471: revert FluidDexError(ErrorTypes.DexT1__PaybackAmtsZero);
1472: }
1473:
1474:
1475: temp_ = (temp_ * totalBorrowShares_ / 1e18);
1476:
1477:
1478:
1479: temp_ = temp_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1480:
1481: shares_ += temp_;
1482:
1483: totalBorrowShares_ -= temp_;
1484: }
1485:
1486: if (estimate_) revert FluidDexLiquidityOutput(shares_);
1487:
1488: if (shares_ < minSharesAmt_) revert FluidDexError(ErrorTypes.DexT1__PaybackSharedBurnedLess);
1489:
1490: if (token0Amt_ > 0) {
1491:
1492: _verifyToken0Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1493:
1494: temp_ = token0Amt_;
1495: _depositOrPaybackInLiquidity(TOKEN_0, 0, temp_);
1496: }
1497:
1498: if (token1Amt_ > 0) {
1499:
1500: _verifyToken1Reserves((d_.token0Debt - p_.token0AmtAdjusted), (d_.token1Debt - p_.token1AmtAdjusted), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1501:
1502: temp_ = token1Amt_;
1503: _depositOrPaybackInLiquidity(TOKEN_1, 0, temp_);
1504: }
1505:
1506:
1507:
1508: temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1509: temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);
1510:
1511:
1512:
1513: temp2_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, temp_);
1514:
1515: temp_ -= shares_;
1516:
1517: _updatingUserBorrowDataOnStorage(userBorrowData_, temp_, temp2_);
1518:
1519: _totalBorrowShares = totalBorrowShares_;
1520:
1521: emit LogPaybackDebtLiquidity(token0Amt_, token1Amt_, shares_);
1522:
1523: _arbitrage(dexVariables_, dexVariables2_, pex_);
1524: } else {
1525: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1526: }
1527: }
['1535']
1535: function withdrawPerfectInOneToken(
1536: uint shares_,
1537: uint minToken0_,
1538: uint minToken1_,
1539: bool estimate_
1540: ) public returns (uint withdrawAmt_) {
1541: uint dexVariables_ = dexVariables;
1542: uint dexVariables2_ = dexVariables2;
1543:
1544: _check(dexVariables_, dexVariables2_);
1545:
1546: uint userSupplyData_ = _userSupplyData[msg.sender];
1547:
1548: if (userSupplyData_ & 1 == 0 && !estimate_) {
1549: revert FluidDexError(ErrorTypes.DexT1__UserSupplyInNotOn);
1550: }
1551:
1552: if ((minToken0_ > 0 && minToken1_ > 0) || (minToken0_ == 0 && minToken1_ == 0)) {
1553:
1554: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1555: }
1556:
1557:
1558: if ((dexVariables2_ & 1) == 1) {
1559: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1560:
1561: uint totalSupplyShares_ = _totalSupplyShares;
1562:
1563: _verifyRedeem(shares_, totalSupplyShares_);
1564:
1565: uint token0Amt_;
1566: uint token1Amt_;
1567:
1568: CollateralReserves memory c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1569: CollateralReserves memory c2_ = _getUpdatedColReserves(shares_, totalSupplyShares_, c_, false);
1570:
1571: token0Amt_ = c_.token0RealReserves - c2_.token0RealReserves - 1;
1572: token1Amt_ = c_.token1RealReserves - c2_.token1RealReserves - 1;
1573:
1574: if (minToken0_ > 0) {
1575:
1576: token0Amt_ += _getAmountOut(token1Amt_, c2_.token1ImaginaryReserves, c2_.token0ImaginaryReserves);
1577: token1Amt_ = 0;
1578: _verifyToken0Reserves((c_.token0RealReserves - token0Amt_), c_.token1RealReserves, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1579:
1580:
1581: token0Amt_ = (((token0Amt_ - 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) - 1;
1582:
1583:
1584: token0Amt_ = token0Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1585:
1586: withdrawAmt_ = token0Amt_;
1587: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1588: if (withdrawAmt_ < minToken0_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1589: } else {
1590:
1591: token1Amt_ += _getAmountOut(token0Amt_, c2_.token0ImaginaryReserves, c2_.token1ImaginaryReserves);
1592: token0Amt_ = 0;
1593: _verifyToken1Reserves(c_.token0RealReserves, (c_.token1RealReserves - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1594:
1595:
1596: token1Amt_ = (((token1Amt_ - 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) - 1;
1597:
1598:
1599: token1Amt_ = token1Amt_ * (SIX_DECIMALS - ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1600:
1601: withdrawAmt_ = token1Amt_;
1602: if (estimate_) revert FluidDexSingleTokenOutput(withdrawAmt_);
1603: if (withdrawAmt_ < minToken1_) revert FluidDexError(ErrorTypes.DexT1__WithdrawalNotEnough);
1604: }
1605:
1606: uint256 userSupply_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;
1607: userSupply_ = (userSupply_ >> DEFAULT_EXPONENT_SIZE) << (userSupply_ & DEFAULT_EXPONENT_MASK);
1608:
1609:
1610:
1611: uint256 temp_ = DexCalcs.calcWithdrawalLimitBeforeOperate(userSupplyData_, userSupply_);
1612:
1613: userSupply_ -= shares_;
1614:
1615:
1616: if (userSupply_ < temp_) revert FluidDexError(ErrorTypes.DexT1__WithdrawLimitReached);
1617:
1618: _updatingUserSupplyDataOnStorage(userSupplyData_, userSupply_, temp_);
1619:
1620: _totalSupplyShares = totalSupplyShares_ - shares_;
1621:
1622: if (minToken0_ > 0) {
1623:
1624: LIQUIDITY.operate(TOKEN_0, -int(token0Amt_), 0, msg.sender, address(0), new bytes(0));
1625: } else {
1626:
1627: LIQUIDITY.operate(TOKEN_1, -int(token1Amt_), 0, msg.sender, address(0), new bytes(0));
1628: }
1629:
1630:
1631: temp_ = shares_;
1632: emit LogWithdrawColInOneToken(temp_, token0Amt_, token1Amt_);
1633:
1634: _arbitrage(dexVariables_, dexVariables2_, pex_);
1635: } else {
1636: revert FluidDexError(ErrorTypes.DexT1__SmartColNotEnabled);
1637: }
1638: }
['1646']
1646: function paybackPerfectInOneToken(
1647: uint shares_,
1648: uint maxToken0_,
1649: uint maxToken1_,
1650: bool estimate_
1651: ) public payable returns (uint paybackAmt_) {
1652: uint dexVariables_ = dexVariables;
1653: uint dexVariables2_ = dexVariables2;
1654:
1655: _check(dexVariables_, dexVariables2_);
1656:
1657: uint userBorrowData_ = _userBorrowData[msg.sender];
1658:
1659: if (userBorrowData_ & 1 == 0 && !estimate_) revert FluidDexError(ErrorTypes.DexT1__UserDebtInNotOn);
1660:
1661: if ((maxToken0_ > 0 && maxToken1_ > 0) || (maxToken0_ == 0 && maxToken1_ == 0)) {
1662:
1663: revert FluidDexError(ErrorTypes.DexT1__InvalidWithdrawAmts);
1664: }
1665:
1666:
1667: if (((dexVariables2_ >> 1) & 1) == 1) {
1668: PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);
1669:
1670: uint totalBorrowShares_ = _totalBorrowShares;
1671:
1672: _verifyRedeem(shares_, totalBorrowShares_);
1673:
1674: uint token0Amt_;
1675: uint token1Amt_;
1676:
1677:
1678: DebtReserves memory d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1679:
1680: DebtReserves memory d2_ = _getUpdateDebtReserves(shares_, totalBorrowShares_, d_, false);
1681:
1682: if (maxToken0_ > 0) {
1683:
1684: token0Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1685: d2_.token0ImaginaryReserves,
1686: d2_.token1ImaginaryReserves,
1687: d_.token0Debt,
1688: d_.token1Debt,
1689: d2_.token0RealReserves,
1690: d2_.token1RealReserves
1691: );
1692: _verifyToken0Reserves((d_.token0Debt - token0Amt_), d_.token1Debt, pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1693:
1694:
1695: token0Amt_ = (((token0Amt_ + 1) * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION) + 1;
1696:
1697:
1698: token0Amt_ = token0Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1699:
1700: paybackAmt_ = token0Amt_;
1701: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1702: if (paybackAmt_ > maxToken0_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1703: _depositOrPaybackInLiquidity(TOKEN_0, 0, paybackAmt_);
1704: } else {
1705:
1706: token1Amt_ = _getSwapAndPaybackOneTokenPerfectShares(
1707: d2_.token1ImaginaryReserves,
1708: d2_.token0ImaginaryReserves,
1709: d_.token1Debt,
1710: d_.token0Debt,
1711: d2_.token1RealReserves,
1712: d2_.token0RealReserves
1713: );
1714: _verifyToken1Reserves(d_.token0Debt, (d_.token1Debt - token1Amt_), pex_.centerPrice, MINIMUM_LIQUIDITY_USER_OPERATIONS);
1715:
1716:
1717: token1Amt_ = (((token1Amt_ + 1) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION) + 1;
1718:
1719:
1720: token1Amt_ = token1Amt_ * (SIX_DECIMALS + ((dexVariables2_ >> 2) & X17)) / SIX_DECIMALS;
1721:
1722: paybackAmt_ = token1Amt_;
1723: if (estimate_) revert FluidDexSingleTokenOutput(paybackAmt_);
1724: if (paybackAmt_ > maxToken1_) revert FluidDexError(ErrorTypes.DexT1__PaybackAmtTooHigh);
1725: _depositOrPaybackInLiquidity(TOKEN_1, 0, paybackAmt_);
1726: }
1727:
1728:
1729: uint256 userBorrow_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_AMOUNT) & X64;
1730: userBorrow_ = (userBorrow_ >> DEFAULT_EXPONENT_SIZE) << (userBorrow_ & DEFAULT_EXPONENT_MASK);
1731:
1732:
1733:
1734: uint256 temp_ = DexCalcs.calcBorrowLimitBeforeOperate(userBorrowData_, userBorrow_);
1735: userBorrow_ -= shares_;
1736:
1737: _updatingUserBorrowDataOnStorage(userBorrowData_, userBorrow_, temp_);
1738:
1739: _totalBorrowShares = totalBorrowShares_ - shares_;
1740:
1741:
1742: temp_ = shares_;
1743: emit LogPaybackDebtInOneToken(temp_, token0Amt_, token1Amt_);
1744:
1745: _arbitrage(dexVariables_, dexVariables2_, pex_);
1746: } else {
1747: revert FluidDexError(ErrorTypes.DexT1__SmartDebtNotEnabled);
1748: }
1749: }
['1758']
1758: function _arbitrage(uint dexVariables_, uint dexVariables2_, PricesAndExchangePrice memory pex_) private { // <= FOUND
1759: if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);
1760:
1761: CollateralReserves memory c_;
1762: DebtReserves memory d_;
1763: uint price_;
1764: if ((dexVariables2_ & 1) == 1) {
1765: c_ = getCollateralReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.supplyToken0ExchangePrice, pex_.supplyToken1ExchangePrice);
1766: }
1767: if ((dexVariables2_ & 2) == 2) {
1768: d_ = getDebtReserves(pex_.geometricMean, pex_.upperRange, pex_.lowerRange, pex_.borrowToken0ExchangePrice, pex_.borrowToken1ExchangePrice);
1769: }
1770: if ((dexVariables2_ & 3) < 3) {
1771: price_ = ((dexVariables2_ & 1) == 1) ?
1772: ((c_.token1ImaginaryReserves) * 1e27) / (c_.token0ImaginaryReserves) :
1773: ((d_.token1ImaginaryReserves) * 1e27) / (d_.token0ImaginaryReserves);
1774:
1775:
1776: dexVariables = _updateOracle(
1777: price_,
1778: pex_.centerPrice,
1779: dexVariables_
1780: );
1781: return;
1782: }
1783:
1784: uint temp_;
1785: uint amtOut_;
1786: uint amtIn_;
1787:
1788:
1789:
1790:
1791: int a_ = _swapRoutingIn(0, c_.token1ImaginaryReserves, c_.token0ImaginaryReserves, d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
1792: if (a_ > 0) {
1793:
1794: temp_ = uint(a_);
1795: amtOut_ = _getAmountOut(temp_ , c_.token0ImaginaryReserves, c_.token1ImaginaryReserves);
1796: amtIn_ = _getAmountIn(temp_ , d_.token1ImaginaryReserves, d_.token0ImaginaryReserves);
1797:
1798:
1799:
1800:
1801: price_ = ((c_.token1ImaginaryReserves - amtOut_) * 1e27) / (c_.token0ImaginaryReserves + temp_);
1802:
1803:
1804: a_ = (((a_) * int(TOKEN_0_DENOMINATOR_PRECISION)) / int(TOKEN_0_NUMERATOR_PRECISION));
1805: amtOut_ = (((amtOut_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1806: amtIn_ = (((amtIn_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1807:
1808:
1809:
1810: LIQUIDITY.operate(TOKEN_0, a_, a_, address(0), address(this), abi.encode(SKIP_TRANSFERS, address(this)));
1811: LIQUIDITY.operate(TOKEN_1, -int(amtOut_), -int(amtIn_), address(this), address(0), abi.encode(SKIP_TRANSFERS, address(this)));
1812: } else if (a_ < 0) {
1813:
1814: temp_ = uint(-a_);
1815: amtOut_ = _getAmountOut(temp_ , d_.token0ImaginaryReserves, d_.token1ImaginaryReserves);
1816: amtIn_ = _getAmountIn(temp_ , c_.token1ImaginaryReserves, c_.token0ImaginaryReserves);
1817:
1818:
1819:
1820:
1821: price_ = ((d_.token1ImaginaryReserves - amtOut_) * 1e27) / (d_.token0ImaginaryReserves + temp_);
1822:
1823:
1824: a_ = ((a_ * int(TOKEN_0_DENOMINATOR_PRECISION)) / int(TOKEN_0_NUMERATOR_PRECISION));
1825: amtOut_ = ((amtOut_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1826: amtIn_ = (((amtIn_) * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);
1827:
1828:
1829:
1830: LIQUIDITY.operate(TOKEN_0, a_, a_, address(this), address(0), abi.encode(SKIP_TRANSFERS, address(this)));
1831: LIQUIDITY.operate(TOKEN_1, int(amtIn_), int(amtOut_), address(0), address(this), abi.encode(SKIP_TRANSFERS, address(this)));
1832: } else {
1833:
1834: revert FluidDexError(ErrorTypes.DexT1__NothingToArbitrage);
1835: }
1836:
1837:
1838: temp_ = (dexVariables2_ >> 142) & X30;
1839: if (temp_ > 0) {
1840: uint lastPrice_ = (dexVariables_ >> 41) & X40;
1841: lastPrice_ = (lastPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastPrice_ & DEFAULT_EXPONENT_MASK);
1842: _hookVerify(temp_, 2, lastPrice_ > price_, price_);
1843: }
1844:
1845:
1846: dexVariables = _updateOracle(
1847: price_,
1848: pex_.centerPrice,
1849: dexVariables_
1850: );
1851:
1852: emit LogArbitrage(a_, amtOut_);
1853: }
['1878']
1878: function oraclePrice(
1879: uint[] memory secondsAgos_
1880: ) external view returns (
1881: Oracle[] memory twaps_,
1882: uint currentPrice_
1883: ) {
1884: OraclePriceMemory memory o_;
1885:
1886: uint dexVariables_ = dexVariables;
1887: twaps_ = new Oracle[](secondsAgos_.length);
1888:
1889: uint totalTime_;
1890: uint time_;
1891:
1892: uint i;
1893: uint secondsAgo_ = secondsAgos_[0];
1894:
1895: currentPrice_ = (dexVariables_ >> 41) & X40;
1896: currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);
1897: uint price_ = currentPrice_;
1898: o_.lowestPrice1by0 = currentPrice_;
1899: o_.highestPrice1by0 = currentPrice_;
1900:
1901: uint twap1by0_;
1902: uint twap0by1_;
1903:
1904: uint j;
1905:
1906: o_.oracleSlot = (dexVariables_ >> 176) & X3;
1907: o_.oracleMap = (dexVariables_ >> 179) & X16;
1908:
1909: o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;
1910:
1911: uint slotData_;
1912: uint percentDiff_;
1913:
1914: if (((dexVariables_ >> 121) & X33) < block.timestamp) {
1915:
1916:
1917: time_ = block.timestamp - ((dexVariables_ >> 121) & X33);
1918: } else {
1919:
1920: ++j;
1921: }
1922:
1923: while (true) {
1924: if (j == 2) {
1925: if (++o_.oracleSlot == 8) {
1926: o_.oracleSlot = 0;
1927: if (o_.oracleMap == 0) {
1928: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1929: }
1930: o_.oracle = _oracle[--o_.oracleMap];
1931: }
1932:
1933: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1934: if (slotData_ > 0) {
1935: time_ = slotData_ & X9;
1936: if (time_ == 0) {
1937:
1938: time_ = slotData_ >> 9;
1939:
1940: if (o_.oracleSlot == 7) {
1941: o_.oracleSlot = 0;
1942: if (o_.oracleMap == 0) {
1943: o_.oracleMap = TOTAL_ORACLE_MAPPING;
1944: }
1945: o_.oracle = _oracle[--o_.oracleMap];
1946: slotData_ = o_.oracle & X32;
1947: } else {
1948: ++o_.oracleSlot;
1949: slotData_ = o_.oracle >> (o_.oracleSlot * 32) & X32;
1950: }
1951: }
1952: percentDiff_ = slotData_ >> 10;
1953: percentDiff_ = ORACLE_LIMIT * percentDiff_ / X22;
1954: if (((slotData_ >> 9) & 1 == 1)) {
1955:
1956: price_ = price_ - price_ * percentDiff_ / ORACLE_PRECISION;
1957: } else {
1958:
1959: price_ = price_ + price_ * percentDiff_ / ORACLE_PRECISION;
1960: }
1961: } else {
1962:
1963: revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);
1964: }
1965: } else if (j == 1) {
1966:
1967: price_ = (dexVariables_ >> 1) & X40;
1968: price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);
1969: time_ = (dexVariables_ >> 154) & X22;
1970: ++j;
1971: } else if (j == 0) {
1972: ++j;
1973: }
1974:
1975: totalTime_ += time_;
1976: if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;
1977: if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;
1978: if (totalTime_ < secondsAgo_) {
1979: twap1by0_ += price_ * time_;
1980: twap0by1_ += (1e54 / price_) * time_;
1981: } else {
1982: time_ = time_ + secondsAgo_ - totalTime_;
1983: twap1by0_ += price_ * time_;
1984: twap0by1_ += (1e54 / price_) * time_;
1985:
1986: twap1by0_ = twap1by0_ / secondsAgo_;
1987: twap0by1_ = twap0by1_ / secondsAgo_;
1988:
1989: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
1990:
1991:
1992: o_.lowestPrice1by0 = price_;
1993: o_.highestPrice1by0 = price_;
1994:
1995: while (++i < secondsAgos_.length) {
1996:
1997: time_ = totalTime_ - secondsAgo_;
1998:
1999: totalTime_ = time_;
2000:
2001: secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];
2002: if (totalTime_ < secondsAgo_) {
2003: twap1by0_ = price_ * time_;
2004: twap0by1_ = (1e54 / price_) * time_;
2005:
2006: if (time_ == 0) {
2007: o_.lowestPrice1by0 = type(uint).max;
2008: o_.highestPrice1by0 = 0;
2009: }
2010: break;
2011: } else {
2012: time_ = time_ + secondsAgo_ - totalTime_;
2013:
2014: twap1by0_ = price_ * time_;
2015:
2016: twap0by1_ = (1e54 / price_) * time_;
2017: twap1by0_ = twap1by0_ / secondsAgo_;
2018: twap0by1_ = twap0by1_ / secondsAgo_;
2019: twaps_[i] = Oracle(twap1by0_, o_.lowestPrice1by0, o_.highestPrice1by0, twap0by1_ , (1e54 / o_.highestPrice1by0), (1e54 / o_.lowestPrice1by0));
2020: }
2021: }
2022: if (i == secondsAgos_.length) return (twaps_, currentPrice_);
2023: }
2024: }
2025:
2026: }
['147']
147: function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) { // <= FOUND
148: uint oldCenterPrice_ = (dexVariables_ >> 81) & X40;
149: oldCenterPrice_ = (oldCenterPrice_ >> DEFAULT_EXPONENT_SIZE) << (oldCenterPrice_ & DEFAULT_EXPONENT_MASK);
150: uint centerPriceShift_ = _centerPriceShift;
151: uint startTimeStamp_ = centerPriceShift_ & X33;
152: uint percent_ = (centerPriceShift_ >> 33) & X20;
153: uint time_ = (centerPriceShift_ >> 53) & X20;
154:
155: uint fromTimeStamp_ = (dexVariables_ >> 121) & X33;
156: fromTimeStamp_ = fromTimeStamp_ > startTimeStamp_ ? fromTimeStamp_ : startTimeStamp_;
157:
158: newCenterPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, ((dexVariables2_ >> 112) & X30))).centerPrice();
159: uint priceShift_ = (oldCenterPrice_ * percent_ * (block.timestamp - fromTimeStamp_)) / (time_ * SIX_DECIMALS);
160:
161: if (newCenterPrice_ > oldCenterPrice_) {
162:
163: oldCenterPrice_ += priceShift_;
164: if (newCenterPrice_ > oldCenterPrice_) {
165: newCenterPrice_ = oldCenterPrice_;
166: } else {
167:
168: delete _centerPriceShift;
169:
170:
171: dexVariables2 = dexVariables2 & ~uint(1 << 248);
172: }
173: } else {
174: unchecked {
175: oldCenterPrice_ = oldCenterPrice_ > priceShift_ ? oldCenterPrice_ - priceShift_ : 0;
176:
177:
178:
179:
180: }
181: if (newCenterPrice_ < oldCenterPrice_) {
182: newCenterPrice_ = oldCenterPrice_;
183: } else {
184:
185: delete _centerPriceShift;
186:
187:
188: dexVariables2 = dexVariables2 & ~uint(1 << 248);
189: }
190: }
191: }
['214']
214: function _getPricesAndExchangePrices(
215: uint dexVariables_,
216: uint dexVariables2_
217: ) internal returns (
218: PricesAndExchangePrice memory pex_
219: ) {
220: uint centerPrice_;
221:
222: if (((dexVariables2_ >> 248) & 1) == 0) {
223:
224: centerPrice_ = (dexVariables2_ >> 112) & X30;
225: if (centerPrice_ == 0) {
2