Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Tick
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 1
- EVM Version
- default
- Verified at
- 2023-12-18T14:39:26.936457Z
contracts/libraries/Tick.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0 <0.8.0; pragma abicoder v2; import "./LowGasSafeMath.sol"; import "./SafeCast.sol"; import "./TickMath.sol"; import "./LiquidityMath.sol"; import "./States.sol"; /// @title Tick /// @notice Contains functions for managing tick processes and relevant calculations library Tick { using LowGasSafeMath for int256; using SafeCast for int256; /// @notice Derives max liquidity per tick from given tick spacing /// @dev Executed within the pool constructor /// @param tickSpacing The amount of required tick separation, realized in multiples of `tickSpacing` /// e.g., a tickSpacing of 3 requires ticks to be initialized every 3rd tick i.e., ..., -6, -3, 0, 3, 6, ... /// @return The max liquidity per tick function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) external pure returns (uint128) { int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1; return type(uint128).max / numTicks; } /// @notice Retrieves fee growth data /// @param self The mapping containing all tick information for initialized ticks /// @param tickLower The lower tick boundary of the position /// @param tickUpper The upper tick boundary of the position /// @param tickCurrent The current tick /// @param feeGrowthGlobal0X128 The all-time global fee growth, per unit of liquidity, in token0 /// @param feeGrowthGlobal1X128 The all-time global fee growth, per unit of liquidity, in token1 /// @return feeGrowthInside0X128 The all-time fee growth in token0, per unit of liquidity, inside the position's tick boundaries /// @return feeGrowthInside1X128 The all-time fee growth in token1, per unit of liquidity, inside the position's tick boundaries function getFeeGrowthInside( mapping(int24 => TickInfo) storage self, int24 tickLower, int24 tickUpper, int24 tickCurrent, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128 ) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { TickInfo storage lower = self[tickLower]; TickInfo storage upper = self[tickUpper]; // calculate fee growth below uint256 feeGrowthBelow0X128; uint256 feeGrowthBelow1X128; if (tickCurrent >= tickLower) { feeGrowthBelow0X128 = lower.feeGrowthOutside0X128; feeGrowthBelow1X128 = lower.feeGrowthOutside1X128; } else { feeGrowthBelow0X128 = feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128; feeGrowthBelow1X128 = feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128; } // calculate fee growth above uint256 feeGrowthAbove0X128; uint256 feeGrowthAbove1X128; if (tickCurrent < tickUpper) { feeGrowthAbove0X128 = upper.feeGrowthOutside0X128; feeGrowthAbove1X128 = upper.feeGrowthOutside1X128; } else { feeGrowthAbove0X128 = feeGrowthGlobal0X128 - upper.feeGrowthOutside0X128; feeGrowthAbove1X128 = feeGrowthGlobal1X128 - upper.feeGrowthOutside1X128; } feeGrowthInside0X128 = feeGrowthGlobal0X128 - feeGrowthBelow0X128 - feeGrowthAbove0X128; feeGrowthInside1X128 = feeGrowthGlobal1X128 - feeGrowthBelow1X128 - feeGrowthAbove1X128; } struct UpdateTickParams { // the tick that will be updated int24 tick; // the current tick int24 tickCurrent; // a new amount of liquidity to be added (subtracted) when tick is crossed from left to right (right to left) int128 liquidityDelta; // the all-time global fee growth, per unit of liquidity, in token0 uint256 feeGrowthGlobal0X128; // the all-time global fee growth, per unit of liquidity, in token1 uint256 feeGrowthGlobal1X128; // The all-time seconds per max(1, liquidity) of the pool uint160 secondsPerLiquidityCumulativeX128; // the tick * time elapsed since the pool was first initialized int56 tickCumulative; // the current block timestamp cast to a uint32 uint32 time; // true for updating a position's upper tick, or false for updating a position's lower tick bool upper; // the maximum liquidity allocation for a single tick uint128 maxLiquidity; } /// @notice Updates a tick and returns true if the tick was flipped from initialized to uninitialized, or vice versa /// @param self The mapping containing all tick information for initialized ticks /// @param params the tick details and changes /// @return flipped Whether the tick was flipped from initialized to uninitialized, or vice versa function update(mapping(int24 => TickInfo) storage self, UpdateTickParams memory params) internal returns (bool flipped) { TickInfo storage info = self[params.tick]; uint128 liquidityGrossBefore = info.liquidityGross; uint128 liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, params.liquidityDelta); require(liquidityGrossAfter <= params.maxLiquidity, "LO"); flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0); if (liquidityGrossBefore == 0) { // by convention, we assume that all growth before a tick was initialized happened _below_ the tick if (params.tick <= params.tickCurrent) { info.feeGrowthOutside0X128 = params.feeGrowthGlobal0X128; info.feeGrowthOutside1X128 = params.feeGrowthGlobal1X128; info.secondsPerLiquidityOutsideX128 = params.secondsPerLiquidityCumulativeX128; info.tickCumulativeOutside = params.tickCumulative; info.secondsOutside = params.time; } info.initialized = true; } info.liquidityGross = liquidityGrossAfter; // when the lower (upper) tick is crossed left to right (right to left), liquidity must be added (removed) info.liquidityNet = params.upper ? int256(info.liquidityNet).sub(params.liquidityDelta).toInt128() : int256(info.liquidityNet).add(params.liquidityDelta).toInt128(); } /// @notice Clears tick data /// @param self The mapping containing all initialized tick information for initialized ticks /// @param tick The tick that will be cleared function clear(mapping(int24 => TickInfo) storage self, int24 tick) internal { delete self[tick]; } struct CrossParams { // The destination tick of the transition int24 tick; // The all-time global fee growth, per unit of liquidity, in token0 uint256 feeGrowthGlobal0X128; // The all-time global fee growth, per unit of liquidity, in token1 uint256 feeGrowthGlobal1X128; // The current seconds per liquidity uint160 secondsPerLiquidityCumulativeX128; // The previous period end's seconds per liquidity uint256 endSecondsPerLiquidityPeriodX128; // The starting tick of the period int24 periodStartTick; // The tick * time elapsed since the pool was first initialized int56 tickCumulative; // The current block.timestamp uint32 time; } /// @notice Transitions to next tick as needed by price movement /// @param self The mapping containing all tick information for initialized ticks /// @param params Structured cross params /// @return liquidityNet The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left) function cross(mapping(int24 => TickInfo) storage self, CrossParams calldata params) external returns (int128 liquidityNet) { TickInfo storage info = self[params.tick]; uint256 period = params.time / 1 weeks; info.feeGrowthOutside0X128 = params.feeGrowthGlobal0X128 - info.feeGrowthOutside0X128; info.feeGrowthOutside1X128 = params.feeGrowthGlobal1X128 - info.feeGrowthOutside1X128; info.secondsPerLiquidityOutsideX128 = params.secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; { uint256 periodSecondsPerLiquidityOutsideX128; uint256 periodSecondsPerLiquidityOutsideBeforeX128 = info.periodSecondsPerLiquidityOutsideX128[period]; if (params.tick <= params.periodStartTick && periodSecondsPerLiquidityOutsideBeforeX128 == 0) { periodSecondsPerLiquidityOutsideX128 = params.secondsPerLiquidityCumulativeX128 - periodSecondsPerLiquidityOutsideBeforeX128 - params.endSecondsPerLiquidityPeriodX128; } else { periodSecondsPerLiquidityOutsideX128 = params.secondsPerLiquidityCumulativeX128 - periodSecondsPerLiquidityOutsideBeforeX128; } info.periodSecondsPerLiquidityOutsideX128[period] = periodSecondsPerLiquidityOutsideX128; } info.tickCumulativeOutside = params.tickCumulative - info.tickCumulativeOutside; info.secondsOutside = params.time - info.secondsOutside; liquidityNet = info.liquidityNet; } /// @dev Common checks for valid tick inputs. function checkTicks(int24 tickLower, int24 tickUpper) external pure { require(tickLower < tickUpper, "TLU"); require(tickLower >= TickMath.MIN_TICK, "TLM"); require(tickUpper <= TickMath.MAX_TICK, "TUM"); } }
contracts/interfaces/IERC20Minimal.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Minimal ERC20 interface for Equilibre /// @notice Contains a subset of the full ERC20 interface that is used in Equilibre V2 interface IERC20Minimal { /// @notice Returns the balance of a token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
contracts/libraries/FullMath.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.4.0 <0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = -denominator & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } }
contracts/libraries/LiquidityMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import "./FullMath.sol"; import "./SafeCast.sol"; import "openzeppelin3/math/Math.sol"; /// @title Math library for liquidity library LiquidityMath { /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { if (y < 0) { require((z = x - uint128(-y)) < x, "LS"); } else { require((z = x + uint128(y)) >= x, "LA"); } } /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta256(uint256 x, int256 y) internal pure returns (uint256 z) { if (y < 0) { require((z = x - uint256(-y)) < x, "LS"); } else { require((z = x + uint256(y)) >= x, "LA"); } } }
contracts/libraries/LowGasSafeMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.0; /// @title Optimized overflow and underflow safe math operations /// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost library LowGasSafeMath { /// @notice Returns x + y, reverts if sum overflows uint256 /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x); } /// @notice Returns x - y, reverts if underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x); } /// @notice Returns x * y, reverts if overflows /// @param x The multiplicand /// @param y The multiplier /// @return z The product of x and y function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(x == 0 || (z = x * y) / x == y); } /// @notice Returns x + y, reverts if overflows or underflows /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(int256 x, int256 y) internal pure returns (int256 z) { require((z = x + y) >= x == (y >= 0)); } /// @notice Returns x - y, reverts if overflows or underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(int256 x, int256 y) internal pure returns (int256 z) { require((z = x - y) <= x == (y >= 0)); } }
contracts/libraries/SafeCast.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint128(uint256 y) internal pure returns (uint128 z) { require((z = uint128(y)) == y); } /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { require((z = uint160(y)) == y); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { require((z = int128(y)) == y); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { require(y < 2 ** 255); z = int256(y); } }
contracts/libraries/States.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0 <0.9.0; import "contracts/interfaces/IERC20Minimal.sol"; struct Slot0 { // the current price uint160 sqrtPriceX96; // the current tick int24 tick; // the most-recently updated index of the observations array uint16 observationIndex; // the current maximum number of observations that are being stored uint16 observationCardinality; // the next maximum number of observations to store, triggered in observations.write uint16 observationCardinalityNext; // the current protocol fee as a percentage of the swap fee taken on withdrawal // represented as an integer denominator (1/x)% uint8 feeProtocol; // whether the pool is locked bool unlocked; } struct Observation { // the block timestamp of the observation uint32 blockTimestamp; // the tick accumulator, i.e. tick * time elapsed since the pool was first initialized int56 tickCumulative; // the seconds per liquidity, i.e. seconds elapsed / max(1, liquidity) since the pool was first initialized uint160 secondsPerLiquidityCumulativeX128; // whether or not the observation is initialized bool initialized; } // info stored for each user's position struct PositionInfo { // the amount of liquidity owned by this position uint128 liquidity; // fee growth per unit of liquidity as of the last update to liquidity or fees owed uint256 feeGrowthInside0LastX128; uint256 feeGrowthInside1LastX128; // the fees owed to the position owner in token0/token1 uint128 tokensOwed0; uint128 tokensOwed1; uint256 attachedVeVaraId; } struct PeriodExtensionInfo { int128 totalVeVaraAmount; mapping(bytes32 => ExtensionInfo) positions; mapping(uint256 => VeVaraInfo) veVaraInfos; } struct VeVaraInfo { uint128 timesAttached; mapping(bytes32 => uint256) positionExtensionUsedRatio; } struct ExtensionInfo { uint128 amount; int128 veVaraAmount; int256 secondsDebtX96; bool initialized; int160 secondsPerLiquidityPeriodStartX128; } // info stored for each initialized individual tick struct TickInfo { // the total position liquidity that references this tick uint128 liquidityGross; // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; uint128 cleanUnusedSlot; int128 cleanUnusedSlot2; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; // the cumulative tick value on the other side of the tick int56 tickCumulativeOutside; // the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint160 secondsPerLiquidityOutsideX128; // the seconds spent on the other side of the tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint32 secondsOutside; // true iff the tick is initialized, i.e. the value is exactly equivalent to the expression liquidityGross != 0 // these 8 bits are set to prevent fresh sstores when crossing newly initialized ticks bool initialized; // secondsPerLiquidityOutsideX128 separated into periods, placed here to preserve struct slots mapping(uint256 => uint256) periodSecondsPerLiquidityOutsideX128; } // info stored for each period struct PeriodInfo { uint32 previousPeriod; int24 startTick; int24 lastTick; uint160 endSecondsPerLiquidityPeriodX128; } // accumulated protocol fees in token0/token1 units struct ProtocolFees { uint128 token0; uint128 token1; } // Position period and liquidity struct PositionCheckpoint { uint256 period; uint256 liquidity; } library States { bytes32 public constant STATES_SLOT = keccak256("states.storage"); struct PoolStates { address factory; address nfpManager; address veVara; address voter; address token0; address token1; uint24 fee; int24 tickSpacing; uint128 maxLiquidityPerTick; Slot0 slot0; mapping(uint256 => PeriodInfo) periods; uint256 lastPeriod; uint256 feeGrowthGlobal0X128; uint256 feeGrowthGlobal1X128; ProtocolFees protocolFees; uint128 liquidity; mapping(int24 => TickInfo) _ticks; mapping(int16 => uint256) tickBitmap; mapping(bytes32 => PositionInfo) positions; mapping(uint256 => PeriodExtensionInfo) extensionInfos; mapping(bytes32 => uint256) cleanUnusedSlot; Observation[65535] observations; mapping(bytes32 => PositionCheckpoint[]) positionCheckpoints; uint24 initialFee; } // Return state storage struct for reading and writing function getStorage() internal pure returns (PoolStates storage storageStruct) { bytes32 position = STATES_SLOT; assembly { storageStruct.slot := position } } /// @dev Returns the block timestamp truncated to 32 bits, i.e. mod 2**32. This method is overridden in tests. function _blockTimestamp() internal view returns (uint32) { return uint32(block.timestamp); // truncation is desired } /// @dev Get the pool's balance of token0 /// @dev This function is gas optimized to avoid a redundant extcodesize check in addition to the returndatasize /// check function balance0() internal view returns (uint256) { PoolStates storage states = getStorage(); (bool success, bytes memory data) = states.token0.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this))); require(success && data.length >= 32); return abi.decode(data, (uint256)); } /// @dev Get the pool's balance of token1 /// @dev This function is gas optimized to avoid a redundant extcodesize check in addition to the returndatasize /// check function balance1() internal view returns (uint256) { PoolStates storage states = getStorage(); (bool success, bytes memory data) = states.token1.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this))); require(success && data.length >= 32); return abi.decode(data, (uint256)); } }
contracts/libraries/TickMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0 <0.8.0; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) /// at the given tick function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); require(absTick <= uint256(MAX_TICK), "T"); uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; if (tick > 0) ratio = type(uint256).max / ratio; // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtRatio of the output price is always consistent sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, "R"); uint256 ratio = uint256(sqrtPriceX96) << 32; uint256 r = ratio; uint256 msb = 0; assembly { let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(5, gt(r, 0xFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(4, gt(r, 0xFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(3, gt(r, 0xFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(2, gt(r, 0xF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(1, gt(r, 0x3)) msb := or(msb, f) r := shr(f, r) } assembly { let f := gt(r, 0x1) msb := or(msb, f) } if (msb >= 128) r = ratio >> (msb - 127); else r = ratio << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; } }
openzeppelin3/math/Math.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":1,"enabled":true},"metadata":{"bytecodeHash":"none"},"libraries":{}}
Contract ABI
[{"type":"function","stateMutability":"pure","outputs":[],"name":"checkTicks","inputs":[{"type":"int24","name":"tickLower","internalType":"int24"},{"type":"int24","name":"tickUpper","internalType":"int24"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"tickSpacingToMaxLiquidityPerTick","inputs":[{"type":"int24","name":"tickSpacing","internalType":"int24"}]}]
Contract Creation Code
0x610531610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061004b5760003560e01c806382c66f8714610050578063bf7ca94e14610079578063d267849c146100a6575b600080fd5b61006361005e3660046103b4565b6100bb565b6040516100709190610510565b60405180910390f35b81801561008557600080fd5b50610099610094366004610428565b610127565b60405161007091906104ab565b6100b96100b43660046103d5565b610321565b005b60008082600281900b620d89e719816100d057fe5b05029050600083600281900b620d89e8816100e757fe5b0502905060008460020b83830360020b816100fe57fe5b0560010190508062ffffff166001600160801b0380168161011b57fe5b0493505050505b919050565b600080838161013960208601866103b4565b60020b60020b81526020019081526020016000209050600062093a808460e00160208101906101689190610487565b63ffffffff168161017557fe5b60028401805460208801350390556003840180546040880135039055600484015491900463ffffffff169150600160381b90046001600160a01b03166101c16080860160608701610460565b600484018054600160381b600160d81b031916600160381b939092036001600160a01b031692909202179055600081815260058301602052604081205461020e60c0870160a088016103b4565b60020b61021e60208801886103b4565b60020b1315801561022d575080155b1561025a576080860180359082906102489060608a01610460565b6001600160a01b031603039150610278565b8061026b6080880160608901610460565b6001600160a01b03160391505b506000828152600584016020526040902055600482015460060b6102a260e0860160c08701610407565b60048401805466ffffffffffffff191666ffffffffffffff9390920360060b929092161790819055600160d81b900463ffffffff166102e8610100860160e08701610487565b60048401805463ffffffff60d81b1916600160d81b9390920363ffffffff16929092021790555054600160801b9004600f0b9392505050565b8060020b8260020b1261034f5760405162461bcd60e51b8152600401610346906104b9565b60405180910390fd5b620d89e719600283900b12156103775760405162461bcd60e51b8152600401610346906104f3565b620d89e8600282900b131561039e5760405162461bcd60e51b8152600401610346906104d6565b5050565b8035600281900b811461012257600080fd5b6000602082840312156103c5578081fd5b6103ce826103a2565b9392505050565b600080604083850312156103e7578081fd5b6103f0836103a2565b91506103fe602084016103a2565b90509250929050565b600060208284031215610418578081fd5b81358060060b81146103ce578182fd5b60008082840361012081121561043c578283fd5b83359250610100601f1982011215610452578182fd5b506020830190509250929050565b600060208284031215610471578081fd5b81356001600160a01b03811681146103ce578182fd5b600060208284031215610498578081fd5b813563ffffffff811681146103ce578182fd5b600f9190910b815260200190565b602080825260039082015262544c5560e81b604082015260600190565b60208082526003908201526254554d60e81b604082015260600190565b602080825260039082015262544c4d60e81b604082015260600190565b6001600160801b039190911681526020019056fea164736f6c6343000706000a
Deployed ByteCode
0x7301f97a36917c2b76a43924368a97dcbd051a9a75301460806040526004361061004b5760003560e01c806382c66f8714610050578063bf7ca94e14610079578063d267849c146100a6575b600080fd5b61006361005e3660046103b4565b6100bb565b6040516100709190610510565b60405180910390f35b81801561008557600080fd5b50610099610094366004610428565b610127565b60405161007091906104ab565b6100b96100b43660046103d5565b610321565b005b60008082600281900b620d89e719816100d057fe5b05029050600083600281900b620d89e8816100e757fe5b0502905060008460020b83830360020b816100fe57fe5b0560010190508062ffffff166001600160801b0380168161011b57fe5b0493505050505b919050565b600080838161013960208601866103b4565b60020b60020b81526020019081526020016000209050600062093a808460e00160208101906101689190610487565b63ffffffff168161017557fe5b60028401805460208801350390556003840180546040880135039055600484015491900463ffffffff169150600160381b90046001600160a01b03166101c16080860160608701610460565b600484018054600160381b600160d81b031916600160381b939092036001600160a01b031692909202179055600081815260058301602052604081205461020e60c0870160a088016103b4565b60020b61021e60208801886103b4565b60020b1315801561022d575080155b1561025a576080860180359082906102489060608a01610460565b6001600160a01b031603039150610278565b8061026b6080880160608901610460565b6001600160a01b03160391505b506000828152600584016020526040902055600482015460060b6102a260e0860160c08701610407565b60048401805466ffffffffffffff191666ffffffffffffff9390920360060b929092161790819055600160d81b900463ffffffff166102e8610100860160e08701610487565b60048401805463ffffffff60d81b1916600160d81b9390920363ffffffff16929092021790555054600160801b9004600f0b9392505050565b8060020b8260020b1261034f5760405162461bcd60e51b8152600401610346906104b9565b60405180910390fd5b620d89e719600283900b12156103775760405162461bcd60e51b8152600401610346906104f3565b620d89e8600282900b131561039e5760405162461bcd60e51b8152600401610346906104d6565b5050565b8035600281900b811461012257600080fd5b6000602082840312156103c5578081fd5b6103ce826103a2565b9392505050565b600080604083850312156103e7578081fd5b6103f0836103a2565b91506103fe602084016103a2565b90509250929050565b600060208284031215610418578081fd5b81358060060b81146103ce578182fd5b60008082840361012081121561043c578283fd5b83359250610100601f1982011215610452578182fd5b506020830190509250929050565b600060208284031215610471578081fd5b81356001600160a01b03811681146103ce578182fd5b600060208284031215610498578081fd5b813563ffffffff811681146103ce578182fd5b600f9190910b815260200190565b602080825260039082015262544c5560e81b604082015260600190565b60208082526003908201526254554d60e81b604082015260600190565b602080825260039082015262544c4d60e81b604082015260600190565b6001600160801b039190911681526020019056fea164736f6c6343000706000a