My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x2668a705c255cd6cb8e20f59bd1f86d3a03c14090815feff46dd1d5073530adc | 0x60c06040 | 8393016 | 19 days 4 hrs ago | 0xf60f3a45c7d4476019262fc1ff6756fc15042f13 | IN | Create: QuoterV2 | 0 CRO | 7.9544112 |
[ Download CSV Export ]
Contract Name:
QuoterV2
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; pragma abicoder v2; import {SafeCast} from '../libraries/SafeCast.sol'; import {TickMath} from '../libraries/TickMath.sol'; import {PathHelper} from './libraries/PathHelper.sol'; import {PoolAddress} from './libraries/PoolAddress.sol'; import {PoolTicksCounter} from './libraries/PoolTicksCounter.sol'; import {IPool} from '../interfaces/IPool.sol'; import {IFactory} from '../interfaces/IFactory.sol'; import {ISwapCallback} from '../interfaces/callback/ISwapCallback.sol'; import {IQuoterV2} from '../interfaces/periphery/IQuoterV2.sol'; /// @title Provides quotes for swaps /// @notice Allows getting the expected amount out or amount in for a given swap without executing the swap /// @dev These functions are not gas efficient and should _not_ be called on chain. Instead, optimistically execute /// the swap and check the amounts in the callback. contract QuoterV2 is IQuoterV2, ISwapCallback { using PathHelper for bytes; using SafeCast for uint256; address public immutable factory; bytes32 internal immutable poolInitHash; /// @dev Transient storage variable used to check a safety condition in exact output swaps. uint256 private amountOutCached; constructor(address _factory) { factory = _factory; poolInitHash = IFactory(_factory).poolInitHash(); } /** * @dev Returns the pool address for the requested token pair swap fee * Because the function calculates it instead of fetching the address from the factory, * the returned pool address may not be in existence yet */ function _getPool( address tokenA, address tokenB, uint24 feeUnits ) private view returns (IPool) { return IPool(PoolAddress.computeAddress(factory, tokenA, tokenB, feeUnits, poolInitHash)); } /// @inheritdoc ISwapCallback function swapCallback( int256 amount0Delta, int256 amount1Delta, bytes memory path ) external view override { require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported (address tokenIn, address tokenOut, uint24 feeUnits) = path.decodeFirstPool(); IPool pool = _getPool(tokenIn, tokenOut, feeUnits); require(address(pool) == msg.sender, 'invalid sender'); (uint160 afterSqrtP, , int24 nearestCurrentTickAfter, ) = pool.getPoolState(); (bool isExactInput, uint256 amountToPay, uint256 amountReceived) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta), uint256(-amount1Delta)) : (tokenOut < tokenIn, uint256(amount1Delta), uint256(-amount0Delta)); if (isExactInput) { assembly { let ptr := mload(0x40) mstore(ptr, amountToPay) mstore(add(ptr, 0x20), amountReceived) mstore(add(ptr, 0x40), afterSqrtP) mstore(add(ptr, 0x60), nearestCurrentTickAfter) revert(ptr, 128) } } else { // if the cache has been populated, ensure that the full output amount has been received if (amountOutCached != 0) require(amountReceived == amountOutCached); assembly { let ptr := mload(0x40) mstore(ptr, amountReceived) mstore(add(ptr, 0x20), amountToPay) mstore(add(ptr, 0x40), afterSqrtP) mstore(add(ptr, 0x60), nearestCurrentTickAfter) revert(ptr, 128) } } } /// @dev Parses a revert reason that should contain the numeric quote function _parseRevertReason(bytes memory reason) private pure returns ( uint256 usedAmount, uint256 returnedAmount, uint160 afterSqrtP, int24 tickAfter ) { if (reason.length != 128) { if (reason.length < 68) revert('Unexpected error'); assembly { reason := add(reason, 0x04) } revert(abi.decode(reason, (string))); } return abi.decode(reason, (uint256, uint256, uint160, int24)); } function _handleRevert( bytes memory reason, IPool pool, uint256 gasEstimate ) private view returns (QuoteOutput memory output) { int24 nearestCurrentTickBefore; int24 nearestCurrentTickAfter; (, , nearestCurrentTickBefore, ) = pool.getPoolState(); ( output.usedAmount, output.returnedAmount, output.afterSqrtP, nearestCurrentTickAfter ) = _parseRevertReason(reason); output.initializedTicksCrossed = PoolTicksCounter.countInitializedTicksCrossed( pool, nearestCurrentTickBefore, nearestCurrentTickAfter ); output.gasEstimate = gasEstimate; } function quoteExactInputSingle(QuoteExactInputSingleParams memory params) public override returns (QuoteOutput memory output) { // if tokenIn < tokenOut, token input and specified token is token0, swap from 0 to 1 bool isToken0 = params.tokenIn < params.tokenOut; IPool pool = _getPool(params.tokenIn, params.tokenOut, params.feeUnits); bytes memory data = abi.encodePacked(params.tokenIn, params.feeUnits, params.tokenOut); uint160 priceLimit = params.limitSqrtP == 0 ? (isToken0 ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : params.limitSqrtP; uint256 gasBefore = gasleft(); try pool.swap(address(this), params.amountIn.toInt256(), isToken0, priceLimit, data) {} catch ( bytes memory reason ) { uint256 gasEstimate = gasBefore - gasleft(); output = _handleRevert(reason, pool, gasEstimate); } } function quoteExactInput(bytes memory path, uint256 amountIn) public override returns ( uint256 amountOut, uint160[] memory afterSqrtPList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ) { afterSqrtPList = new uint160[](path.numPools()); initializedTicksCrossedList = new uint32[](path.numPools()); uint256 i = 0; while (true) { (address tokenIn, address tokenOut, uint24 feeUnits) = path.decodeFirstPool(); // the outputs of prior swaps become the inputs to subsequent ones QuoteOutput memory quoteOutput = quoteExactInputSingle( QuoteExactInputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, feeUnits: feeUnits, amountIn: amountIn, limitSqrtP: 0 }) ); afterSqrtPList[i] = quoteOutput.afterSqrtP; initializedTicksCrossedList[i] = quoteOutput.initializedTicksCrossed; amountIn = quoteOutput.returnedAmount; gasEstimate += quoteOutput.gasEstimate; i++; // decide whether to continue or terminate if (path.hasMultiplePools()) { path = path.skipToken(); } else { return (amountIn, afterSqrtPList, initializedTicksCrossedList, gasEstimate); } } } function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params) public override returns (QuoteOutput memory output) { // if tokenIn > tokenOut, output token and specified token is token0, swap from token1 to token0 bool isToken0 = params.tokenIn > params.tokenOut; IPool pool = _getPool(params.tokenIn, params.tokenOut, params.feeUnits); // if no price limit has been specified, cache the output amount for comparison in the swap callback if (params.limitSqrtP == 0) amountOutCached = params.amount; uint256 gasBefore = gasleft(); try pool.swap( address(this), // address(0) might cause issues with some tokens -params.amount.toInt256(), isToken0, params.limitSqrtP == 0 ? (isToken0 ? TickMath.MAX_SQRT_RATIO - 1 : TickMath.MIN_SQRT_RATIO + 1) : params.limitSqrtP, abi.encodePacked(params.tokenOut, params.feeUnits, params.tokenIn) ) {} catch (bytes memory reason) { uint256 gasEstimate = gasBefore - gasleft(); if (params.limitSqrtP == 0) delete amountOutCached; // clear cache output = _handleRevert(reason, pool, gasEstimate); } } function quoteExactOutput(bytes memory path, uint256 amountOut) public override returns ( uint256 amountIn, uint160[] memory afterSqrtPList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ) { afterSqrtPList = new uint160[](path.numPools()); initializedTicksCrossedList = new uint32[](path.numPools()); uint256 i = 0; while (true) { (address tokenOut, address tokenIn, uint24 feeUnits) = path.decodeFirstPool(); // the inputs of prior swaps become the outputs of subsequent ones QuoteOutput memory quoteOutput = quoteExactOutputSingle( QuoteExactOutputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, amount: amountOut, feeUnits: feeUnits, limitSqrtP: 0 }) ); afterSqrtPList[i] = quoteOutput.afterSqrtP; initializedTicksCrossedList[i] = quoteOutput.initializedTicksCrossed; amountOut = quoteOutput.returnedAmount; gasEstimate += quoteOutput.gasEstimate; i++; // decide whether to continue or terminate if (path.hasMultiplePools()) { path = path.skipToken(); } else { return (amountOut, afterSqrtPList, initializedTicksCrossedList, gasEstimate); } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to uint32, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint32 function toUint32(uint256 y) internal pure returns (uint32 z) { require((z = uint32(y)) == y); } /// @notice Cast a uint128 to a int128, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt128(uint128 y) internal pure returns (int128 z) { require(y < 2**127); z = int128(y); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y the uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint128(uint256 y) internal pure returns (uint128 z) { require((z = uint128(y)) == y); } /// @notice Cast a int128 to a uint128 and reverses the sign. /// @param y The int128 to be casted /// @return z = -y, now type uint128 function revToUint128(int128 y) internal pure returns (uint128 z) { unchecked { return type(uint128).max - uint128(y) + 1; } } /// @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 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); } /// @notice Cast a uint256 to a int256 and reverses the sign, revert on overflow /// @param y The uint256 to be casted /// @return z = -y, now type int256 function revToInt256(uint256 y) internal pure returns (int256 z) { require(y < 2**255); z = -int256(y); } /// @notice Cast a int256 to a uint256 and reverses the sign. /// @param y The int256 to be casted /// @return z = -y, now type uint256 function revToUint256(int256 y) internal pure returns (uint256 z) { unchecked { return type(uint256).max - uint256(y) + 1; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=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 sqrtP 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 sqrtP) { unchecked { uint256 absTick = uint256(tick < 0 ? -int256(tick) : int256(tick)); require(absTick <= uint256(int256(MAX_TICK)), 'T'); // do bitwise comparison, if i-th bit is turned on, // multiply ratio by hardcoded values of sqrt(1.0001^-(2^i)) * 2^128 // where 0 <= i <= 19 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; // take reciprocal for positive tick values 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 sqrtP = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtP < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtP 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 sqrtP) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(sqrtP >= MIN_SQRT_RATIO && sqrtP < MAX_SQRT_RATIO, 'R'); uint256 ratio = uint256(sqrtP) << 32; uint256 r = ratio; uint256 msb = 0; unchecked { 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) <= sqrtP ? tickHi : tickLow; } } function getMaxNumberTicks(int24 _tickDistance) internal pure returns (uint24 numTicks) { return uint24(TickMath.MAX_TICK / _tickDistance) * 2; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import './BytesLib.sol'; /// @title Functions for manipulating path data for multihop swaps library PathHelper { using BytesLib for bytes; /// @dev The length of the bytes encoded address uint256 private constant ADDR_SIZE = 20; /// @dev The length of the bytes encoded fee uint256 private constant FEE_SIZE = 3; /// @dev The offset of a single token address and pool fee uint256 private constant TOKEN_AND_POOL_OFFSET = ADDR_SIZE + FEE_SIZE; /// @dev The offset of an encoded pool data uint256 private constant POOL_DATA_OFFSET = TOKEN_AND_POOL_OFFSET + ADDR_SIZE; /// @dev The minimum length of an encoding that contains 2 or more pools uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POOL_DATA_OFFSET + TOKEN_AND_POOL_OFFSET; /// @notice Returns true iff the path contains two or more pools /// @param path The encoded swap path /// @return True if path contains two or more pools, otherwise false function hasMultiplePools(bytes memory path) internal pure returns (bool) { return path.length >= MULTIPLE_POOLS_MIN_LENGTH; } /// @notice Returns the number of pools in the path /// @param path The encoded swap path /// @return The number of pools in the path function numPools(bytes memory path) internal pure returns (uint256) { // Ignore the first token address. From then on every fee and token offset indicates a pool. return ((path.length - ADDR_SIZE) / TOKEN_AND_POOL_OFFSET); } /// @notice Decodes the first pool in path /// @param path The bytes encoded swap path /// @return tokenA The first token of the given pool /// @return tokenB The second token of the given pool /// @return fee The fee level of the pool function decodeFirstPool(bytes memory path) internal pure returns ( address tokenA, address tokenB, uint24 fee ) { tokenA = path.toAddress(0); fee = path.toUint24(ADDR_SIZE); tokenB = path.toAddress(TOKEN_AND_POOL_OFFSET); } /// @notice Gets the segment corresponding to the first pool in the path /// @param path The bytes encoded swap path /// @return The segment containing all data necessary to target the first pool in the path function getFirstPool(bytes memory path) internal pure returns (bytes memory) { return path.slice(0, POOL_DATA_OFFSET); } /// @notice Skips a token + fee element from the buffer and returns the remainder /// @param path The swap path /// @return The remaining token + fee elements in the path function skipToken(bytes memory path) internal pure returns (bytes memory) { return path.slice(TOKEN_AND_POOL_OFFSET, path.length - TOKEN_AND_POOL_OFFSET); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; /// @title Provides a function for deriving a pool address from the factory, tokens, and swap fee library PoolAddress { /// @notice Deterministically computes the pool address from the given data /// @param factory the factory address /// @param token0 One of the tokens constituting the token pair, regardless of order /// @param token1 The other token constituting the token pair, regardless of order /// @param swapFee Fee to be collected upon every swap in the pool, in fee units /// @param poolInitHash The keccak256 hash of the Pool creation code /// @return pool the pool address function computeAddress( address factory, address token0, address token1, uint24 swapFee, bytes32 poolInitHash ) internal pure returns (address pool) { (token0, token1) = token0 < token1 ? (token0, token1) : (token1, token0); bytes32 hashed = keccak256( abi.encodePacked( hex'ff', factory, keccak256(abi.encode(token0, token1, swapFee)), poolInitHash ) ); pool = address(uint160(uint256(hashed))); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import {IPool} from '../../interfaces/IPool.sol'; library PoolTicksCounter { function countInitializedTicksCrossed( IPool self, int24 nearestCurrentTickBefore, int24 nearestCurrentTickAfter ) internal view returns (uint32 initializedTicksCrossed) { initializedTicksCrossed = 0; (int24 tickLower, int24 tickUpper) = (nearestCurrentTickBefore < nearestCurrentTickAfter) ? (nearestCurrentTickBefore, nearestCurrentTickAfter) : (nearestCurrentTickAfter, nearestCurrentTickBefore); while (tickLower != tickUpper) { initializedTicksCrossed++; (, tickLower) = self.initializedTicks(tickLower); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IPoolActions} from './pool/IPoolActions.sol'; import {IPoolEvents} from './pool/IPoolEvents.sol'; import {IPoolStorage} from './pool/IPoolStorage.sol'; interface IPool is IPoolActions, IPoolEvents, IPoolStorage {}
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @title KyberSwap v2 factory /// @notice Deploys KyberSwap v2 pools and manages control over government fees interface IFactory { /// @notice Emitted when a pool is created /// @param token0 First pool token by address sort order /// @param token1 Second pool token by address sort order /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @param tickDistance Minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint24 indexed swapFeeUnits, int24 tickDistance, address pool ); /// @notice Emitted when a new fee is enabled for pool creation via the factory /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @param tickDistance Minimum number of ticks between initialized ticks for pools created with the given fee event SwapFeeEnabled(uint24 indexed swapFeeUnits, int24 indexed tickDistance); /// @notice Emitted when vesting period changes /// @param vestingPeriod The maximum time duration for which LP fees /// are proportionally burnt upon LP removals event VestingPeriodUpdated(uint32 vestingPeriod); /// @notice Emitted when configMaster changes /// @param oldConfigMaster configMaster before the update /// @param newConfigMaster configMaster after the update event ConfigMasterUpdated(address oldConfigMaster, address newConfigMaster); /// @notice Emitted when fee configuration changes /// @param feeTo Recipient of government fees /// @param governmentFeeUnits Fee amount, in fee units, /// to be collected out of the fee charged for a pool swap event FeeConfigurationUpdated(address feeTo, uint24 governmentFeeUnits); /// @notice Emitted when whitelist feature is enabled event WhitelistEnabled(); /// @notice Emitted when whitelist feature is disabled event WhitelistDisabled(); /// @notice Returns the maximum time duration for which LP fees /// are proportionally burnt upon LP removals function vestingPeriod() external view returns (uint32); /// @notice Returns the tick distance for a specified fee. /// @dev Once added, cannot be updated or removed. /// @param swapFeeUnits Swap fee, in fee units. /// @return The tick distance. Returns 0 if fee has not been added. function feeAmountTickDistance(uint24 swapFeeUnits) external view returns (int24); /// @notice Returns the address which can update the fee configuration function configMaster() external view returns (address); /// @notice Returns the keccak256 hash of the Pool creation code /// This is used for pre-computation of pool addresses function poolInitHash() external view returns (bytes32); /// @notice Returns the pool oracle contract for twap function poolOracle() external view returns (address); /// @notice Fetches the recipient of government fees /// and current government fee charged in fee units function feeConfiguration() external view returns (address _feeTo, uint24 _governmentFeeUnits); /// @notice Returns the status of whitelisting feature of NFT managers /// If true, anyone can mint liquidity tokens /// Otherwise, only whitelisted NFT manager(s) are allowed to mint liquidity tokens function whitelistDisabled() external view returns (bool); //// @notice Returns all whitelisted NFT managers /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens function getWhitelistedNFTManagers() external view returns (address[] memory); /// @notice Checks if sender is a whitelisted NFT manager /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens /// @param sender address to be checked /// @return true if sender is a whistelisted NFT manager, false otherwise function isWhitelistedNFTManager(address sender) external view returns (bool); /// @notice Returns the pool address for a given pair of tokens and a swap fee /// @dev Token order does not matter /// @param tokenA Contract address of either token0 or token1 /// @param tokenB Contract address of the other token /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @return pool The pool address. Returns null address if it does not exist function getPool( address tokenA, address tokenB, uint24 swapFeeUnits ) external view returns (address pool); /// @notice Fetch parameters to be used for pool creation /// @dev Called by the pool constructor to fetch the parameters of the pool /// @return factory The factory address /// @return poolOracle The pool oracle for twap /// @return token0 First pool token by address sort order /// @return token1 Second pool token by address sort order /// @return swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @return tickDistance Minimum number of ticks between initialized ticks function parameters() external view returns ( address factory, address poolOracle, address token0, address token1, uint24 swapFeeUnits, int24 tickDistance ); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param swapFeeUnits Desired swap fee for the pool, in fee units /// @dev Token order does not matter. tickDistance is determined from the fee. /// Call will revert under any of these conditions: /// 1) pool already exists /// 2) invalid swap fee /// 3) invalid token arguments /// @return pool The address of the newly created pool function createPool( address tokenA, address tokenB, uint24 swapFeeUnits ) external returns (address pool); /// @notice Enables a fee amount with the given tickDistance /// @dev Fee amounts may never be removed once enabled /// @param swapFeeUnits The fee amount to enable, in fee units /// @param tickDistance The distance between ticks to be enforced for all pools created with the given fee amount function enableSwapFee(uint24 swapFeeUnits, int24 tickDistance) external; /// @notice Updates the address which can update the fee configuration /// @dev Must be called by the current configMaster function updateConfigMaster(address) external; /// @notice Updates the vesting period /// @dev Must be called by the current configMaster function updateVestingPeriod(uint32) external; /// @notice Updates the address receiving government fees and fee quantity /// @dev Only configMaster is able to perform the update /// @param feeTo Address to receive government fees collected from pools /// @param governmentFeeUnits Fee amount, in fee units, /// to be collected out of the fee charged for a pool swap function updateFeeConfiguration(address feeTo, uint24 governmentFeeUnits) external; /// @notice Enables the whitelisting feature /// @dev Only configMaster is able to perform the update function enableWhitelist() external; /// @notice Disables the whitelisting feature /// @dev Only configMaster is able to perform the update function disableWhitelist() external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @title Callback for IPool#swap /// @notice Any contract that calls IPool#swap must implement this interface interface ISwapCallback { /// @notice Called to `msg.sender` after swap execution of IPool#swap. /// @dev This function's implementation must pay tokens owed to the pool for the swap. /// The caller of this method must be checked to be a Pool deployed by the canonical Factory. /// deltaQty0 and deltaQty1 can both be 0 if no tokens were swapped. /// @param deltaQty0 The token0 quantity that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send deltaQty0 of token0 to the pool. /// @param deltaQty1 The token1 quantity that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send deltaQty1 of token1 to the pool. /// @param data Data passed through by the caller via the IPool#swap call function swapCallback( int256 deltaQty0, int256 deltaQty1, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; pragma abicoder v2; /// @title QuoterV2 Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps. /// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap. /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. interface IQuoterV2 { struct QuoteOutput { uint256 usedAmount; uint256 returnedAmount; uint160 afterSqrtP; uint32 initializedTicksCrossed; uint256 gasEstimate; } /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee /// @param amountIn The amount of the first token to swap /// @return amountOut The amount of the last token that would be received /// @return afterSqrtPList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactInput(bytes memory path, uint256 amountIn) external returns ( uint256 amountOut, uint160[] memory afterSqrtPList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 feeUnits; uint160 limitSqrtP; } /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// fee The fee of the token pool to consider for the pair /// amountIn The desired input amount /// limitSqrtP The price limit of the pool that cannot be exceeded by the swap function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (QuoteOutput memory); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order /// @param amountOut The amount of the last token to receive /// @return amountIn The amount of first token required to be paid /// @return afterSqrtPList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactOutput(bytes memory path, uint256 amountOut) external returns ( uint256 amountIn, uint160[] memory afterSqrtPList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); struct QuoteExactOutputSingleParams { address tokenIn; address tokenOut; uint256 amount; uint24 feeUnits; uint160 limitSqrtP; } /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// fee The fee of the token pool to consider for the pair /// amountOut The desired output amount /// limitSqrtP The price limit of the pool that cannot be exceeded by the swap function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params) external returns (QuoteOutput memory); }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity 0.8.9; library BytesLib { function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, 'slice_overflow'); require(_bytes.length >= _start + _length, 'slice_outOfBounds'); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) // update free-memory pointer // allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) // zero out the 32 bytes slice we are about to return // we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, 'toAddress_outOfBounds'); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, 'toUint16_outOfBounds'); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { require(_bytes.length >= _start + 3, 'toUint24_outOfBounds'); uint24 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x3), _start)) } return tempUint; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolActions { /// @notice Sets the initial price for the pool and seeds reinvestment liquidity /// @dev Assumes the caller has sent the necessary token amounts /// required for initializing reinvestment liquidity prior to calling this function /// @param initialSqrtP the initial sqrt price of the pool /// @param qty0 token0 quantity sent to and locked permanently in the pool /// @param qty1 token1 quantity sent to and locked permanently in the pool function unlockPool(uint160 initialSqrtP) external returns (uint256 qty0, uint256 qty1); /// @notice Adds liquidity for the specified recipient/tickLower/tickUpper position /// @dev Any token0 or token1 owed for the liquidity provision have to be paid for when /// the IMintCallback#mintCallback is called to this method's caller /// The quantity of token0/token1 to be sent depends on /// tickLower, tickUpper, the amount of liquidity, and the current price of the pool. /// Also sends reinvestment tokens (fees) to the recipient for any fees collected /// while the position is in range /// Reinvestment tokens have to be burnt via #burnRTokens in exchange for token0 and token1 /// @param recipient Address for which the added liquidity is credited to /// @param tickLower Recipient position's lower tick /// @param tickUpper Recipient position's upper tick /// @param ticksPrevious The nearest tick that is initialized and <= the lower & upper ticks /// @param qty Liquidity quantity to mint /// @param data Data (if any) to be passed through to the callback /// @return qty0 token0 quantity sent to the pool in exchange for the minted liquidity /// @return qty1 token1 quantity sent to the pool in exchange for the minted liquidity /// @return feeGrowthInside position's updated feeGrowthInside value function mint( address recipient, int24 tickLower, int24 tickUpper, int24[2] calldata ticksPrevious, uint128 qty, bytes calldata data ) external returns ( uint256 qty0, uint256 qty1, uint256 feeGrowthInside ); /// @notice Remove liquidity from the caller /// Also sends reinvestment tokens (fees) to the caller for any fees collected /// while the position is in range /// Reinvestment tokens have to be burnt via #burnRTokens in exchange for token0 and token1 /// @param tickLower Position's lower tick for which to burn liquidity /// @param tickUpper Position's upper tick for which to burn liquidity /// @param qty Liquidity quantity to burn /// @return qty0 token0 quantity sent to the caller /// @return qty1 token1 quantity sent to the caller /// @return feeGrowthInside position's updated feeGrowthInside value function burn( int24 tickLower, int24 tickUpper, uint128 qty ) external returns ( uint256 qty0, uint256 qty1, uint256 feeGrowthInside ); /// @notice Burns reinvestment tokens in exchange to receive the fees collected in token0 and token1 /// @param qty Reinvestment token quantity to burn /// @param isLogicalBurn true if burning rTokens without returning any token0/token1 /// otherwise should transfer token0/token1 to sender /// @return qty0 token0 quantity sent to the caller for burnt reinvestment tokens /// @return qty1 token1 quantity sent to the caller for burnt reinvestment tokens function burnRTokens(uint256 qty, bool isLogicalBurn) external returns (uint256 qty0, uint256 qty1); /// @notice Swap token0 -> token1, or vice versa /// @dev This method's caller receives a callback in the form of ISwapCallback#swapCallback /// @dev swaps will execute up to limitSqrtP or swapQty is fully used /// @param recipient The address to receive the swap output /// @param swapQty The swap quantity, which implicitly configures the swap as exact input (>0), or exact output (<0) /// @param isToken0 Whether the swapQty is specified in token0 (true) or token1 (false) /// @param limitSqrtP the limit of sqrt price after swapping /// could be MAX_SQRT_RATIO-1 when swapping 1 -> 0 and MIN_SQRT_RATIO+1 when swapping 0 -> 1 for no limit swap /// @param data Any data to be passed through to the callback /// @return qty0 Exact token0 qty sent to recipient if < 0. Minimally received quantity if > 0. /// @return qty1 Exact token1 qty sent to recipient if < 0. Minimally received quantity if > 0. function swap( address recipient, int256 swapQty, bool isToken0, uint160 limitSqrtP, bytes calldata data ) external returns (int256 qty0, int256 qty1); /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback /// @dev The caller of this method receives a callback in the form of IFlashCallback#flashCallback /// @dev Fees collected are sent to the feeTo address if it is set in Factory /// @param recipient The address which will receive the token0 and token1 quantities /// @param qty0 token0 quantity to be loaned to the recipient /// @param qty1 token1 quantity to be loaned to the recipient /// @param data Any data to be passed through to the callback function flash( address recipient, uint256 qty0, uint256 qty1, bytes calldata data ) external; /// @notice sync fee of position /// @param tickLower Position's lower tick /// @param tickUpper Position's upper tick function tweakPosZeroLiq(int24 tickLower, int24 tickUpper) external returns(uint256 feeGrowthInsideLast); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolEvents { /// @notice Emitted only once per pool when #initialize is first called /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize /// @param sqrtP The initial price of the pool /// @param tick The initial tick of the pool event Initialize(uint160 sqrtP, int24 tick); /// @notice Emitted when liquidity is minted for a given position /// @dev transfers reinvestment tokens for any collected fees earned by the position /// @param sender address that minted the liquidity /// @param owner address of owner of the position /// @param tickLower position's lower tick /// @param tickUpper position's upper tick /// @param qty liquidity minted to the position range /// @param qty0 token0 quantity needed to mint the liquidity /// @param qty1 token1 quantity needed to mint the liquidity event Mint( address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 qty, uint256 qty0, uint256 qty1 ); /// @notice Emitted when a position's liquidity is removed /// @dev transfers reinvestment tokens for any collected fees earned by the position /// @param owner address of owner of the position /// @param tickLower position's lower tick /// @param tickUpper position's upper tick /// @param qty liquidity removed /// @param qty0 token0 quantity withdrawn from removal of liquidity /// @param qty1 token1 quantity withdrawn from removal of liquidity event Burn( address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 qty, uint256 qty0, uint256 qty1 ); /// @notice Emitted when reinvestment tokens are burnt /// @param owner address which burnt the reinvestment tokens /// @param qty reinvestment token quantity burnt /// @param qty0 token0 quantity sent to owner for burning reinvestment tokens /// @param qty1 token1 quantity sent to owner for burning reinvestment tokens event BurnRTokens(address indexed owner, uint256 qty, uint256 qty0, uint256 qty1); /// @notice Emitted for swaps by the pool between token0 and token1 /// @param sender Address that initiated the swap call, and that received the callback /// @param recipient Address that received the swap output /// @param deltaQty0 Change in pool's token0 balance /// @param deltaQty1 Change in pool's token1 balance /// @param sqrtP Pool's sqrt price after the swap /// @param liquidity Pool's liquidity after the swap /// @param currentTick Log base 1.0001 of pool's price after the swap event Swap( address indexed sender, address indexed recipient, int256 deltaQty0, int256 deltaQty1, uint160 sqrtP, uint128 liquidity, int24 currentTick ); /// @notice Emitted by the pool for any flash loans of token0/token1 /// @param sender The address that initiated the flash loan, and that received the callback /// @param recipient The address that received the flash loan quantities /// @param qty0 token0 quantity loaned to the recipient /// @param qty1 token1 quantity loaned to the recipient /// @param paid0 token0 quantity paid for the flash, which can exceed qty0 + fee /// @param paid1 token1 quantity paid for the flash, which can exceed qty0 + fee event Flash( address indexed sender, address indexed recipient, uint256 qty0, uint256 qty1, uint256 paid0, uint256 paid1 ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {IFactory} from '../IFactory.sol'; import {IPoolOracle} from '../oracle/IPoolOracle.sol'; interface IPoolStorage { /// @notice The contract that deployed the pool, which must adhere to the IFactory interface /// @return The contract address function factory() external view returns (IFactory); /// @notice The oracle contract that stores necessary data for price oracle /// @return The contract address function poolOracle() external view returns (IPoolOracle); /// @notice The first of the two tokens of the pool, sorted by address /// @return The token contract address function token0() external view returns (IERC20); /// @notice The second of the two tokens of the pool, sorted by address /// @return The token contract address function token1() external view returns (IERC20); /// @notice The fee to be charged for a swap in basis points /// @return The swap fee in basis points function swapFeeUnits() external view returns (uint24); /// @notice The pool tick distance /// @dev Ticks can only be initialized and used at multiples of this value /// It remains an int24 to avoid casting even though it is >= 1. /// e.g: a tickDistance of 5 means ticks can be initialized every 5th tick, i.e., ..., -10, -5, 0, 5, 10, ... /// @return The tick distance function tickDistance() external view returns (int24); /// @notice Maximum gross liquidity that an initialized tick can have /// @dev This is to prevent overflow the pool's active base liquidity (uint128) /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool /// @return The max amount of liquidity per tick function maxTickLiquidity() external view returns (uint128); /// @notice Look up information about a specific tick in the pool /// @param tick The tick to look up /// @return liquidityGross total liquidity amount from positions that uses this tick as a lower or upper tick /// liquidityNet how much liquidity changes when the pool tick crosses above the tick /// feeGrowthOutside the fee growth on the other side of the tick relative to the current tick /// secondsPerLiquidityOutside the seconds per unit of liquidity spent on the other side of the tick relative to the current tick function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside, uint128 secondsPerLiquidityOutside ); /// @notice Returns the previous and next initialized ticks of a specific tick /// @dev If specified tick is uninitialized, the returned values are zero. /// @param tick The tick to look up function initializedTicks(int24 tick) external view returns (int24 previous, int24 next); /// @notice Returns the information about a position by the position's key /// @return liquidity the liquidity quantity of the position /// @return feeGrowthInsideLast fee growth inside the tick range as of the last mint / burn action performed function getPositions( address owner, int24 tickLower, int24 tickUpper ) external view returns (uint128 liquidity, uint256 feeGrowthInsideLast); /// @notice Fetches the pool's prices, ticks and lock status /// @return sqrtP sqrt of current price: sqrt(token1/token0) /// @return currentTick pool's current tick /// @return nearestCurrentTick pool's nearest initialized tick that is <= currentTick /// @return locked true if pool is locked, false otherwise function getPoolState() external view returns ( uint160 sqrtP, int24 currentTick, int24 nearestCurrentTick, bool locked ); /// @notice Fetches the pool's liquidity values /// @return baseL pool's base liquidity without reinvest liqudity /// @return reinvestL the liquidity is reinvested into the pool /// @return reinvestLLast last cached value of reinvestL, used for calculating reinvestment token qty function getLiquidityState() external view returns ( uint128 baseL, uint128 reinvestL, uint128 reinvestLLast ); /// @return feeGrowthGlobal All-time fee growth per unit of liquidity of the pool function getFeeGrowthGlobal() external view returns (uint256); /// @return secondsPerLiquidityGlobal All-time seconds per unit of liquidity of the pool /// @return lastUpdateTime The timestamp in which secondsPerLiquidityGlobal was last updated function getSecondsPerLiquidityData() external view returns (uint128 secondsPerLiquidityGlobal, uint32 lastUpdateTime); /// @notice Calculates and returns the active time per unit of liquidity until current block.timestamp /// @param tickLower The lower tick (of a position) /// @param tickUpper The upper tick (of a position) /// @return secondsPerLiquidityInside active time (multiplied by 2^96) /// between the 2 ticks, per unit of liquidity. function getSecondsPerLiquidityInside(int24 tickLower, int24 tickUpper) external view returns (uint128 secondsPerLiquidityInside); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolOracle { /// @notice Owner withdrew funds in the pool oracle in case some funds are stuck there event OwnerWithdrew( address indexed owner, address indexed token, uint256 indexed amount ); /// @notice Emitted by the Pool Oracle for increases to the number of observations that can be stored /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index /// just before a mint/swap/burn. /// @param pool The pool address to update /// @param observationCardinalityNextOld The previous value of the next observation cardinality /// @param observationCardinalityNextNew The updated value of the next observation cardinality event IncreaseObservationCardinalityNext( address pool, uint16 observationCardinalityNextOld, uint16 observationCardinalityNextNew ); /// @notice Initalize observation data for the caller. function initializeOracle(uint32 time) external returns (uint16 cardinality, uint16 cardinalityNext); /// @notice Write a new oracle entry into the array /// and update the observation index and cardinality /// Read the Oralce.write function for more details function writeNewEntry( uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint16 cardinality, uint16 cardinalityNext ) external returns (uint16 indexUpdated, uint16 cardinalityUpdated); /// @notice Write a new oracle entry into the array, take the latest observaion data as inputs /// and update the observation index and cardinality /// Read the Oralce.write function for more details function write( uint32 blockTimestamp, int24 tick, uint128 liquidity ) external returns (uint16 indexUpdated, uint16 cardinalityUpdated); /// @notice Increase the maximum number of price observations that this pool will store /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to /// the input observationCardinalityNext. /// @param pool The pool address to be updated /// @param observationCardinalityNext The desired minimum number of observations for the pool to store function increaseObservationCardinalityNext( address pool, uint16 observationCardinalityNext ) external; /// @notice Returns the accumulator values as of each time seconds ago from the latest block time in the array of `secondsAgos` /// @dev Reverts if `secondsAgos` > oldest observation /// @dev It fetches the latest current tick data from the pool /// Read the Oracle.observe function for more details function observeFromPool( address pool, uint32[] memory secondsAgos ) external view returns (int56[] memory tickCumulatives); /// @notice Returns the accumulator values as the time seconds ago from the latest block time of secondsAgo /// @dev Reverts if `secondsAgo` > oldest observation /// @dev It fetches the latest current tick data from the pool /// Read the Oracle.observeSingle function for more details function observeSingleFromPool( address pool, uint32 secondsAgo ) external view returns (int56 tickCumulative); /// @notice Return the latest pool observation data given the pool address function getPoolObservation(address pool) external view returns (bool initialized, uint16 index, uint16 cardinality, uint16 cardinalityNext); /// @notice Returns data about a specific observation index /// @param pool The pool address of the observations array to fetch /// @param index The element of the observations array to fetch /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time /// ago, rather than at a specific index in the array. /// @return blockTimestamp The timestamp of the observation, /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, /// Returns initialized whether the observation has been initialized and the values are safe to use function getObservationAt(address pool, uint256 index) external view returns ( uint32 blockTimestamp, int56 tickCumulative, bool initialized ); }
{ "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"quoteExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160[]","name":"afterSqrtPList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint24","name":"feeUnits","type":"uint24"},{"internalType":"uint160","name":"limitSqrtP","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactInputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactInputSingle","outputs":[{"components":[{"internalType":"uint256","name":"usedAmount","type":"uint256"},{"internalType":"uint256","name":"returnedAmount","type":"uint256"},{"internalType":"uint160","name":"afterSqrtP","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"internalType":"struct IQuoterV2.QuoteOutput","name":"output","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"quoteExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160[]","name":"afterSqrtPList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"feeUnits","type":"uint24"},{"internalType":"uint160","name":"limitSqrtP","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactOutputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactOutputSingle","outputs":[{"components":[{"internalType":"uint256","name":"usedAmount","type":"uint256"},{"internalType":"uint256","name":"returnedAmount","type":"uint256"},{"internalType":"uint160","name":"afterSqrtP","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"internalType":"struct IQuoterV2.QuoteOutput","name":"output","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"swapCallback","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162001e3e38038062001e3e8339810160408190526200003491620000bf565b6001600160a01b038116608081905260408051630d04b86b60e41b8152905163d04b86b091600480820192602092909190829003018186803b1580156200007a57600080fd5b505afa1580156200008f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b59190620000f1565b60a052506200010b565b600060208284031215620000d257600080fd5b81516001600160a01b0381168114620000ea57600080fd5b9392505050565b6000602082840312156200010457600080fd5b5051919050565b60805160a051611d06620001386000396000610e510152600081816101190152610e2d0152611d066000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063c6a5026a11610050578063c6a5026a14610160578063cdca175314610173578063fa483e721461018657600080fd5b80632f80bb1d14610077578063bd21704a146100a3578063c45a015514610114575b600080fd5b61008a6100853660046116a3565b61019b565b60405161009a94939291906116e8565b60405180910390f35b6100b66100b1366004611852565b6103ab565b60405161009a9190600060a082019050825182526020830151602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015263ffffffff60608401511660608301526080830151608083015292915050565b61013b7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161009a565b6100b661016e366004611852565b610698565b61008a6101813660046116a3565b610937565b610199610194366004611875565b610b2c565b005b600060608060006101ab86610d53565b67ffffffffffffffff8111156101c3576101c3611589565b6040519080825280602002602001820160405280156101ec578160200160208202803683370190505b5092506101f886610d53565b67ffffffffffffffff81111561021057610210611589565b604051908082528060200260200182016040528015610239578160200160208202803683370190505b50915060005b600080600061024d8a610d7f565b92509250925060006102cc6040518060a001604052808573ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018c81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152506103ab565b905080604001518886815181106102e5576102e56118c5565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508060600151878681518110610336576103366118c5565b63ffffffff9092166020928302919091018201528101516080820151909a5061035f9087611923565b95508461036b8161193b565b9550506103778b610dbb565b1561038c576103858b610df5565b9a50610399565b89985050505050506103a2565b5050505061023f565b92959194509250565b6103f96040518060a001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600063ffffffff168152602001600081525090565b60208201518251606084015173ffffffffffffffffffffffffffffffffffffffff808416908316119260009261043192909190610e26565b9050836080015173ffffffffffffffffffffffffffffffffffffffff166000141561045f5760408401516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff166324b31a0c3061048e8860400151610e7d565b61049790611974565b86896080015173ffffffffffffffffffffffffffffffffffffffff166000146104c45789608001516104fd565b876104de576104d96401000276a360016119ad565b6104fd565b6104fd600173fffd8963efd1fc6a506488495d951d5263988d266119e5565b6020808c015160608d01518d516040516105789401606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016105a7959493929190611a94565b6040805180830381600087803b1580156105c057600080fd5b505af192505050801561060e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261060b91810190611ae6565b60015b61068d573d80801561063c576040519150601f19603f3d011682016040523d82523d6000602084013e610641565b606091505b5060005a61064f9084611b0a565b9050866080015173ffffffffffffffffffffffffffffffffffffffff166000141561067957600080555b610684828583610eaf565b95505050610690565b50505b505050919050565b6106e66040518060a001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600063ffffffff168152602001600081525090565b60208201518251606084015173ffffffffffffffffffffffffffffffffffffffff808416908316109260009261071e92909190610e26565b845160608601516020808801516040519495506000946107a194939201606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b60405160208183030381529060405290506000856080015173ffffffffffffffffffffffffffffffffffffffff166000146107e0578560800151610819565b8361080957610804600173fffd8963efd1fc6a506488495d951d5263988d266119e5565b610819565b6108196401000276a360016119ad565b905060005a90508373ffffffffffffffffffffffffffffffffffffffff166324b31a0c3061084a8a60400151610e7d565b8886886040518663ffffffff1660e01b815260040161086d959493929190611a94565b6040805180830381600087803b15801561088657600080fd5b505af19250505080156108d4575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526108d191810190611ae6565b60015b61092b573d808015610902576040519150601f19603f3d011682016040523d82523d6000602084013e610907565b606091505b5060005a6109159084611b0a565b9050610922828783610eaf565b9750505061068d565b50505050505050919050565b6000606080600061094786610d53565b67ffffffffffffffff81111561095f5761095f611589565b604051908082528060200260200182016040528015610988578160200160208202803683370190505b50925061099486610d53565b67ffffffffffffffff8111156109ac576109ac611589565b6040519080825280602002602001820160405280156109d5578160200160208202803683370190505b50915060005b60008060006109e98a610d7f565b9250925092506000610a686040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018c81526020018462ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610698565b90508060400151888681518110610a8157610a816118c5565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508060600151878681518110610ad257610ad26118c5565b63ffffffff9092166020928302919091018201528101516080820151909a50610afb9087611923565b955084610b078161193b565b955050610b138b610dbb565b1561038c57610b218b610df5565b9a50505050506109db565b6000831380610b3b5750600082135b610b4457600080fd5b6000806000610b5284610d7f565b9250925092506000610b65848484610e26565b905073ffffffffffffffffffffffffffffffffffffffff81163314610beb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c69642073656e64657200000000000000000000000000000000000060448201526064015b60405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610c3457600080fd5b505afa158015610c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6c9190611b38565b5092505091506000806000808c13610cbd578873ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16108b8d610cb890611974565b610cf7565b8773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16108c8c610cf790611974565b9250925092508215610d2057604051828152816020820152856040820152846060820152608081fd5b60005415610d36576000548114610d3657600080fd5b604051818152826020820152856040820152846060820152608081fd5b6000610d6160036014611923565b60148351610d6f9190611b0a565b610d799190611b95565b92915050565b60008080610d8d8482610fde565b9250610d9a84601461106e565b9050610db2610dab60036014611923565b8590610fde565b91509193909250565b6000610dc960036014611923565b6014610dd6600382611923565b610de09190611923565b610dea9190611923565b825110159050919050565b6060610d79610e0660036014611923565b610e1260036014611923565b8451610e1e9190611b0a565b8491906110ee565b6000610e757f00000000000000000000000000000000000000000000000000000000000000008585857f0000000000000000000000000000000000000000000000000000000000000000611268565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610eab57600080fd5b5090565b610efd6040518060a001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600063ffffffff168152602001600081525090565b6000808473ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610f4657600080fd5b505afa158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7e9190611b38565b509350610f8e91508790506113b1565b73ffffffffffffffffffffffffffffffffffffffff909116604087015260208601919091529084529050610fc385838361149c565b63ffffffff1660608401525050608081019190915292915050565b6000610feb826014611923565b83511015611055576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610be2565b5001602001516c01000000000000000000000000900490565b600061107b826003611923565b835110156110e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610be2565b50016003015190565b6060816110fc81601f611923565b1015611164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610be2565b61116e8284611923565b845110156111d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610be2565b6060821580156111f7576040519150600082526020820160405261125f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611230578051835260209283019201611218565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16106112a45783856112a7565b84845b6040805173ffffffffffffffffffffffffffffffffffffffff808516602083015283169181019190915262ffffff86166060820152919650945060009087906080016040516020818303038152906040528051906020012084604051602001611370939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120979650505050505050565b60008060008084516080146114795760448551101561142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f556e6578706563746564206572726f72000000000000000000000000000000006044820152606401610be2565b600485019450848060200190518101906114469190611bd0565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610be29190611c47565b8480602001905181019061148d9190611c5a565b93509350935093509193509193565b600080808360020b8560020b126114b45783856114b7565b84845b915091505b8060020b8260020b1461158057826114d381611ca2565b6040517fc0ac75cf000000000000000000000000000000000000000000000000000000008152600285900b600482015290945073ffffffffffffffffffffffffffffffffffffffff8816915063c0ac75cf90602401604080518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115779190611cc6565b92506114bc9050565b50509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156115ff576115ff611589565b604052919050565b600067ffffffffffffffff82111561162157611621611589565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261165e57600080fd5b813561167161166c82611607565b6115b8565b81815284602083860101111561168657600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156116b657600080fd5b823567ffffffffffffffff8111156116cd57600080fd5b6116d98582860161164d565b95602094909401359450505050565b600060808201868352602060808185015281875180845260a086019150828901935060005b8181101561173f57845173ffffffffffffffffffffffffffffffffffffffff168352938301939183019160010161170d565b50508481036040860152865180825290820192508187019060005b8181101561177c57825163ffffffff168552938301939183019160010161175a565b5050505060609290920192909252949350505050565b73ffffffffffffffffffffffffffffffffffffffff811681146117b457600080fd5b50565b600060a082840312156117c957600080fd5b60405160a0810181811067ffffffffffffffff821117156117ec576117ec611589565b60405290508082356117fd81611792565b8152602083013561180d81611792565b602082015260408381013590820152606083013562ffffff8116811461183257600080fd5b6060820152608083013561184581611792565b6080919091015292915050565b600060a0828403121561186457600080fd5b61186e83836117b7565b9392505050565b60008060006060848603121561188a57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156118af57600080fd5b6118bb8682870161164d565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611936576119366118f4565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561196d5761196d6118f4565b5060010190565b60007f80000000000000000000000000000000000000000000000000000000000000008214156119a6576119a66118f4565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8083168185168083038211156119dc576119dc6118f4565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015611a1257611a126118f4565b039392505050565b60005b83811015611a35578181015183820152602001611a1d565b83811115611a44576000848401525b50505050565b60008151808452611a62816020860160208601611a1a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352866020840152851515604084015280851660608401525060a06080830152611adb60a0830184611a4a565b979650505050505050565b60008060408385031215611af957600080fd5b505080516020909101519092909150565b600082821015611b1c57611b1c6118f4565b500390565b8051600281900b8114611b3357600080fd5b919050565b60008060008060808587031215611b4e57600080fd5b8451611b5981611792565b9350611b6760208601611b21565b9250611b7560408601611b21565b915060608501518015158114611b8a57600080fd5b939692955090935050565b600082611bcb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215611be257600080fd5b815167ffffffffffffffff811115611bf957600080fd5b8201601f81018413611c0a57600080fd5b8051611c1861166c82611607565b818152856020838501011115611c2d57600080fd5b611c3e826020830160208601611a1a565b95945050505050565b60208152600061186e6020830184611a4a565b60008060008060808587031215611c7057600080fd5b84519350602085015192506040850151611c8981611792565b9150611c9760608601611b21565b905092959194509250565b600063ffffffff80831681811415611cbc57611cbc6118f4565b6001019392505050565b60008060408385031215611cd957600080fd5b611ce283611b21565b9150611cf060208401611b21565b9050925092905056fea164736f6c6343000809000a000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a
-----Decoded View---------------
Arg [0] : _factory (address): 0xc7a590291e07b9fe9e64b86c58fd8fc764308c4a
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.