Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
931218 | 9 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Oracle
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 100 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.26; import {PoolStorage, Observation, TickInfo, Slot0} from './PoolStorage.sol'; /// @title Oracle /// @notice Provides price and liquidity data useful for a wide variety of system designs /// @dev Instances of stored oracle data, "observations", are collected in the oracle array /// Every pool is initialized with an oracle array length of 1. Anyone can pay the SSTOREs to increase the /// maximum length of the oracle array. New slots will be added when the array is fully populated. /// Observations are overwritten when the full length of the oracle array is populated. /// The most recent observation is available, independent of the length of the oracle array, by passing 0 to observe() library Oracle { error I(); error OLD(); /// @notice Transforms a previous observation into a new observation, given the passage of time and the current tick and liquidity values /// @dev blockTimestamp _must_ be chronologically equal to or greater than last.blockTimestamp, safe for 0 or 1 overflows /// @param last The specified observation to be transformed /// @param blockTimestamp The timestamp of the new observation /// @param tick The active tick at the time of the new observation /// @param liquidity The total in-range liquidity at the time of the new observation /// @return Observation The newly populated observation function transform( Observation memory last, uint32 blockTimestamp, int24 tick, uint128 liquidity ) private pure returns (Observation memory) { unchecked { uint32 delta = blockTimestamp - last.blockTimestamp; return Observation({ blockTimestamp: blockTimestamp, tickCumulative: last.tickCumulative + int56(tick) * int56(uint56(delta)), secondsPerLiquidityCumulativeX128: last.secondsPerLiquidityCumulativeX128 + ((uint160(delta) << 128) / (liquidity > 0 ? liquidity : 1)), initialized: true }); } } /// @notice Initialize the oracle array by writing the first slot. Called once for the lifecycle of the observations array /// @param self The stored oracle array /// @param time The time of the oracle initialization, via block.timestamp truncated to uint32 /// @return cardinality The number of populated elements in the oracle array /// @return cardinalityNext The new length of the oracle array, independent of population function initialize( Observation[65535] storage self, uint32 time ) internal returns (uint16 cardinality, uint16 cardinalityNext) { self[0] = Observation({ blockTimestamp: time, tickCumulative: 0, secondsPerLiquidityCumulativeX128: 0, initialized: true }); return (1, 1); } /// @notice Writes an oracle observation to the array /// @dev Writable at most once per block. Index represents the most recently written element. cardinality and index must be tracked externally. /// If the index is at the end of the allowable array length (according to cardinality), and the next cardinality /// is greater than the current one, cardinality may be increased. This restriction is created to preserve ordering. /// @param self The stored oracle array /// @param index The index of the observation that was most recently written to the observations array /// @param blockTimestamp The timestamp of the new observation /// @param tick The active tick at the time of the new observation /// @param liquidity The total in-range liquidity at the time of the new observation /// @param cardinality The number of populated elements in the oracle array /// @param cardinalityNext The new length of the oracle array, independent of population /// @return indexUpdated The new index of the most recently written element in the oracle array /// @return cardinalityUpdated The new cardinality of the oracle array function write( Observation[65535] storage self, uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint16 cardinality, uint16 cardinalityNext ) internal returns (uint16 indexUpdated, uint16 cardinalityUpdated) { unchecked { Observation memory last = self[index]; /// @dev early return if we've already written an observation this block if (last.blockTimestamp == blockTimestamp) return (index, cardinality); /// @dev if the conditions are right, we can bump the cardinality if (cardinalityNext > cardinality && index == (cardinality - 1)) { cardinalityUpdated = cardinalityNext; } else { cardinalityUpdated = cardinality; } indexUpdated = (index + 1) % cardinalityUpdated; self[indexUpdated] = transform(last, blockTimestamp, tick, liquidity); } } /// @notice Prepares the oracle array to store up to `next` observations /// @param self The stored oracle array /// @param current The current next cardinality of the oracle array /// @param next The proposed next cardinality which will be populated in the oracle array /// @return next The next cardinality which will be populated in the oracle array function grow(Observation[65535] storage self, uint16 current, uint16 next) internal returns (uint16) { unchecked { if (current <= 0) revert I(); /// @dev no-op if the passed next value isn't greater than the current next value if (next <= current) return current; /// @dev store in each slot to prevent fresh SSTOREs in swaps /// @dev this data will not be used because the initialized boolean is still false for (uint16 i = current; i < next; i++) self[i].blockTimestamp = 1; return next; } } /// @notice comparator for 32-bit timestamps /// @dev safe for 0 or 1 overflows, a and b _must_ be chronologically before or equal to time /// @param time A timestamp truncated to 32 bits /// @param a A comparison timestamp from which to determine the relative position of `time` /// @param b From which to determine the relative position of `time` /// @return Whether `a` is chronologically <= `b` function lte(uint32 time, uint32 a, uint32 b) private pure returns (bool) { unchecked { /// @dev if there hasn't been overflow, no need to adjust if (a <= time && b <= time) return a <= b; uint256 aAdjusted = a > time ? a : a + 2 ** 32; uint256 bAdjusted = b > time ? b : b + 2 ** 32; return aAdjusted <= bAdjusted; } } /// @notice Fetches the observations beforeOrAt and atOrAfter a target, i.e. where [beforeOrAt, atOrAfter] is satisfied. /// The result may be the same observation, or adjacent observations. /// @dev The answer must be contained in the array, used when the target is located within the stored observation /// boundaries: older than the most recent observation and younger, or the same age as, the oldest observation /// @param self The stored oracle array /// @param time The current block.timestamp /// @param target The timestamp at which the reserved observation should be for /// @param index The index of the observation that was most recently written to the observations array /// @param cardinality The number of populated elements in the oracle array /// @return beforeOrAt The observation recorded before, or at, the target /// @return atOrAfter The observation recorded at, or after, the target function binarySearch( Observation[65535] storage self, uint32 time, uint32 target, uint16 index, uint16 cardinality ) private view returns (Observation memory beforeOrAt, Observation memory atOrAfter) { unchecked { /// @dev oldest observation uint256 l = (index + 1) % cardinality; /// @dev newest observation uint256 r = l + cardinality - 1; uint256 i; while (true) { i = (l + r) / 2; beforeOrAt = self[i % cardinality]; /// @dev we've landed on an uninitialized tick, keep searching higher (more recently) if (!beforeOrAt.initialized) { l = i + 1; continue; } atOrAfter = self[(i + 1) % cardinality]; bool targetAtOrAfter = lte(time, beforeOrAt.blockTimestamp, target); /// @dev check if we've found the answer! if (targetAtOrAfter && lte(time, target, atOrAfter.blockTimestamp)) break; if (!targetAtOrAfter) r = i - 1; else l = i + 1; } } } /// @notice Fetches the observations beforeOrAt and atOrAfter a given target, i.e. where [beforeOrAt, atOrAfter] is satisfied /// @dev Assumes there is at least 1 initialized observation. /// Used by observeSingle() to compute the counterfactual accumulator values as of a given block timestamp. /// @param self The stored oracle array /// @param time The current block.timestamp /// @param target The timestamp at which the reserved observation should be for /// @param tick The active tick at the time of the returned or simulated observation /// @param index The index of the observation that was most recently written to the observations array /// @param liquidity The total pool liquidity at the time of the call /// @param cardinality The number of populated elements in the oracle array /// @return beforeOrAt The observation which occurred at, or before, the given timestamp /// @return atOrAfter The observation which occurred at, or after, the given timestamp function getSurroundingObservations( Observation[65535] storage self, uint32 time, uint32 target, int24 tick, uint16 index, uint128 liquidity, uint16 cardinality ) private view returns (Observation memory beforeOrAt, Observation memory atOrAfter) { unchecked { /// @dev optimistically set before to the newest observation beforeOrAt = self[index]; /// @dev if the target is chronologically at or after the newest observation, we can early return if (lte(time, beforeOrAt.blockTimestamp, target)) { if (beforeOrAt.blockTimestamp == target) { /// @dev if newest observation equals target, we're in the same block, so we can ignore atOrAfter return (beforeOrAt, atOrAfter); } else { /// @dev otherwise, we need to transform return (beforeOrAt, transform(beforeOrAt, target, tick, liquidity)); } } /// @dev now, set before to the oldest observation beforeOrAt = self[(index + 1) % cardinality]; if (!beforeOrAt.initialized) beforeOrAt = self[0]; /// @dev ensure that the target is chronologically at or after the oldest observation if (!lte(time, beforeOrAt.blockTimestamp, target)) revert OLD(); /// @dev if we've reached this point, we have to binary search return binarySearch(self, time, target, index, cardinality); } } /// @dev Reverts if an observation at or before the desired observation timestamp does not exist. /// 0 may be passed as `secondsAgo' to return the current cumulative values. /// If called with a timestamp falling between two observations, returns the counterfactual accumulator values /// at exactly the timestamp between the two observations. /// @param self The stored oracle array /// @param time The current block timestamp /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an observation /// @param tick The current tick /// @param index The index of the observation that was most recently written to the observations array /// @param liquidity The current in-range pool liquidity /// @param cardinality The number of populated elements in the oracle array /// @return tickCumulative The tick * time elapsed since the pool was first initialized, as of `secondsAgo` /// @return secondsPerLiquidityCumulativeX128 The time elapsed / max(1, liquidity) since the pool was first initialized, as of `secondsAgo` function observeSingle( Observation[65535] storage self, uint32 time, uint32 secondsAgo, int24 tick, uint16 index, uint128 liquidity, uint16 cardinality ) internal view returns (int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128) { unchecked { if (secondsAgo == 0) { Observation memory last = self[index]; if (last.blockTimestamp != time) last = transform(last, time, tick, liquidity); return (last.tickCumulative, last.secondsPerLiquidityCumulativeX128); } uint32 target = time - secondsAgo; (Observation memory beforeOrAt, Observation memory atOrAfter) = getSurroundingObservations( self, time, target, tick, index, liquidity, cardinality ); if (target == beforeOrAt.blockTimestamp) { /// @dev we're at the left boundary return (beforeOrAt.tickCumulative, beforeOrAt.secondsPerLiquidityCumulativeX128); } else if (target == atOrAfter.blockTimestamp) { /// @dev we're at the right boundary return (atOrAfter.tickCumulative, atOrAfter.secondsPerLiquidityCumulativeX128); } else { /// @dev we're in the middle uint32 observationTimeDelta = atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; uint32 targetDelta = target - beforeOrAt.blockTimestamp; return ( beforeOrAt.tickCumulative + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / int56(uint56(observationTimeDelta))) * int56(uint56(targetDelta)), beforeOrAt.secondsPerLiquidityCumulativeX128 + uint160( (uint256( atOrAfter.secondsPerLiquidityCumulativeX128 - beforeOrAt.secondsPerLiquidityCumulativeX128 ) * targetDelta) / observationTimeDelta ) ); } } } /// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos` /// @dev Reverts if `secondsAgos` > oldest observation /// @param self The stored oracle array /// @param time The current block.timestamp /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an observation /// @param tick The current tick /// @param index The index of the observation that was most recently written to the observations array /// @param liquidity The current in-range pool liquidity /// @param cardinality The number of populated elements in the oracle array /// @return tickCumulatives The tick * time elapsed since the pool was first initialized, as of each `secondsAgo` /// @return secondsPerLiquidityCumulativeX128s The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of each `secondsAgo` function observe( Observation[65535] storage self, uint32 time, uint32[] memory secondsAgos, int24 tick, uint16 index, uint128 liquidity, uint16 cardinality ) internal view returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s) { unchecked { if (cardinality <= 0) revert I(); tickCumulatives = new int56[](secondsAgos.length); secondsPerLiquidityCumulativeX128s = new uint160[](secondsAgos.length); for (uint256 i = 0; i < secondsAgos.length; i++) { (tickCumulatives[i], secondsPerLiquidityCumulativeX128s[i]) = observeSingle( self, time, secondsAgos[i], tick, index, liquidity, cardinality ); } } } function newPeriod( Observation[65535] storage self, uint16 index, uint256 period ) external returns (uint160 secondsPerLiquidityCumulativeX128) { Observation memory last = self[index]; PoolStorage.PoolState storage $ = PoolStorage.getStorage(); unchecked { uint32 delta = uint32(period) * 1 weeks - 1 - last.blockTimestamp; secondsPerLiquidityCumulativeX128 = last.secondsPerLiquidityCumulativeX128 + ((uint160(delta) << 128) / ($.liquidity > 0 ? $.liquidity : 1)); self[index] = Observation({ blockTimestamp: uint32(period) * 1 weeks - 1, tickCumulative: last.tickCumulative + int56($.slot0.tick) * int56(uint56(delta)), secondsPerLiquidityCumulativeX128: secondsPerLiquidityCumulativeX128, initialized: last.initialized }); } } struct SnapShot { int56 tickCumulativeLower; int56 tickCumulativeUpper; uint160 secondsPerLiquidityOutsideLowerX128; uint160 secondsPerLiquidityOutsideUpperX128; uint32 secondsOutsideLower; uint32 secondsOutsideUpper; } struct SnapshotCumulativesInsideCache { uint32 time; int56 tickCumulative; uint160 secondsPerLiquidityCumulativeX128; } /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed. /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first /// snapshot is taken and the second snapshot is taken. Boosted data is only valid if it's within the same period /// @param tickLower The lower tick of the range /// @param tickUpper The upper tick of the range /// @return tickCumulativeInside The snapshot of the tick accumulator for the range /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range /// @return secondsInside The snapshot of seconds per liquidity for the range function snapshotCumulativesInside( int24 tickLower, int24 tickUpper, uint32 _blockTimestamp ) external view returns (int56 tickCumulativeInside, uint160 secondsPerLiquidityInsideX128, uint32 secondsInside) { PoolStorage.PoolState storage $ = PoolStorage.getStorage(); TickInfo storage lower = $._ticks[tickLower]; TickInfo storage upper = $._ticks[tickUpper]; SnapShot memory snapshot; bool initializedLower; ( snapshot.tickCumulativeLower, snapshot.secondsPerLiquidityOutsideLowerX128, snapshot.secondsOutsideLower, initializedLower ) = ( lower.tickCumulativeOutside, lower.secondsPerLiquidityOutsideX128, lower.secondsOutside, lower.initialized ); require(initializedLower); bool initializedUpper; ( snapshot.tickCumulativeUpper, snapshot.secondsPerLiquidityOutsideUpperX128, snapshot.secondsOutsideUpper, initializedUpper ) = ( upper.tickCumulativeOutside, upper.secondsPerLiquidityOutsideX128, upper.secondsOutside, upper.initialized ); require(initializedUpper); Slot0 memory _slot0 = $.slot0; unchecked { if (_slot0.tick < tickLower) { return ( snapshot.tickCumulativeLower - snapshot.tickCumulativeUpper, snapshot.secondsPerLiquidityOutsideLowerX128 - snapshot.secondsPerLiquidityOutsideUpperX128, snapshot.secondsOutsideLower - snapshot.secondsOutsideUpper ); } else if (_slot0.tick < tickUpper) { SnapshotCumulativesInsideCache memory cache; cache.time = _blockTimestamp; (cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128) = observeSingle( $.observations, cache.time, 0, _slot0.tick, _slot0.observationIndex, $.liquidity, _slot0.observationCardinality ); return ( cache.tickCumulative - snapshot.tickCumulativeLower - snapshot.tickCumulativeUpper, cache.secondsPerLiquidityCumulativeX128 - snapshot.secondsPerLiquidityOutsideLowerX128 - snapshot.secondsPerLiquidityOutsideUpperX128, cache.time - snapshot.secondsOutsideLower - snapshot.secondsOutsideUpper ); } else { return ( snapshot.tickCumulativeUpper - snapshot.tickCumulativeLower, snapshot.secondsPerLiquidityOutsideUpperX128 - snapshot.secondsPerLiquidityOutsideLowerX128, snapshot.secondsOutsideUpper - snapshot.secondsOutsideLower ); } } } /// @notice Returns the seconds per liquidity and seconds inside a tick range for a period /// @dev This does not ensure the range is a valid range /// @param period The timestamp of the period /// @param tickLower The lower tick of the range /// @param tickUpper The upper tick of the range /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range function periodCumulativesInside( uint32 period, int24 tickLower, int24 tickUpper, uint32 _blockTimestamp ) external view returns (uint160 secondsPerLiquidityInsideX128) { PoolStorage.PoolState storage $ = PoolStorage.getStorage(); TickInfo storage lower = $._ticks[tickLower]; TickInfo storage upper = $._ticks[tickUpper]; SnapShot memory snapshot; { int24 startTick = $.periods[period].startTick; uint256 previousPeriod = $.periods[period].previousPeriod; snapshot.secondsPerLiquidityOutsideLowerX128 = uint160(lower.periodSecondsPerLiquidityOutsideX128[period]); if (tickLower <= startTick && snapshot.secondsPerLiquidityOutsideLowerX128 == 0) { snapshot.secondsPerLiquidityOutsideLowerX128 = $ .periods[previousPeriod] .endSecondsPerLiquidityPeriodX128; } snapshot.secondsPerLiquidityOutsideUpperX128 = uint160(upper.periodSecondsPerLiquidityOutsideX128[period]); if (tickUpper <= startTick && snapshot.secondsPerLiquidityOutsideUpperX128 == 0) { snapshot.secondsPerLiquidityOutsideUpperX128 = $ .periods[previousPeriod] .endSecondsPerLiquidityPeriodX128; } } int24 lastTick; uint256 currentPeriod = $.lastPeriod; { /// @dev if period is already finalized, use period's last tick, if not, use current tick if (currentPeriod > period) { lastTick = $.periods[period].lastTick; } else { lastTick = $.slot0.tick; } } unchecked { if (lastTick < tickLower) { return snapshot.secondsPerLiquidityOutsideLowerX128 - snapshot.secondsPerLiquidityOutsideUpperX128; } else if (lastTick < tickUpper) { SnapshotCumulativesInsideCache memory cache; /// @dev if period's on-going, observeSingle, if finalized, use endSecondsPerLiquidityPeriodX128 if (currentPeriod <= period) { cache.time = _blockTimestamp; /// @dev limit to the end of period if (cache.time >= currentPeriod * 1 weeks + 1 weeks) { cache.time = uint32(currentPeriod * 1 weeks + 1 weeks - 1); } Slot0 memory _slot0 = $.slot0; (, cache.secondsPerLiquidityCumulativeX128) = observeSingle( $.observations, cache.time, 0, _slot0.tick, _slot0.observationIndex, $.liquidity, _slot0.observationCardinality ); } else { cache.secondsPerLiquidityCumulativeX128 = $.periods[period].endSecondsPerLiquidityPeriodX128; } return cache.secondsPerLiquidityCumulativeX128 - snapshot.secondsPerLiquidityOutsideLowerX128 - snapshot.secondsPerLiquidityOutsideUpperX128; } else { return snapshot.secondsPerLiquidityOutsideUpperX128 - snapshot.secondsPerLiquidityOutsideLowerX128; } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.26; struct Slot0 { /// @dev the current price uint160 sqrtPriceX96; /// @dev the current tick int24 tick; /// @dev the most-recently updated index of the observations array uint16 observationIndex; /// @dev the current maximum number of observations that are being stored uint16 observationCardinality; /// @dev the next maximum number of observations to store, triggered in observations.write uint16 observationCardinalityNext; /// @dev the current protocol fee as a percentage of the swap fee taken on withdrawal /// @dev represented as an integer denominator (1/x)% uint8 feeProtocol; /// @dev whether the pool is locked bool unlocked; } struct Observation { /// @dev the block timestamp of the observation uint32 blockTimestamp; /// @dev the tick accumulator, i.e. tick * time elapsed since the pool was first initialized int56 tickCumulative; /// @dev the seconds per liquidity, i.e. seconds elapsed / max(1, liquidity) since the pool was first initialized uint160 secondsPerLiquidityCumulativeX128; /// @dev whether or not the observation is initialized bool initialized; } struct RewardInfo { /// @dev used to account for changes in the deposit amount int256 secondsDebtX96; /// @dev used to check if starting seconds have already been written bool initialized; /// @dev used to account for changes in secondsPerLiquidity int160 secondsPerLiquidityPeriodStartX128; } /// @dev info stored for each user's position struct PositionInfo { /// @dev the amount of liquidity owned by this position uint128 liquidity; /// @dev fee growth per unit of liquidity as of the last update to liquidity or fees owed uint256 feeGrowthInside0LastX128; uint256 feeGrowthInside1LastX128; /// @dev the fees owed to the position owner in token0/token1 uint128 tokensOwed0; uint128 tokensOwed1; mapping(uint256 => RewardInfo) periodRewardInfo; } /// @dev info stored for each initialized individual tick struct TickInfo { /// @dev the total position liquidity that references this tick uint128 liquidityGross; /// @dev amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; /// @dev fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) /// @dev only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; /// @dev the cumulative tick value on the other side of the tick int56 tickCumulativeOutside; /// @dev the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick) /// @dev only has relative meaning, not absolute — the value depends on when the tick is initialized uint160 secondsPerLiquidityOutsideX128; /// @dev the seconds spent on the other side of the tick (relative to the current tick) /// @dev only has relative meaning, not absolute — the value depends on when the tick is initialized uint32 secondsOutside; /// @dev true iff the tick is initialized, i.e. the value is exactly equivalent to the expression liquidityGross != 0 /// @dev these 8 bits are set to prevent fresh sstores when crossing newly initialized ticks bool initialized; /// @dev secondsPerLiquidityOutsideX128 separated into periods, placed here to preserve struct slots mapping(uint256 => uint256) periodSecondsPerLiquidityOutsideX128; } /// @dev info stored for each period struct PeriodInfo { uint32 previousPeriod; int24 startTick; int24 lastTick; uint160 endSecondsPerLiquidityPeriodX128; } /// @dev accumulated protocol fees in token0/token1 units struct ProtocolFees { uint128 token0; uint128 token1; } /// @dev Position period and liquidity struct PositionCheckpoint { uint256 period; uint256 liquidity; } library PoolStorage { /// @dev keccak256(abi.encode(uint256(keccak256("pool.storage")) - 1)) & ~bytes32(uint256(0xff)); bytes32 public constant POOL_STORAGE_LOCATION = 0xf047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800; /// @custom꞉storage‑location erc7201꞉pool.storage struct PoolState { Slot0 slot0; uint24 fee; uint256 feeGrowthGlobal0X128; uint256 feeGrowthGlobal1X128; ProtocolFees protocolFees; uint128 liquidity; mapping(int24 => TickInfo) _ticks; mapping(int16 => uint256) tickBitmap; mapping(bytes32 => PositionInfo) positions; Observation[65535] observations; mapping(uint256 => PeriodInfo) periods; uint256 lastPeriod; mapping(bytes32 => PositionCheckpoint[]) positionCheckpoints; bool initialized; address nfpManager; } /// @dev Return state storage struct for reading and writing function getStorage() internal pure returns (PoolState storage $) { assembly { $.slot := POOL_STORAGE_LOCATION } } }
{ "remappings": [ "@openzeppelin-contracts-upgradeable-5.1.0/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/", "@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/", "forge-std/=dependencies/forge-std-1.9.4/src/", "permit2/=lib/permit2/", "@openzeppelin-3.4.2/=node_modules/@openzeppelin-3.4.2/", "@openzeppelin-contracts-5.1.0/=dependencies/@openzeppelin-contracts-5.1.0/", "@uniswap/=node_modules/@uniswap/", "base64-sol/=node_modules/base64-sol/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std-1.9.4/=dependencies/forge-std-1.9.4/src/", "hardhat/=node_modules/hardhat/", "solmate/=node_modules/solmate/" ], "optimizer": { "enabled": true, "runs": 100 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": { "contracts/CL/core/libraries/Oracle.sol": { "Oracle": "0x739CB2b30fC47c19262aB023eaE966A15c2F9A28" }, "contracts/CL/core/libraries/Position.sol": { "Position": "0x0bE5821b66b82676a550fdfF0b686b3e2D85Ac62" }, "contracts/CL/core/libraries/ProtocolActions.sol": { "ProtocolActions": "0x2D26aa011df96ab6Ff66f7cB8EF1ed13Afb8A43B" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"I","type":"error"},{"inputs":[],"name":"OLD","type":"error"},{"inputs":[{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint32","name":"_blockTimestamp","type":"uint32"}],"name":"periodCumulativesInside","outputs":[{"internalType":"uint160","name":"secondsPerLiquidityInsideX128","type":"uint160"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint32","name":"_blockTimestamp","type":"uint32"}],"name":"snapshotCumulativesInside","outputs":[{"internalType":"int56","name":"tickCumulativeInside","type":"int56"},{"internalType":"uint160","name":"secondsPerLiquidityInsideX128","type":"uint160"},{"internalType":"uint32","name":"secondsInside","type":"uint32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60808060405234601b57610b6a90816100208239308160a20152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80639b7beb601461024f578063c51185d81461009f5763feb0d7171461003a575f80fd5b608036600319011261009b5760043563ffffffff8116810361009b5761005e6102b5565b906044358060020b810361009b576064359063ffffffff8216820361009b57602093610089936106c2565b6040516001600160a01b039091168152f35b5f80fd5b307f00000000000000000000000000000000000000000000000000000000000000001461009b57606036600319011261009b5760043560243561ffff8116810361009b576100f66100f0828461062c565b50610650565b805160408201515f516020610ad55f395f51905f525460443563ffffffff90811662093a800281165f19018116969316860393916101d4916001600160a01b0391909116906001600160801b0316801561024657905b6001600160a01b0391610175906001600160801b0316608088901b63ffffffff60801b1661068f565b011694602083015160060b60605f516020610b155f395f51905f525460a01c60020b9401511515936101a56102f5565b98895263ffffffff60208a01971660060b0260060b0160060b855260408701938685526060880193845261062c565b939093610233579451945191519051602092831b6affffffffffffff000000001663ffffffff969096169590951760589190911b600160581b600160f81b03161793151560f81b6001600160f81b031916939093179055604051908152f35b634e487b7160e01b5f525f60045260245ffd5b5060019061014c565b606036600319011261009b576004358060020b810361009b576102706102b5565b6044359163ffffffff8316830361009b5760609263ffffffff926102939261041f565b906040939293519360060b845260018060a01b03166020840152166040820152f35b602435908160020b820361009b57565b60020b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280660205260405f2090565b604051906080820182811067ffffffffffffffff82111761031557604052565b634e487b7160e01b5f52604160045260245ffd5b6040519060c0820182811067ffffffffffffffff821117610315576040525f60a0838281528260208201528260408201528260608201528260808201520152565b6040519060e0820182811067ffffffffffffffff821117610315576040528160c060ff5f516020610b155f395f51905f525460018060a01b03811684528060a01c60020b602085015261ffff8160b81c16604085015261ffff8160c81c16606085015261ffff8160d81c166080850152818160e81c1660a085015260f01c161515910152565b604051906060820182811067ffffffffffffffff821117610315576040525f6040838281528260208201520152565b92909161042b846102c5565b93610435846102c5565b936003610440610329565b960154956040810195608082019763ffffffff8160d81c16895260018060a01b038160381c1688528060060b835260f81c1561009b5760030154936020820192606083019460a084019663ffffffff8160d81c16885260018060a01b038160381c1687528060060b865260f81c1561009b576104ba61036a565b906020820192835160020b9160020b82125f1461051e57505050505063ffffffff9392849283925160060b905160060b900360060b9660018060a01b0390511660018060a01b039160018060a01b0390511690031696511691511690031691929190565b939a94999496959360020b13156105e8576105376103f0565b9963ffffffff1691828b525160020b90604081015161ffff16600160801b600190035f516020610ad55f395f51905f525416916060015161ffff169261057c94610997565b6001600160a01b0390811660408b01819052600692830b60208c0181905299519351945195519a519651975194830b93830b909903820b92909203900b9781169281169096038616919091039094169363ffffffff908116928116918116919091038116919091031690565b50505195519151905193519251600692830b96830b9690960390910b95506001600160a01b03928316908316039091169263ffffffff908116918116919091031690565b61ffff82101561063c5701905f90565b634e487b7160e01b5f52603260045260245ffd5b906106596102f5565b915463ffffffff81168352602081811c60060b90840152605881901c6001600160a01b0316604084015260f81c15156060830152565b6001600160a01b039091169081156106ae576001600160a01b03160490565b634e487b7160e01b5f52601260045260245ffd5b929091926106cf836102c5565b916106d9856102c5565b9263ffffffff6106e7610329565b93165f8181525f516020610af55f395f51905f5260209081526040808320546004958601835292819020546001600160a01b031690870181815298600290810b989284901c900b96939463ffffffff9093169392919087891315908161098e575b50610961575b845f5201602052606060018060a01b0360405f20541691019781895260020b948513159081610958575b5061092b575b507ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2809549281841194855f1461091157825f525f516020610af55f395f51905f5260205260405f205460381c60020b5b60020b908112156107fb575050935194516001600160a01b0390811695811695909503909416949350505050565b12156108f0576108096103f0565b936108c0575063ffffffff1680835262093a8091820291820111156108ad575b5061087661083561036a565b63ffffffff83511690602081015160020b61ffff6040830151169061ffff606060018060801b035f516020610ad55f395f51905f5254169401511693610997565b6001600160a01b03166040830152505b60400151905191516001600160a01b03908116928116918116919091038116919091031690565b62093a7f0163ffffffff1681525f610829565b9150505f525f516020610af55f395f51905f5260205260018060a01b0360405f205460501c166040820152610886565b5050925191516001600160a01b039081169281169290920390911692915050565b5f516020610b155f395f51905f525460a01c60020b6107cd565b5f9081525f516020610af55f395f51905f52602052604081205460501c6001600160a01b0316875261077e565b9050155f610778565b5f8481525f516020610af55f395f51905f52602052604090205460501c6001600160a01b0316895261074e565b9050155f610748565b92919094935061ffff81101561063c576109d2907ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280901610650565b9363ffffffff85511663ffffffff841603610a04575b505050602082015160060b91604060018060a01b039101511690565b5f949192939450610a13610ab4565b508151602083015160409093015163ffffffff91821686039460069490940b936001600160a01b03909116906001600160801b03811615610aab57905b6001600160a01b0391610a71906001600160801b031687851660801b61068f565b01169381610a7d6102f5565b961686521660060b9060020b0260060b0160060b6020830152604082015260016060820152905f80806109e8565b50600190610a50565b610abc6102f5565b905f82525f60208301525f60408301525f606083015256fef047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2805f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2808f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800a2646970667358221220e41104ddddff2e487a115e1b57d6d08ef9fdd8c09ef19d0f7b6fe043c17bd8f264736f6c634300081c0033
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80639b7beb601461024f578063c51185d81461009f5763feb0d7171461003a575f80fd5b608036600319011261009b5760043563ffffffff8116810361009b5761005e6102b5565b906044358060020b810361009b576064359063ffffffff8216820361009b57602093610089936106c2565b6040516001600160a01b039091168152f35b5f80fd5b307f000000000000000000000000739cb2b30fc47c19262ab023eae966a15c2f9a281461009b57606036600319011261009b5760043560243561ffff8116810361009b576100f66100f0828461062c565b50610650565b805160408201515f516020610ad55f395f51905f525460443563ffffffff90811662093a800281165f19018116969316860393916101d4916001600160a01b0391909116906001600160801b0316801561024657905b6001600160a01b0391610175906001600160801b0316608088901b63ffffffff60801b1661068f565b011694602083015160060b60605f516020610b155f395f51905f525460a01c60020b9401511515936101a56102f5565b98895263ffffffff60208a01971660060b0260060b0160060b855260408701938685526060880193845261062c565b939093610233579451945191519051602092831b6affffffffffffff000000001663ffffffff969096169590951760589190911b600160581b600160f81b03161793151560f81b6001600160f81b031916939093179055604051908152f35b634e487b7160e01b5f525f60045260245ffd5b5060019061014c565b606036600319011261009b576004358060020b810361009b576102706102b5565b6044359163ffffffff8316830361009b5760609263ffffffff926102939261041f565b906040939293519360060b845260018060a01b03166020840152166040820152f35b602435908160020b820361009b57565b60020b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280660205260405f2090565b604051906080820182811067ffffffffffffffff82111761031557604052565b634e487b7160e01b5f52604160045260245ffd5b6040519060c0820182811067ffffffffffffffff821117610315576040525f60a0838281528260208201528260408201528260608201528260808201520152565b6040519060e0820182811067ffffffffffffffff821117610315576040528160c060ff5f516020610b155f395f51905f525460018060a01b03811684528060a01c60020b602085015261ffff8160b81c16604085015261ffff8160c81c16606085015261ffff8160d81c166080850152818160e81c1660a085015260f01c161515910152565b604051906060820182811067ffffffffffffffff821117610315576040525f6040838281528260208201520152565b92909161042b846102c5565b93610435846102c5565b936003610440610329565b960154956040810195608082019763ffffffff8160d81c16895260018060a01b038160381c1688528060060b835260f81c1561009b5760030154936020820192606083019460a084019663ffffffff8160d81c16885260018060a01b038160381c1687528060060b865260f81c1561009b576104ba61036a565b906020820192835160020b9160020b82125f1461051e57505050505063ffffffff9392849283925160060b905160060b900360060b9660018060a01b0390511660018060a01b039160018060a01b0390511690031696511691511690031691929190565b939a94999496959360020b13156105e8576105376103f0565b9963ffffffff1691828b525160020b90604081015161ffff16600160801b600190035f516020610ad55f395f51905f525416916060015161ffff169261057c94610997565b6001600160a01b0390811660408b01819052600692830b60208c0181905299519351945195519a519651975194830b93830b909903820b92909203900b9781169281169096038616919091039094169363ffffffff908116928116918116919091038116919091031690565b50505195519151905193519251600692830b96830b9690960390910b95506001600160a01b03928316908316039091169263ffffffff908116918116919091031690565b61ffff82101561063c5701905f90565b634e487b7160e01b5f52603260045260245ffd5b906106596102f5565b915463ffffffff81168352602081811c60060b90840152605881901c6001600160a01b0316604084015260f81c15156060830152565b6001600160a01b039091169081156106ae576001600160a01b03160490565b634e487b7160e01b5f52601260045260245ffd5b929091926106cf836102c5565b916106d9856102c5565b9263ffffffff6106e7610329565b93165f8181525f516020610af55f395f51905f5260209081526040808320546004958601835292819020546001600160a01b031690870181815298600290810b989284901c900b96939463ffffffff9093169392919087891315908161098e575b50610961575b845f5201602052606060018060a01b0360405f20541691019781895260020b948513159081610958575b5061092b575b507ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2809549281841194855f1461091157825f525f516020610af55f395f51905f5260205260405f205460381c60020b5b60020b908112156107fb575050935194516001600160a01b0390811695811695909503909416949350505050565b12156108f0576108096103f0565b936108c0575063ffffffff1680835262093a8091820291820111156108ad575b5061087661083561036a565b63ffffffff83511690602081015160020b61ffff6040830151169061ffff606060018060801b035f516020610ad55f395f51905f5254169401511693610997565b6001600160a01b03166040830152505b60400151905191516001600160a01b03908116928116918116919091038116919091031690565b62093a7f0163ffffffff1681525f610829565b9150505f525f516020610af55f395f51905f5260205260018060a01b0360405f205460501c166040820152610886565b5050925191516001600160a01b039081169281169290920390911692915050565b5f516020610b155f395f51905f525460a01c60020b6107cd565b5f9081525f516020610af55f395f51905f52602052604081205460501c6001600160a01b0316875261077e565b9050155f610778565b5f8481525f516020610af55f395f51905f52602052604090205460501c6001600160a01b0316895261074e565b9050155f610748565b92919094935061ffff81101561063c576109d2907ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280901610650565b9363ffffffff85511663ffffffff841603610a04575b505050602082015160060b91604060018060a01b039101511690565b5f949192939450610a13610ab4565b508151602083015160409093015163ffffffff91821686039460069490940b936001600160a01b03909116906001600160801b03811615610aab57905b6001600160a01b0391610a71906001600160801b031687851660801b61068f565b01169381610a7d6102f5565b961686521660060b9060020b0260060b0160060b6020830152604082015260016060820152905f80806109e8565b50600190610a50565b610abc6102f5565b905f82525f60208301525f60408301525f606083015256fef047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2805f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2808f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800a2646970667358221220e41104ddddff2e487a115e1b57d6d08ef9fdd8c09ef19d0f7b6fe043c17bd8f264736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.