Contract
0xCbE0Ac9a00A69aA28099091B2ceac5941EC43521
11
Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Contract Name:
UnipilotStrategy
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 10 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity =0.7.6; pragma abicoder v2; import "./interfaces/IUnipilotStrategy.sol"; import "./base/oracle/libraries/OracleLibrary.sol"; import "@uniswap/v3-core/contracts/libraries/TickMath.sol"; import "@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol"; /** * * @notice * This contract calculates suitable tick ranges to fully deposit liquidity asset. * It maintains two strategies for unipilot vaults * 1) Base order => For depositing in-range liquidity * 2) Range order => To distribute remaining assets behind or ahead of base order ticks, * so that users liquidity does not abruptly goes out of range * @dev These ranges are named as follows. * Base => upper and lower ticks for main range to deposit * Ask => Upper and lower ticks ahead of the current tick and base upper * Bid => Upper and lower ticks behind the current and base lower **/ contract UnipilotStrategy is IUnipilotStrategy { /// @dev governance address is set on deployment for the governance based functions address public governance; /// @dev rangeTicks is multiplied with tick spacing to calculate range order spread int24 public rangeTicks; /// @dev baseTicks is multiplied with tick spacing to calculate base order spread int24 public baseTicks; /// @dev rangeOrder is the range calculate the spread behind and ahead of the base range int24 private rangeOrder; /// @dev baseMultiplier multiplier for base position for active pools int24 public baseMultiplier; /// @dev readjustMultiplier is the percentage multiplier of raedjust threshold int24 private readjustMultiplier; /// @dev maxTwapDeviation is the max time weighted average deviation of price from the normal range in both directions int24 public override maxTwapDeviation; /// @dev twapDuration is the minimum duration in which the diviated price moves uint32 public override twapDuration; constructor(address _governance) { governance = _governance; maxTwapDeviation = 300; twapDuration = 3600; rangeTicks = 1800; baseTicks = 1800; readjustMultiplier = 10; baseMultiplier = 30; } /// @dev poolStrategy maintains the base,range multipliers and /// twap variations for each pool mapping(address => PoolStrategy) internal poolStrategy; mapping(address => mapping(uint16 => int24)) internal activePoolStrategy; modifier onlyGovernance() { require(msg.sender == governance, "NG"); _; } function setGovernance(address _governance) external onlyGovernance { require(_governance != address(0), "IGA"); emit GovernanceUpdated(governance, _governance); governance = _governance; } /** * @notice This function returns base,ask and bid range ticks for the given pool * - It fetches the current tick and tick spacing of the pool * - Multiples the tick spacing with pools base and range multipliers * - Calculates pools twap and verifies whether it is under the maxtwapdeviation * - If the price is under the deviation limit, it returns the base ranges along with range order ticks * @param _pool: pool address **/ function getTicks(address _pool) external override returns ( int24 baseLower, int24 baseUpper, int24 bidLower, int24 bidUpper, int24 askLower, int24 askUpper ) { (int24 tick, int24 tickSpacing) = getCurrentTick(_pool); if ( poolStrategy[_pool].baseThreshold == 0 || poolStrategy[_pool].rangeThreshold == 0 ) { int24 baseFloor = _floor(baseTicks, tickSpacing); poolStrategy[_pool] = PoolStrategy({ baseThreshold: baseFloor, rangeThreshold: _floor(rangeTicks, tickSpacing), maxTwapDeviation: maxTwapDeviation, readjustThreshold: (baseFloor * readjustMultiplier) / 100, twapDuration: twapDuration, baseMultiplier: baseMultiplier }); } rangeOrder = poolStrategy[_pool].rangeThreshold; int24 maxThreshold = poolStrategy[_pool].baseThreshold > rangeOrder ? poolStrategy[_pool].baseThreshold : rangeOrder; require( (tick > TickMath.MIN_TICK + maxThreshold + tickSpacing) && (tick < (TickMath.MAX_TICK - maxThreshold - tickSpacing)), "IT" ); int24 twap = calculateTwap(_pool); int24 deviation = tick > twap ? tick - twap : twap - tick; require(deviation <= poolStrategy[_pool].maxTwapDeviation, "MTF"); int24 tickFloor = _floor(tick, tickSpacing); int24 tickCeil = tickFloor + tickSpacing; baseLower = tickFloor - poolStrategy[_pool].baseThreshold; baseUpper = tickFloor + poolStrategy[_pool].baseThreshold; bidLower = tickFloor - rangeOrder; bidUpper = tickFloor; askLower = tickCeil; askUpper = tickCeil + rangeOrder; } /** * @notice This function sets the global multipier value of the range order * @param _rangeTicks: a multiplier value to decide the spread of range order **/ function setRangeTicks(int24 _rangeTicks) external onlyGovernance { require(_rangeTicks > 0, "IRM"); emit RangeTicksUpdated(rangeTicks, _rangeTicks); rangeTicks = _rangeTicks; } /** * @notice This function updates the base range mutiplier * @param _baseMultiplier: a mutiplier value to decide the spread of base range **/ function setBaseTicks( address[] memory _pools, uint16[] memory _strategyType, int24[] memory _baseMultiplier ) external onlyGovernance { require(_pools.length == _baseMultiplier.length); require(_pools.length == _strategyType.length); for (uint256 i = 0; i < _pools.length; i++) { activePoolStrategy[_pools[i]][_strategyType[i]] = _baseMultiplier[ i ]; } } /** * @notice This function updates the deviation limit of tick spread * @param _twapDeviation: a value to decide the maximum price deviation **/ function setMaxTwapDeviation(int24 _twapDeviation) external onlyGovernance { require(_twapDeviation >= 20, "PF"); emit MaxTwapDeviationUpdated( maxTwapDeviation, maxTwapDeviation = _twapDeviation ); } /** * @notice This function updates the twap duration * @param _twapDuration: a value for the duration of recalbiration of the twap **/ function setTwapDuration(uint32 _twapDuration) external onlyGovernance { require(_twapDuration >= 100, "TD"); emit TwapDurationUpdated(twapDuration, twapDuration = _twapDuration); } function setReadjustMultiplier(int24 _readjustMultipier) external onlyGovernance { require(_readjustMultipier > 0, "IREM"); emit ReadjustMultiplierUpdated( readjustMultiplier, readjustMultiplier = _readjustMultipier ); } /** * @notice This function updates the range,base threshold and twap values specific to a pool * @param params: struct values of PoolStrategy struct, the values can be inspected from interface * @param _pool<: pool address **/ function changeStrategy(PoolStrategy memory params, address _pool) public onlyGovernance { PoolStrategy memory oldStrategy = poolStrategy[_pool]; validateStrategy( params.baseThreshold, IAlgebraPool(_pool).tickSpacing() ); emit StrategyUpdated( oldStrategy, poolStrategy[_pool] = PoolStrategy({ baseThreshold: params.baseThreshold, rangeThreshold: params.rangeThreshold, maxTwapDeviation: params.maxTwapDeviation, readjustThreshold: params.readjustThreshold, twapDuration: params.twapDuration, baseMultiplier: params.baseMultiplier }) ); } function setAllStrategies( PoolStrategy[] memory params, address[] memory pools ) external onlyGovernance { require(params.length == pools.length, "IVI"); for (uint256 i = 0; i < params.length; i++) { changeStrategy(params[i], pools[i]); } } /** * @notice This function updates the twapDeviation value of pools iteratively * @param _pools: pools addresses * @param _twapDeviations: devaiation values **/ function setPoolTwapDeviation( address[] memory _pools, int24[] memory _twapDeviations ) external onlyGovernance { require(_pools.length == _twapDeviations.length, "IVI"); for (uint256 i; i < _pools.length; i++) { poolStrategy[_pools[i]].maxTwapDeviation = _twapDeviations[i]; } } function checkDeviation(address pool) external view override { int24 twap = calculateTwap(pool); (int24 tick, ) = getCurrentTick(pool); int24 deviation = tick > twap ? tick - twap : twap - tick; require(deviation <= poolStrategy[pool].maxTwapDeviation, "MTF"); } function getStrategy(address _pool) external view override returns (PoolStrategy memory strategy) { strategy = poolStrategy[_pool]; } /** * @notice This function returns the readjust threshold of a pool * @param _pool: pool address **/ function getReadjustThreshold(address _pool) public view returns (int24 readjustThreshold) { readjustThreshold = poolStrategy[_pool].readjustThreshold; return readjustThreshold; } function getBaseThreshold(address _pool, uint16 _strategyType) external view override returns (int24 baseThreshold) { baseThreshold = activePoolStrategy[_pool][_strategyType]; } /** * @notice This function calculates the current twap of pool * @param pool: pool address **/ function calculateTwap(address pool) internal view returns (int24 twap) { uint128 inRangeLiquidity = IAlgebraPool(pool).liquidity(); if (inRangeLiquidity == 0) { (uint160 sqrtPriceX96, , , , , , ) = IAlgebraPool(pool) .globalState(); twap = TickMath.getTickAtSqrtRatio(sqrtPriceX96); } else { twap = getTwap(pool); } } /** * @notice This function fetches the twap of pool from the observation * @param _pool: pool address **/ function getTwap(address _pool) public view override returns (int24 twap) { IAlgebraPool uniswapV3Pool = IAlgebraPool(_pool); (, , , uint16 observationIndex, , , ) = uniswapV3Pool.globalState(); uint16 oldestIndex; // check if we have overflow in the past uint16 nextIndex = observationIndex + 1; // considering overflow (bool initialized, , , , , , ) = uniswapV3Pool.timepoints(nextIndex); if (initialized) { oldestIndex = nextIndex; } (, uint32 lastTimeStamp, , , , , ) = uniswapV3Pool.timepoints( oldestIndex ); uint32 timeDiff = uint32(block.timestamp) - lastTimeStamp; uint32 duration = poolStrategy[_pool].twapDuration; if (duration == 0) { duration = twapDuration; } twap = OracleLibrary.consult( _pool, timeDiff > duration ? duration : timeDiff ); } /** * @notice This function calculates the lower tick value from the current tick * @param tick: current tick of the pool * @param tickSpacing: tick spacing according to the fee tier **/ function _floor(int24 tick, int24 tickSpacing) internal pure returns (int24) { int24 compressed = tick / tickSpacing; if (tick < 0 && tick % tickSpacing != 0) compressed--; return compressed * tickSpacing; } /** * @notice This function fetches the current tick of the pool * @param pool: pool address **/ function getCurrentTick(address pool) internal view returns (int24 tick, int24 tickSpacing) { (, tick, , , , , ) = IAlgebraPoolState(pool).globalState(); tickSpacing = IAlgebraPool(pool).tickSpacing(); } /** * @notice This function validates that the updating strategy of the pool during the update * @param _strategy: a value for baseThreshold * @param _tickSpacing: spacing of tick according to fee tier **/ function validateStrategy(int24 _strategy, int24 _tickSpacing) internal pure { require( _strategy <= TickMath.MAX_TICK && _strategy % _tickSpacing == 0 && _strategy > 0, "INS" ); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.6; pragma abicoder v2; interface IUnipilotStrategy { struct PoolStrategy { int24 baseThreshold; int24 rangeThreshold; int24 maxTwapDeviation; int24 readjustThreshold; uint32 twapDuration; int24 baseMultiplier; } event GovernanceUpdated(address oldGovernance, address newGovernance); event StrategyUpdated(PoolStrategy oldStrategy, PoolStrategy newStrategy); event MaxTwapDeviationUpdated(int24 oldDeviation, int24 newDeviation); event BaseTicksUpdated(int24 oldBaseTicks, int24 newBaseTicks); event RangeTicksUpdated(int24 oldRangeTicks, int24 newRangeTicks); event TwapDurationUpdated(uint32 oldDuration, uint32 newDuration); event ReadjustMultiplierUpdated(int24 oldMultiplier, int24 newMultiplier); function getTicks(address _pool) external returns ( int24 baseLower, int24 baseUpper, int24 bidLower, int24 bidUpper, int24 askLower, int24 askUpper ); function getTwap(address _pool) external view returns (int24); function getStrategy(address _pool) external view returns (PoolStrategy memory strategy); function getBaseThreshold(address _pool, uint16 _strategyType) external view returns (int24 baseThreshold); function twapDuration() external view returns (uint32); function maxTwapDeviation() external view returns (int24); function checkDeviation(address pool) external view; }
// SPDX-License-Identifier: MIT pragma solidity =0.7.6; import "@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol"; import "@uniswap/v3-core/contracts/libraries/FullMath.sol"; import "@uniswap/v3-core/contracts/libraries/TickMath.sol"; library OracleLibrary { /// @notice Fetches time-weighted average tick using Uniswap V3 oracle /// @param pool Address of Uniswap V3 pool that we want to observe /// @param period Number of seconds in the past to start calculating time-weighted average /// @return timeWeightedAverageTick The time-weighted average tick from (block.timestamp - period) to block.timestamp function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) { require(period != 0, "BP"); uint32[] memory secondAgos = new uint32[](2); secondAgos[0] = period; secondAgos[1] = 0; (int56[] memory tickCumulatives, , , ) = IAlgebraPool(pool) .getTimepoints(secondAgos); int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0]; timeWeightedAverageTick = int24(tickCumulativesDelta / period); // Always round to negative infinity if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--; } /// @notice Given a tick and a token amount, calculates the amount of token received in exchange /// @param tick Tick value used to calculate the quote /// @param baseAmount Amount of token to be converted /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken function getQuoteAtTick( int24 tick, uint128 baseAmount, address baseToken, address quoteToken ) internal pure returns (uint256 quoteAmount) { uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick); // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself if (sqrtRatioX96 <= type(uint128).max) { uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96; quoteAmount = baseToken < quoteToken ? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192) : FullMath.mulDiv(1 << 192, baseAmount, ratioX192); } else { uint256 ratioX128 = FullMath.mulDiv( sqrtRatioX96, sqrtRatioX96, 1 << 64 ); quoteAmount = baseToken < quoteToken ? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128) : FullMath.mulDiv(1 << 128, baseAmount, ratioX128); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) /// at the given tick function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); require(absTick <= uint256(MAX_TICK), 'T'); uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; if (tick > 0) ratio = type(uint256).max / ratio; // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtRatio of the output price is always consistent sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R'); uint256 ratio = uint256(sqrtPriceX96) << 32; uint256 r = ratio; uint256 msb = 0; assembly { let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(5, gt(r, 0xFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(4, gt(r, 0xFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(3, gt(r, 0xFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(2, gt(r, 0xF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(1, gt(r, 0x3)) msb := or(msb, f) r := shr(f, r) } assembly { let f := gt(r, 0x1) msb := or(msb, f) } if (msb >= 128) r = ratio >> (msb - 127); else r = ratio << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import './pool/IAlgebraPoolImmutables.sol'; import './pool/IAlgebraPoolState.sol'; import './pool/IAlgebraPoolDerivedState.sol'; import './pool/IAlgebraPoolActions.sol'; import './pool/IAlgebraPoolPermissionedActions.sol'; import './pool/IAlgebraPoolEvents.sol'; /** * @title The interface for a Algebra Pool * @dev The pool interface is broken up into many smaller pieces. * Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPool is IAlgebraPoolImmutables, IAlgebraPoolState, IAlgebraPoolDerivedState, IAlgebraPoolActions, IAlgebraPoolPermissionedActions, IAlgebraPoolEvents { // used only for combining interfaces }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = -denominator & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import '../IDataStorageOperator.sol'; /// @title Pool state that never changes /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolImmutables { /** * @notice The contract that stores all the timepoints and can perform actions with them * @return The operator address */ function dataStorageOperator() external view returns (address); /** * @notice The contract that deployed the pool, which must adhere to the IAlgebraFactory interface * @return The contract address */ function factory() external view returns (address); /** * @notice The first of the two tokens of the pool, sorted by address * @return The token contract address */ function token0() external view returns (address); /** * @notice The second of the two tokens of the pool, sorted by address * @return The token contract address */ function token1() external view returns (address); /** * @notice The pool tick spacing * @dev Ticks can only be used at multiples of this value * e.g.: a tickSpacing of 60 means ticks can be initialized every 60th tick, i.e., ..., -120, -60, 0, 60, 120, ... * This value is an int24 to avoid casting even though it is always positive. * @return The tick spacing */ function tickSpacing() external view returns (int24); /** * @notice The maximum amount of position liquidity that can use any tick in the range * @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and * 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 maxLiquidityPerTick() external view returns (uint128); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that can change /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolState { /** * @notice The globalState structure in the pool stores many values but requires only one slot * and is exposed as a single method to save gas when accessed externally. * @return price The current price of the pool as a sqrt(token1/token0) Q64.96 value; * Returns tick The current tick of the pool, i.e. according to the last tick transition that was run; * Returns This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick * boundary; * Returns fee The last pool fee value in hundredths of a bip, i.e. 1e-6; * Returns timepointIndex The index of the last written timepoint; * Returns communityFeeToken0 The community fee percentage of the swap fee in thousandths (1e-3) for token0; * Returns communityFeeToken1 The community fee percentage of the swap fee in thousandths (1e-3) for token1; * Returns unlocked Whether the pool is currently locked to reentrancy; */ function globalState() external view returns ( uint160 price, int24 tick, uint16 fee, uint16 timepointIndex, uint8 communityFeeToken0, uint8 communityFeeToken1, bool unlocked ); /** * @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool * @dev This value can overflow the uint256 */ function totalFeeGrowth0Token() external view returns (uint256); /** * @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool * @dev This value can overflow the uint256 */ function totalFeeGrowth1Token() external view returns (uint256); /** * @notice The currently in range liquidity available to the pool * @dev This value has no relationship to the total liquidity across all ticks. * Returned value cannot exceed type(uint128).max */ function liquidity() external view returns (uint128); /** * @notice Look up information about a specific tick in the pool * @dev This is a public structure, so the `return` natspec tags are omitted. * @param tick The tick to look up * @return liquidityTotal the total amount of position liquidity that uses the pool either as tick lower or * tick upper; * Returns liquidityDelta how much liquidity changes when the pool price crosses the tick; * Returns outerFeeGrowth0Token the fee growth on the other side of the tick from the current tick in token0; * Returns outerFeeGrowth1Token the fee growth on the other side of the tick from the current tick in token1; * Returns outerTickCumulative the cumulative tick value on the other side of the tick from the current tick; * Returns outerSecondsPerLiquidity the seconds spent per liquidity on the other side of the tick from the current tick; * Returns outerSecondsSpent the seconds spent on the other side of the tick from the current tick; * Returns initialized Set to true if the tick is initialized, i.e. liquidityTotal is greater than 0 * otherwise equal to false. Outside values can only be used if the tick is initialized. * In addition, these values are only relative and must be used only in comparison to previous snapshots for * a specific position. */ function ticks(int24 tick) external view returns ( uint128 liquidityTotal, int128 liquidityDelta, uint256 outerFeeGrowth0Token, uint256 outerFeeGrowth1Token, int56 outerTickCumulative, uint160 outerSecondsPerLiquidity, uint32 outerSecondsSpent, bool initialized ); /** @notice Returns 256 packed tick initialized boolean values. See TickTable for more information */ function tickTable(int16 wordPosition) external view returns (uint256); /** * @notice Returns the information about a position by the position's key * @dev This is a public mapping of structures, so the `return` natspec tags are omitted. * @param key The position's key is a hash of a preimage composed by the owner, bottomTick and topTick * @return liquidityAmount The amount of liquidity in the position; * Returns lastLiquidityAddTimestamp Timestamp of last adding of liquidity; * Returns innerFeeGrowth0Token Fee growth of token0 inside the tick range as of the last mint/burn/poke; * Returns innerFeeGrowth1Token Fee growth of token1 inside the tick range as of the last mint/burn/poke; * Returns fees0 The computed amount of token0 owed to the position as of the last mint/burn/poke; * Returns fees1 The computed amount of token1 owed to the position as of the last mint/burn/poke */ function positions(bytes32 key) external view returns ( uint128 liquidityAmount, uint32 lastLiquidityAddTimestamp, uint256 innerFeeGrowth0Token, uint256 innerFeeGrowth1Token, uint128 fees0, uint128 fees1 ); /** * @notice Returns data about a specific timepoint index * @param index The element of the timepoints array to fetch * @dev You most likely want to use #getTimepoints() instead of this method to get an timepoint as of some amount of time * ago, rather than at a specific index in the array. * This is a public mapping of structures, so the `return` natspec tags are omitted. * @return initialized whether the timepoint has been initialized and the values are safe to use; * Returns blockTimestamp The timestamp of the timepoint; * Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp; * Returns secondsPerLiquidityCumulative the seconds per in range liquidity for the life of the pool as of the timepoint timestamp; * Returns volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp; * Returns averageTick Time-weighted average tick; * Returns volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp; */ function timepoints(uint256 index) external view returns ( bool initialized, uint32 blockTimestamp, int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint88 volatilityCumulative, int24 averageTick, uint144 volumePerLiquidityCumulative ); /** * @notice Returns the information about active incentive * @dev if there is no active incentive at the moment, virtualPool,endTimestamp,startTimestamp would be equal to 0 * @return virtualPool The address of a virtual pool associated with the current active incentive */ function activeIncentive() external view returns (address virtualPool); /** * @notice Returns the lock time for added liquidity */ function liquidityCooldown() external view returns (uint32 cooldownInSeconds); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title Pool state that is not stored * @notice Contains view functions to provide information about the pool that is computed rather than stored on the * blockchain. The functions here may have variable gas costs. * @dev Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPoolDerivedState { /** * @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp * @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing * the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, * you must call it with secondsAgos = [3600, 0]. * @dev The time weighted average tick represents the geometric time weighted average price of the pool, in * log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. * @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned * @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp * @return secondsPerLiquidityCumulatives Cumulative seconds per liquidity-in-range value as of each `secondsAgos` * from the current block timestamp * @return volatilityCumulatives Cumulative standard deviation as of each `secondsAgos` * @return volumePerAvgLiquiditys Cumulative swap volume per liquidity as of each `secondsAgos` */ function getTimepoints(uint32[] calldata secondsAgos) external view returns ( int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulatives, uint112[] memory volatilityCumulatives, uint256[] memory volumePerAvgLiquiditys ); /** * @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. * @param bottomTick The lower tick of the range * @param topTick The upper tick of the range * @return innerTickCumulative The snapshot of the tick accumulator for the range * @return innerSecondsSpentPerLiquidity The snapshot of seconds per liquidity for the range * @return innerSecondsSpent The snapshot of the number of seconds during which the price was in this range */ function getInnerCumulatives(int24 bottomTick, int24 topTick) external view returns ( int56 innerTickCumulative, uint160 innerSecondsSpentPerLiquidity, uint32 innerSecondsSpent ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissionless pool actions /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolActions { /** * @notice Sets the initial price for the pool * @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value * @param price the initial sqrt price of the pool as a Q64.96 */ function initialize(uint160 price) external; /** * @notice Adds liquidity for the given recipient/bottomTick/topTick position * @dev The caller of this method receives a callback in the form of IAlgebraMintCallback# AlgebraMintCallback * in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends * on bottomTick, topTick, the amount of liquidity, and the current price. * @param sender The address which will receive potential surplus of paid tokens * @param recipient The address for which the liquidity will be created * @param bottomTick The lower tick of the position in which to add liquidity * @param topTick The upper tick of the position in which to add liquidity * @param amount The desired amount of liquidity to mint * @param data Any data that should be passed through to the callback * @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback * @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback * @return liquidityActual The actual minted amount of liquidity */ function mint( address sender, address recipient, int24 bottomTick, int24 topTick, uint128 amount, bytes calldata data ) external returns ( uint256 amount0, uint256 amount1, uint128 liquidityActual ); /** * @notice Collects tokens owed to a position * @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. * Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or * amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the * actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. * @param recipient The address which should receive the fees collected * @param bottomTick The lower tick of the position for which to collect fees * @param topTick The upper tick of the position for which to collect fees * @param amount0Requested How much token0 should be withdrawn from the fees owed * @param amount1Requested How much token1 should be withdrawn from the fees owed * @return amount0 The amount of fees collected in token0 * @return amount1 The amount of fees collected in token1 */ function collect( address recipient, int24 bottomTick, int24 topTick, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); /** * @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position * @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 * @dev Fees must be collected separately via a call to #collect * @param bottomTick The lower tick of the position for which to burn liquidity * @param topTick The upper tick of the position for which to burn liquidity * @param amount How much liquidity to burn * @return amount0 The amount of token0 sent to the recipient * @return amount1 The amount of token1 sent to the recipient */ function burn( int24 bottomTick, int24 topTick, uint128 amount ) external returns (uint256 amount0, uint256 amount1); /** * @notice Swap token0 for token1, or token1 for token0 * @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback# AlgebraSwapCallback * @param recipient The address to receive the output of the swap * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this * value after the swap. If one for zero, the price cannot be greater than this value after the swap * @param data Any data to be passed through to the callback. If using the Router it should contain * SwapRouter#SwapCallbackData * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive */ function swap( address recipient, bool zeroToOne, int256 amountSpecified, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /** * @notice Swap token0 for token1, or token1 for token0 (tokens that have fee on transfer) * @dev The caller of this method receives a callback in the form of I AlgebraSwapCallback# AlgebraSwapCallback * @param sender The address called this function (Comes from the Router) * @param recipient The address to receive the output of the swap * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this * value after the swap. If one for zero, the price cannot be greater than this value after the swap * @param data Any data to be passed through to the callback. If using the Router it should contain * SwapRouter#SwapCallbackData * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive */ function swapSupportingFeeOnInputTokens( address sender, address recipient, bool zeroToOne, int256 amountSpecified, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /** * @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 IAlgebraFlashCallback# AlgebraFlashCallback * @dev All excess tokens paid in the callback are distributed to liquidity providers as an additional fee. So this method can be used * to donate underlying tokens to currently in-range liquidity providers by calling with 0 amount{0,1} and sending * the donation amount(s) from the callback * @param recipient The address which will receive the token0 and token1 amounts * @param amount0 The amount of token0 to send * @param amount1 The amount of token1 to send * @param data Any data to be passed through to the callback */ function flash( address recipient, uint256 amount0, uint256 amount1, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title Permissioned pool actions * @notice Contains pool methods that may only be called by the factory owner or tokenomics * @dev Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPoolPermissionedActions { /** * @notice Set the community's % share of the fees. Cannot exceed 25% (250) * @param communityFee0 new community fee percent for token0 of the pool in thousandths (1e-3) * @param communityFee1 new community fee percent for token1 of the pool in thousandths (1e-3) */ function setCommunityFee(uint8 communityFee0, uint8 communityFee1) external; /** * @notice Sets an active incentive * @param virtualPoolAddress The address of a virtual pool associated with the incentive */ function setIncentive(address virtualPoolAddress) external; /** * @notice Sets new lock time for added liquidity * @param newLiquidityCooldown The time in seconds */ function setLiquidityCooldown(uint32 newLiquidityCooldown) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Events emitted by a pool /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolEvents { /** * @notice Emitted exactly once by a pool when #initialize is first called on the pool * @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize * @param price The initial sqrt price of the pool, as a Q64.96 * @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool */ event Initialize(uint160 price, int24 tick); /** * @notice Emitted when liquidity is minted for a given position * @param sender The address that minted the liquidity * @param owner The owner of the position and recipient of any minted liquidity * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param liquidityAmount The amount of liquidity minted to the position range * @param amount0 How much token0 was required for the minted liquidity * @param amount1 How much token1 was required for the minted liquidity */ event Mint( address sender, address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1 ); /** * @notice Emitted when fees are collected by the owner of a position * @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees * @param owner The owner of the position for which fees are collected * @param recipient The address that received fees * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param amount0 The amount of token0 fees collected * @param amount1 The amount of token1 fees collected */ event Collect(address indexed owner, address recipient, int24 indexed bottomTick, int24 indexed topTick, uint128 amount0, uint128 amount1); /** * @notice Emitted when a position's liquidity is removed * @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect * @param owner The owner of the position for which liquidity is removed * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param liquidityAmount The amount of liquidity to remove * @param amount0 The amount of token0 withdrawn * @param amount1 The amount of token1 withdrawn */ event Burn(address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1); /** * @notice Emitted by the pool for any swaps between token0 and token1 * @param sender The address that initiated the swap call, and that received the callback * @param recipient The address that received the output of the swap * @param amount0 The delta of the token0 balance of the pool * @param amount1 The delta of the token1 balance of the pool * @param price The sqrt(price) of the pool after the swap, as a Q64.96 * @param liquidity The liquidity of the pool after the swap * @param tick The log base 1.0001 of price of the pool after the swap */ event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 price, uint128 liquidity, int24 tick); /** * @notice Emitted by the pool for any flashes of token0/token1 * @param sender The address that initiated the swap call, and that received the callback * @param recipient The address that received the tokens from flash * @param amount0 The amount of token0 that was flashed * @param amount1 The amount of token1 that was flashed * @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee * @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee */ event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1); /** * @notice Emitted when the community fee is changed by the pool * @param communityFee0New The updated value of the token0 community fee percent * @param communityFee1New The updated value of the token1 community fee percent */ event CommunityFee(uint8 communityFee0New, uint8 communityFee1New); /** * @notice Emitted when new activeIncentive is set * @param virtualPoolAddress The address of a virtual pool associated with the current active incentive */ event Incentive(address indexed virtualPoolAddress); /** * @notice Emitted when the fee changes * @param fee The value of the token fee */ event Fee(uint16 fee); /** * @notice Emitted when the LiquidityCooldown changes * @param liquidityCooldown The value of locktime for added liquidity */ event LiquidityCooldown(uint32 liquidityCooldown); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; pragma abicoder v2; import '../libraries/AdaptiveFee.sol'; interface IDataStorageOperator { event FeeConfiguration(AdaptiveFee.Configuration feeConfig); /** * @notice Returns data belonging to a certain timepoint * @param index The index of timepoint in the array * @dev There is more convenient function to fetch a timepoint: observe(). Which requires not an index but seconds * @return initialized Whether the timepoint has been initialized and the values are safe to use, * blockTimestamp The timestamp of the observation, * tickCumulative The tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp, * secondsPerLiquidityCumulative The seconds per in range liquidity for the life of the pool as of the timepoint timestamp, * volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp, * averageTick Time-weighted average tick, * volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp */ function timepoints(uint256 index) external view returns ( bool initialized, uint32 blockTimestamp, int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint88 volatilityCumulative, int24 averageTick, uint144 volumePerLiquidityCumulative ); /// @notice Initialize the dataStorage array by writing the first slot. Called once for the lifecycle of the timepoints array /// @param time The time of the dataStorage initialization, via block.timestamp truncated to uint32 /// @param tick Initial tick function initialize(uint32 time, int24 tick) external; /// @dev Reverts if an timepoint at or before the desired timepoint timestamp does not exist. /// 0 may be passed as `secondsAgo' to return the current cumulative values. /// If called with a timestamp falling between two timepoints, returns the counterfactual accumulator values /// at exactly the timestamp between the two timepoints. /// @param time The current block timestamp /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an timepoint /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return tickCumulative The cumulative tick since the pool was first initialized, as of `secondsAgo` /// @return secondsPerLiquidityCumulative The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of `secondsAgo` /// @return volatilityCumulative The cumulative volatility value since the pool was first initialized, as of `secondsAgo` /// @return volumePerAvgLiquidity The cumulative volume per liquidity value since the pool was first initialized, as of `secondsAgo` function getSingleTimepoint( uint32 time, uint32 secondsAgo, int24 tick, uint16 index, uint128 liquidity ) external view returns ( int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint112 volatilityCumulative, uint256 volumePerAvgLiquidity ); /// @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 timepoint /// @param time The current block.timestamp /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an timepoint /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return tickCumulatives The cumulative tick since the pool was first initialized, as of each `secondsAgo` /// @return secondsPerLiquidityCumulatives The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of each `secondsAgo` /// @return volatilityCumulatives The cumulative volatility values since the pool was first initialized, as of each `secondsAgo` /// @return volumePerAvgLiquiditys The cumulative volume per liquidity values since the pool was first initialized, as of each `secondsAgo` function getTimepoints( uint32 time, uint32[] memory secondsAgos, int24 tick, uint16 index, uint128 liquidity ) external view returns ( int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulatives, uint112[] memory volatilityCumulatives, uint256[] memory volumePerAvgLiquiditys ); /// @notice Returns average volatility in the range from time-WINDOW to time /// @param time The current block.timestamp /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return TWVolatilityAverage The average volatility in the recent range /// @return TWVolumePerLiqAverage The average volume per liquidity in the recent range function getAverages( uint32 time, int24 tick, uint16 index, uint128 liquidity ) external view returns (uint112 TWVolatilityAverage, uint256 TWVolumePerLiqAverage); /// @notice Writes an dataStorage timepoint to the array /// @dev Writable at most once per block. Index represents the most recently written element. index must be tracked externally. /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param blockTimestamp The timestamp of the new timepoint /// @param tick The active tick at the time of the new timepoint /// @param liquidity The total in-range liquidity at the time of the new timepoint /// @param volumePerLiquidity The gmean(volumes)/liquidity at the time of the new timepoint /// @return indexUpdated The new index of the most recently written element in the dataStorage array function write( uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint128 volumePerLiquidity ) external returns (uint16 indexUpdated); /// @notice Changes fee configuration for the pool function changeFeeConfiguration(AdaptiveFee.Configuration calldata feeConfig) external; /// @notice Calculates gmean(volume/liquidity) for block /// @param liquidity The current in-range pool liquidity /// @param amount0 Total amount of swapped token0 /// @param amount1 Total amount of swapped token1 /// @return volumePerLiquidity gmean(volume/liquidity) capped by 100000 << 64 function calculateVolumePerLiquidity( uint128 liquidity, int256 amount0, int256 amount1 ) external pure returns (uint128 volumePerLiquidity); /// @return windowLength Length of window used to calculate averages function window() external view returns (uint32 windowLength); /// @notice Calculates fee based on combination of sigmoids /// @param time The current block.timestamp /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return fee The fee in hundredths of a bip, i.e. 1e-6 function getFee( uint32 time, int24 tick, uint16 index, uint128 liquidity ) external view returns (uint16 fee); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.7.6; import './Constants.sol'; /// @title AdaptiveFee /// @notice Calculates fee based on combination of sigmoids library AdaptiveFee { // alpha1 + alpha2 + baseFee must be <= type(uint16).max struct Configuration { uint16 alpha1; // max value of the first sigmoid uint16 alpha2; // max value of the second sigmoid uint32 beta1; // shift along the x-axis for the first sigmoid uint32 beta2; // shift along the x-axis for the second sigmoid uint16 gamma1; // horizontal stretch factor for the first sigmoid uint16 gamma2; // horizontal stretch factor for the second sigmoid uint32 volumeBeta; // shift along the x-axis for the outer volume-sigmoid uint16 volumeGamma; // horizontal stretch factor the outer volume-sigmoid uint16 baseFee; // minimum possible fee } /// @notice Calculates fee based on formula: /// baseFee + sigmoidVolume(sigmoid1(volatility, volumePerLiquidity) + sigmoid2(volatility, volumePerLiquidity)) /// maximum value capped by baseFee + alpha1 + alpha2 function getFee( uint88 volatility, uint256 volumePerLiquidity, Configuration memory config ) internal pure returns (uint16 fee) { uint256 sumOfSigmoids = sigmoid(volatility, config.gamma1, config.alpha1, config.beta1) + sigmoid(volatility, config.gamma2, config.alpha2, config.beta2); if (sumOfSigmoids > type(uint16).max) { // should be impossible, just in case sumOfSigmoids = type(uint16).max; } return uint16(config.baseFee + sigmoid(volumePerLiquidity, config.volumeGamma, uint16(sumOfSigmoids), config.volumeBeta)); // safe since alpha1 + alpha2 + baseFee _must_ be <= type(uint16).max } /// @notice calculates α / (1 + e^( (β-x) / γ)) /// that is a sigmoid with a maximum value of α, x-shifted by β, and stretched by γ /// @dev returns uint256 for fuzzy testing. Guaranteed that the result is not greater than alpha function sigmoid( uint256 x, uint16 g, uint16 alpha, uint256 beta ) internal pure returns (uint256 res) { if (x > beta) { x = x - beta; if (x >= 6 * uint256(g)) return alpha; // so x < 19 bits uint256 g8 = uint256(g)**8; // < 128 bits (8*16) uint256 ex = exp(x, g, g8); // < 155 bits res = (alpha * ex) / (g8 + ex); // in worst case: (16 + 155 bits) / 155 bits // so res <= alpha } else { x = beta - x; if (x >= 6 * uint256(g)) return 0; // so x < 19 bits uint256 g8 = uint256(g)**8; // < 128 bits (8*16) uint256 ex = g8 + exp(x, g, g8); // < 156 bits res = (alpha * g8) / ex; // in worst case: (16 + 128 bits) / 156 bits // g8 <= ex, so res <= alpha } } /// @notice calculates e^(x/g) * g^8 in a series, since (around zero): /// e^x = 1 + x + x^2/2 + ... + x^n/n! + ... /// e^(x/g) = 1 + x/g + x^2/(2*g^2) + ... + x^(n)/(g^n * n!) + ... function exp( uint256 x, uint16 g, uint256 gHighestDegree ) internal pure returns (uint256 res) { // calculating: // g**8 + x * g**7 + (x**2 * g**6) / 2 + (x**3 * g**5) / 6 + (x**4 * g**4) / 24 + (x**5 * g**3) / 120 + (x**6 * g^2) / 720 + x**7 * g / 5040 + x**8 / 40320 // x**8 < 152 bits (19*8) and g**8 < 128 bits (8*16) // so each summand < 152 bits and res < 155 bits uint256 xLowestDegree = x; res = gHighestDegree; // g**8 gHighestDegree /= g; // g**7 res += xLowestDegree * gHighestDegree; gHighestDegree /= g; // g**6 xLowestDegree *= x; // x**2 res += (xLowestDegree * gHighestDegree) / 2; gHighestDegree /= g; // g**5 xLowestDegree *= x; // x**3 res += (xLowestDegree * gHighestDegree) / 6; gHighestDegree /= g; // g**4 xLowestDegree *= x; // x**4 res += (xLowestDegree * gHighestDegree) / 24; gHighestDegree /= g; // g**3 xLowestDegree *= x; // x**5 res += (xLowestDegree * gHighestDegree) / 120; gHighestDegree /= g; // g**2 xLowestDegree *= x; // x**6 res += (xLowestDegree * gHighestDegree) / 720; xLowestDegree *= x; // x**7 res += (xLowestDegree * g) / 5040 + (xLowestDegree * x) / (40320); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; library Constants { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; uint256 internal constant Q128 = 0x100000000000000000000000000000000; // fee value in hundredths of a bip, i.e. 1e-6 uint16 internal constant BASE_FEE = 100; int24 internal constant TICK_SPACING = 60; // max(uint128) / ( (MAX_TICK - MIN_TICK) / TICK_SPACING ) uint128 internal constant MAX_LIQUIDITY_PER_TICK = 11505743598341114571880798222544994; uint32 internal constant MAX_LIQUIDITY_COOLDOWN = 1 days; uint8 internal constant MAX_COMMUNITY_FEE = 250; uint256 internal constant COMMUNITY_FEE_DENOMINATOR = 1000; }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 10 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"oldBaseTicks","type":"int24"},{"indexed":false,"internalType":"int24","name":"newBaseTicks","type":"int24"}],"name":"BaseTicksUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldGovernance","type":"address"},{"indexed":false,"internalType":"address","name":"newGovernance","type":"address"}],"name":"GovernanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"oldDeviation","type":"int24"},{"indexed":false,"internalType":"int24","name":"newDeviation","type":"int24"}],"name":"MaxTwapDeviationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"oldRangeTicks","type":"int24"},{"indexed":false,"internalType":"int24","name":"newRangeTicks","type":"int24"}],"name":"RangeTicksUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"oldMultiplier","type":"int24"},{"indexed":false,"internalType":"int24","name":"newMultiplier","type":"int24"}],"name":"ReadjustMultiplierUpdated","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"rangeThreshold","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"int24","name":"readjustThreshold","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"int24","name":"baseMultiplier","type":"int24"}],"indexed":false,"internalType":"struct IUnipilotStrategy.PoolStrategy","name":"oldStrategy","type":"tuple"},{"components":[{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"rangeThreshold","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"int24","name":"readjustThreshold","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"int24","name":"baseMultiplier","type":"int24"}],"indexed":false,"internalType":"struct IUnipilotStrategy.PoolStrategy","name":"newStrategy","type":"tuple"}],"name":"StrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"oldDuration","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newDuration","type":"uint32"}],"name":"TwapDurationUpdated","type":"event"},{"inputs":[],"name":"baseMultiplier","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTicks","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"rangeThreshold","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"int24","name":"readjustThreshold","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"int24","name":"baseMultiplier","type":"int24"}],"internalType":"struct IUnipilotStrategy.PoolStrategy","name":"params","type":"tuple"},{"internalType":"address","name":"_pool","type":"address"}],"name":"changeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"checkDeviation","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint16","name":"_strategyType","type":"uint16"}],"name":"getBaseThreshold","outputs":[{"internalType":"int24","name":"baseThreshold","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getReadjustThreshold","outputs":[{"internalType":"int24","name":"readjustThreshold","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getStrategy","outputs":[{"components":[{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"rangeThreshold","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"int24","name":"readjustThreshold","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"int24","name":"baseMultiplier","type":"int24"}],"internalType":"struct IUnipilotStrategy.PoolStrategy","name":"strategy","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getTicks","outputs":[{"internalType":"int24","name":"baseLower","type":"int24"},{"internalType":"int24","name":"baseUpper","type":"int24"},{"internalType":"int24","name":"bidLower","type":"int24"},{"internalType":"int24","name":"bidUpper","type":"int24"},{"internalType":"int24","name":"askLower","type":"int24"},{"internalType":"int24","name":"askUpper","type":"int24"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"getTwap","outputs":[{"internalType":"int24","name":"twap","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTwapDeviation","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rangeTicks","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"int24","name":"baseThreshold","type":"int24"},{"internalType":"int24","name":"rangeThreshold","type":"int24"},{"internalType":"int24","name":"maxTwapDeviation","type":"int24"},{"internalType":"int24","name":"readjustThreshold","type":"int24"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"int24","name":"baseMultiplier","type":"int24"}],"internalType":"struct IUnipilotStrategy.PoolStrategy[]","name":"params","type":"tuple[]"},{"internalType":"address[]","name":"pools","type":"address[]"}],"name":"setAllStrategies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"},{"internalType":"uint16[]","name":"_strategyType","type":"uint16[]"},{"internalType":"int24[]","name":"_baseMultiplier","type":"int24[]"}],"name":"setBaseTicks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_twapDeviation","type":"int24"}],"name":"setMaxTwapDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"},{"internalType":"int24[]","name":"_twapDeviations","type":"int24[]"}],"name":"setPoolTwapDeviation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_rangeTicks","type":"int24"}],"name":"setRangeTicks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_readjustMultipier","type":"int24"}],"name":"setReadjustMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_twapDuration","type":"uint32"}],"name":"setTwapDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162002a5e38038062002a5e8339810160408190526200003491620000bc565b6000805460018054600a65ffffff0000001990911664012c0000001763ffffffff60301b1916670e100000000000001762ffffff19161790556001600160a01b0319166001600160a01b03929092169190911762ffffff60a01b191660e160a31b1762ffffff60b81b191660e160bb1b176001600160e81b0316600f60e91b179055620000ec565b600060208284031215620000ce578081fd5b81516001600160a01b0381168114620000e5578182fd5b9392505050565b61296280620000fc6000396000f3fe608060405234801561001057600080fd5b50600436106101075760003560e01c8063051bb8331461010c5780631ca6aede1461012157806326d895451461013f5780633cbff3fe146101545780633d47d227146101675780634ed8cf271461017a57806357159a2e1461018d5780635aa6e675146101a0578063802036f5146101b55780638df2345e146101da578063963f0bb6146101ed578063ab033ea914610200578063ab24f52614610213578063b0a42a5114610226578063b7ab92e814610239578063c433c80a1461024c578063d4f9b7a71461025f578063d60a095514610272578063e7c7cb911461027a578063f8806a1314610282578063fd0679e9146102a2575b600080fd5b61011f61011a3660046121e7565b6102aa565b005b61012961033c565b60405161013691906126a5565b60405180910390f35b61014761034c565b60405161013691906128a4565b61011f6101623660046124f1565b61035f565b6101296101753660046121e7565b610411565b6101296101883660046121e7565b610627565b61011f61019b366004612383565b610652565b6101a86106e6565b6040516101369190612677565b6101c86101c33660046121e7565b6106f5565b604051610136969594939291906126c7565b61011f6101e83660046122a2565b610b3e565b61011f6101fb366004612529565b610c2b565b61011f61020e3660046121e7565b610eab565b61011f610221366004612242565b610f64565b61012961023436600461220a565b61102e565b61011f6102473660046124f1565b61105d565b61011f61025a36600461260c565b611119565b61011f61026d3660046124f1565b6111c3565b61012961125c565b61012961126c565b6102956102903660046121e7565b61127c565b604051610136919061281a565b610129611314565b60006102b582611324565b905060006102c283611446565b50905060008260020b8260020b136102dc578183036102e0565b8282035b6001600160a01b038516600090815260026020819052604090912054919250600160301b909104810b810b9082900b13156103365760405162461bcd60e51b815260040161032d9061278c565b60405180910390fd5b50505050565b600054600160a01b900460020b81565b600154600160301b900463ffffffff1681565b6000546001600160a01b031633146103895760405162461bcd60e51b815260040161032d906127a9565b60148160020b12156103ad5760405162461bcd60e51b815260040161032d90612736565b60018054600283810b62ffffff16630100000090810265ffffff000000198416179093556040517fb32bf5279c25f60e729f297567e5882813fe72a29dec91009962465b6a98a15f93610406930490910b9084906126b3565b60405180910390a150565b6000808290506000816001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b15801561045257600080fd5b505afa158015610466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048a919061257c565b5050604051633a76757360e11b815291955060009450506001850192508391506001600160a01b038616906374eceae6906104c9908590600401612895565b60e06040518083038186803b1580156104e157600080fd5b505afa1580156104f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610519919061243d565b5050505050509050801561052b578192505b604051633a76757360e11b81526000906001600160a01b038716906374eceae69061055a908790600401612895565b60e06040518083038186803b15801561057257600080fd5b505afa158015610586573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105aa919061243d565b505050506001600160a01b038b1660009081526002602052604090205491935050428390039150600160601b900463ffffffff16806105f55750600154600160301b900463ffffffff165b6106198a8263ffffffff168463ffffffff16116106125783610614565b825b611543565b9a9950505050505050505050565b6001600160a01b038116600090815260026020819052604090912054600160481b9004900b5b919050565b6000546001600160a01b0316331461067c5760405162461bcd60e51b815260040161032d906127a9565b805182511461069d5760405162461bcd60e51b815260040161032d90612752565b60005b82518110156106e1576106d98382815181106106b857fe5b60200260200101518383815181106106cc57fe5b6020026020010151610c2b565b6001016106a0565b505050565b6000546001600160a01b031681565b60008060008060008060008061070a89611446565b6001600160a01b038b1660009081526002602081905260409091205492945090925090810b900b158061076157506001600160a01b03891660009081526002602081905260409091205463010000009004810b900b155b1561092d576000805461077e90600160b81b900460020b8361194d565b90506040518060c001604052808260020b81526020016107ad600060149054906101000a900460020b8561194d565b600290810b825260015463010000008104820b820b602084015260409092019160649190810b8502900b0560020b8152602001600160069054906101000a900463ffffffff1663ffffffff1681526020016000601d9054906101000a900460020b60020b815250600260008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548162ffffff021916908360020b62ffffff16021790555060208201518160000160036101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160000160066101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160000160096101000a81548162ffffff021916908360020b62ffffff160217905550608082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160000160106101000a81548162ffffff021916908360020b62ffffff160217905550905050505b6001600160a01b038916600090815260026020819052604082208054835462ffffff60d01b1916600160d01b62ffffff6301000000909304850b850b9290921682021780855591549104820b820b90820b90910b1361099857600054600160d01b900460020b6109b7565b6001600160a01b038a16600090815260026020819052604090912054900b5b90508181620d89e719010160020b8360020b1380156109e657508181620d89e719600003030360020b8360020b125b610a025760405162461bcd60e51b815260040161032d906127c5565b6000610a0d8b611324565b905060008160020b8560020b13610a2657848203610a2a565b8185035b6001600160a01b038d16600090815260026020819052604090912054919250600160301b909104810b810b9082900b1315610a775760405162461bcd60e51b815260040161032d9061278c565b6000610a83868661194d565b905060008582019050600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a900460020b82039c50600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a900460020b82019b506000601a9054906101000a900460020b82039a508199508098506000601a9054906101000a900460020b810197505050505050505091939550919395565b6000546001600160a01b03163314610b685760405162461bcd60e51b815260040161032d906127a9565b8051835114610b7657600080fd5b8151835114610b8457600080fd5b60005b835181101561033657818181518110610b9c57fe5b602002602001015160036000868481518110610bb457fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000858481518110610bea57fe5b60209081029190910181015161ffff168252810191909152604001600020805460029290920b62ffffff1662ffffff19909216919091179055600101610b87565b6000546001600160a01b03163314610c555760405162461bcd60e51b815260040161032d906127a9565b6001600160a01b038116600081815260026020818152604092839020835160c081018552905480840b840b840b825263010000008104840b840b840b82840152600160301b8104840b840b840b82860152600160481b8104840b840b840b606083015263ffffffff600160601b8204166080830152600160801b9004830b830b90920b60a0830152855183516334324e9f60e21b815293519294610d55949193909263d0c93a7c9260048082019391829003018186803b158015610d1857600080fd5b505afa158015610d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d50919061250d565b61199b565b6040805160c0810182528451600290810b8252602080870151820b81840190815287850151830b8486019081526060808a0151850b9086019081526080808b015163ffffffff90811691880191825260a0808d0151880b9089019081526001600160a01b038c16600090815296889052958990209751885495519451935192519651880b62ffffff908116600160801b0262ffffff60801b1998909316600160601b0263ffffffff60601b19948a0b8216600160481b0262ffffff60481b19968b0b8316600160301b0262ffffff60301b19988c0b841663010000000265ffffff0000001995909c0b90931662ffffff199099169890981792909216989098179490941696909617919091169290921791909116171617815590517fe748bf5f6cb4a1bc33a8d0ec9893c62ea767c51450d362551972251729e9cd3f91610e9e91849190612828565b60405180910390a1505050565b6000546001600160a01b03163314610ed55760405162461bcd60e51b815260040161032d906127a9565b6001600160a01b038116610efb5760405162461bcd60e51b815260040161032d9061276f565b6000546040517f434a2db650703b36c824e745330d6397cdaa9ee2cc891a4938ae853e1c50b68d91610f3a916001600160a01b0390911690849061268b565b60405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f8e5760405162461bcd60e51b815260040161032d906127a9565b8051825114610faf5760405162461bcd60e51b815260040161032d90612752565b60005b82518110156106e157818181518110610fc757fe5b602002602001015160026000858481518110610fdf57fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460029290920b62ffffff16600160301b0262ffffff60301b19909216919091179055600101610fb2565b6001600160a01b03909116600090815260036020908152604080832061ffff9094168352929052205460020b90565b6000546001600160a01b031633146110875760405162461bcd60e51b815260040161032d906127a9565b60008160020b136110aa5760405162461bcd60e51b815260040161032d906127fd565b6000546040517f5d57c30988c079327c7a2866b4ec81c1eb83dca7d6ecd954093458c50034c938916110e991600160a01b90910460020b9084906126b3565b60405180910390a16000805460029290920b62ffffff16600160a01b0262ffffff60a01b19909216919091179055565b6000546001600160a01b031633146111435760405162461bcd60e51b815260040161032d906127a9565b60648163ffffffff16101561116a5760405162461bcd60e51b815260040161032d906127e1565b6001805463ffffffff838116600160301b90810263ffffffff60301b198416179093556040517f1c373b0a9b89049c835cfc0851faad1f23dbb7e5bd46cf58eb88da4dd760378b936104069304919091169084906128b5565b6000546001600160a01b031633146111ed5760405162461bcd60e51b815260040161032d906127a9565b60008160020b136112105760405162461bcd60e51b815260040161032d90612718565b60018054600283810b62ffffff1662ffffff198316179092556040517f6970a7f31fee92e8ced74d8833776ba308b9d4259e72a19b40ea53bdce8c8c489261040692900b9084906126b3565b600054600160e81b900460020b81565b6001546301000000900460020b81565b611284612003565b506001600160a01b0316600090815260026020818152604092839020835160c081018552905480840b840b840b825263010000008104840b840b840b92820192909252600160301b8204830b830b830b93810193909352600160481b8104820b820b820b606084015263ffffffff600160601b8204166080840152600160801b9004810b810b900b60a082015290565b600054600160b81b900460020b81565b600080826001600160a01b0316631a6865026040518163ffffffff1660e01b815260040160206040518083038186803b15801561136057600080fd5b505afa158015611374573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113989190612555565b90506001600160801b038116611434576000836001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b1580156113e357600080fd5b505afa1580156113f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141b919061257c565b505050505050905061142c816119f1565b925050611440565b61143d83610411565b91505b50919050565b600080826001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b15801561148257600080fd5b505afa158015611496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ba919061257c565b5050604080516334324e9f60e21b815290519497506001600160a01b038916955063d0c93a7c94600480830195506020945090925090829003018186803b15801561150457600080fd5b505afa158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c919061250d565b9050915091565b600063ffffffff8216611582576040805162461bcd60e51b8152602060048201526002602482015261042560f41b604482015290519081900360640190fd5b60408051600280825260608201835260009260208301908036833701905050905082816000815181106115b157fe5b602002602001019063ffffffff16908163ffffffff16815250506000816001815181106115da57fe5b63ffffffff909216602092830291909101820152604051639d3a524160e01b8152600481018281528351602483015283516000936001600160a01b03891693639d3a5241938793909283926044019185820191028083838b5b8381101561164b578181015183820152602001611633565b505050509050019250505060006040518083038186803b15801561166e57600080fd5b505afa158015611682573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260808110156116ab57600080fd5b8101908080516040519392919084600160201b8211156116ca57600080fd5b9083019060208201858111156116df57600080fd5b82518660208202830111600160201b821117156116fb57600080fd5b82525081516020918201928201910280838360005b83811015611728578181015183820152602001611710565b5050505090500160405260200180516040519392919084600160201b82111561175057600080fd5b90830190602082018581111561176557600080fd5b82518660208202830111600160201b8211171561178157600080fd5b82525081516020918201928201910280838360005b838110156117ae578181015183820152602001611796565b5050505090500160405260200180516040519392919084600160201b8211156117d657600080fd5b9083019060208201858111156117eb57600080fd5b82518660208202830111600160201b8211171561180757600080fd5b82525081516020918201928201910280838360005b8381101561183457818101518382015260200161181c565b5050505090500160405260200180516040519392919084600160201b82111561185c57600080fd5b90830190602082018581111561187157600080fd5b82518660208202830111600160201b8211171561188d57600080fd5b82525081516020918201928201910280838360005b838110156118ba5781810151838201526020016118a2565b5050505090500160405250505050505090506000816000815181106118db57fe5b6020026020010151826001815181106118f057fe5b60200260200101510390508463ffffffff168160060b8161190d57fe5b05935060008160060b12801561193757508463ffffffff168160060b8161193057fe5b0760060b15155b1561194457600019909301925b50505092915050565b6000808260020b8460020b8161195f57fe5b05905060008460020b12801561198657508260020b8460020b8161197f57fe5b0760020b15155b1561199057600019015b820290505b92915050565b620d89e8600283900b138015906119c257508060020b8260020b816119bc57fe5b0760020b155b80156119d1575060008260020b135b6119ed5760405162461bcd60e51b815260040161032d906126fb565b5050565b60006401000276a36001600160a01b03831610801590611a2d575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b611a62576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b600160201b600160c01b03602083901b166001600160801b03811160071b81811c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c97908811961790941790921717909117171760808110611af457607f810383901c9150611afe565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c6001603f1b161760c19b909b1c6001603e1b169a909a1760c29990991c6001603d1b169890981760c39790971c6001603c1b169690961760c49590951c6001603b1b169490941760c59390931c6001603a1b169290921760c69190911c600160391b161760c79190911c600160381b161760c89190911c600160371b161760c99190911c600160361b161760ca9190911c600160351b161760cb9190911c600160341b161760cc9190911c600160331b161760cd9190911c600160321b1617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b14611ccd57886001600160a01b0316611cb182611cdc565b6001600160a01b03161115611cc65781611cc8565b805b611ccf565b815b9998505050505050505050565b60008060008360020b12611cf3578260020b611cfb565b8260020b6000035b9050620d89e8811115611d39576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216611d4d57600160801b611d5f565b6ffffcb933bd6fad37aa2d162d1a5940015b6001600160881b031690506002821615611d89576ffff97272373d413259a46990580e213a0260801c5b6004821615611da8576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615611dc7576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615611de6576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615611e05576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611e24576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611e43576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611e63576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611e83576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611ea3576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615611ec3576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611ee3576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611f03576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611f23576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611f43576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611f64576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611f84576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611fa3576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615611fc0576b048a170391f7dc42444e8fa20260801c5b60008460020b1315611fdb578060001981611fd757fe5b0490505b600160201b810615611fee576001611ff1565b60005b60ff16602082901c0192505050919050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b600082601f830112612048578081fd5b8135602061205d612058836128ef565b6128cc565b8281528181019085830183850287018401881015612079578586fd5b855b858110156120a057813561208e8161290c565b8452928401929084019060010161207b565b5090979650505050505050565b600082601f8301126120bd578081fd5b813560206120cd612058836128ef565b82815281810190858301838502870184018810156120e9578586fd5b855b858110156120a05781356120fe81612924565b845292840192908401906001016120eb565b8051801515811461064d57600080fd5b803561064d81612924565b600060c0828403121561213c578081fd5b60405160c081016001600160401b038111828210171561215857fe5b604052905080823561216981612924565b8152602083013561217981612924565b6020820152604083013561218c81612924565b604082015261219d60608401612120565b60608201526121ae608084016121cb565b60808201526121bf60a08401612120565b60a08201525092915050565b803561064d81612943565b805160ff8116811461064d57600080fd5b6000602082840312156121f8578081fd5b81356122038161290c565b9392505050565b6000806040838503121561221c578081fd5b82356122278161290c565b9150602083013561223781612933565b809150509250929050565b60008060408385031215612254578081fd5b82356001600160401b038082111561226a578283fd5b61227686838701612038565b9350602085013591508082111561228b578283fd5b50612298858286016120ad565b9150509250929050565b6000806000606084860312156122b6578081fd5b83356001600160401b03808211156122cc578283fd5b6122d887838801612038565b94506020915081860135818111156122ee578384fd5b8601601f810188136122fe578384fd5b803561230c612058826128ef565b81815284810190838601868402850187018c1015612328578788fd5b8794505b8385101561235357803561233f81612933565b83526001949094019391860191860161232c565b509650505050604086013591508082111561236c578283fd5b50612379868287016120ad565b9150509250925092565b60008060408385031215612395578182fd5b82356001600160401b03808211156123ab578384fd5b818501915085601f8301126123be578384fd5b813560206123ce612058836128ef565b8281528181019085830160c0808602880185018c10156123ec57898afd5b8997505b85881015612418576124028c8361212b565b84526001979097019692840192908101906123f0565b50909750505086013592505080821115612430578283fd5b5061229885828601612038565b600080600080600080600060e0888a031215612457578485fd5b61246088612110565b9650602088015161247081612943565b8096505060408801518060060b8114612487578586fd5b60608901519095506124988161290c565b60808901519094506001600160581b03811681146124b4578384fd5b60a08901519093506124c581612924565b60c08901519092506001600160901b03811681146124e1578182fd5b8091505092959891949750929550565b600060208284031215612502578081fd5b813561220381612924565b60006020828403121561251e578081fd5b815161220381612924565b60008060e0838503121561253b578182fd5b612545848461212b565b915060c08301356122378161290c565b600060208284031215612566578081fd5b81516001600160801b0381168114612203578182fd5b600080600080600080600060e0888a031215612596578081fd5b87516125a18161290c565b60208901519097506125b281612924565b60408901519096506125c381612933565b60608901519095506125d481612933565b93506125e2608089016121d6565b92506125f060a089016121d6565b91506125fe60c08901612110565b905092959891949750929550565b60006020828403121561261d578081fd5b813561220381612943565b805160020b8252602081015160020b6020830152604081015160020b6040830152606081015160020b606083015263ffffffff608082015116608083015260a081015160020b60a08301525050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b60029190910b815260200190565b600292830b8152910b602082015260400190565b600296870b815294860b602086015292850b604085015290840b6060840152830b608083015290910b60a082015260c00190565b602080825260039082015262494e5360e81b604082015260600190565b6020808252600490820152634952454d60e01b604082015260600190565b602080825260029082015261282360f11b604082015260600190565b60208082526003908201526249564960e81b604082015260600190565b60208082526003908201526249474160e81b604082015260600190565b60208082526003908201526226aa2360e91b604082015260600190565b6020808252600290820152614e4760f01b604082015260600190565b602080825260029082015261125560f21b604082015260600190565b602080825260029082015261151160f21b604082015260600190565b60208082526003908201526249524d60e81b604082015260600190565b60c081016119958284612628565b61018081016128378285612628565b8254600281810b810b60c08501528160181c810b810b60e08501528160301c810b810b6101008501528160481c810b810b61012085015263ffffffff8260601c166101408501528160801c810b810b61016085015250509392505050565b61ffff91909116815260200190565b63ffffffff91909116815260200190565b63ffffffff92831681529116602082015260400190565b6040518181016001600160401b03811182821017156128e757fe5b604052919050565b60006001600160401b0382111561290257fe5b5060209081020190565b6001600160a01b038116811461292157600080fd5b50565b8060020b811461292157600080fd5b61ffff8116811461292157600080fd5b63ffffffff8116811461292157600080fdfea164736f6c6343000706000a0000000000000000000000001e3881227010c8dcdfa2f11833d3d70a00893f94
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001e3881227010c8dcdfa2f11833d3d70a00893f94
-----Decoded View---------------
Arg [0] : _governance (address): 0x1e3881227010c8dcdfa2f11833d3d70a00893f94
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001e3881227010c8dcdfa2f11833d3d70a00893f94
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.