Overview
BERA Balance
BERA Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
IslandRebalanceHelper
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity =0.8.19; import {IKodiakIslandWithRouter, IUniswapV3Pool} from "./interfaces/IKodiakIslandWithRouter.sol"; import {LiquidityAmounts} from "./vendor/uniswap/LiquidityAmounts.sol"; import {TickMath} from "./vendor/uniswap/TickMath.sol"; import {IUniswapV3Factory} from "lib/v3-core/contracts/interfaces/IUniswapV3Factory.sol"; import {IIslandRebalanceHelper, RebalanceParams, LiquidityData} from "./interfaces/IIslandRebalanceHelper.sol"; contract IslandRebalanceHelper is IIslandRebalanceHelper { using TickMath for int24; uint256 public constant X96 = 2 ** 96; int24 public constant MIN_TICK = -887272; int24 public constant MAX_TICK = 887272; uint256 public constant BPS_PRECISION = 10000; function getRebalanceParams( IKodiakIslandWithRouter island, int24 lowerTick, int24 upperTick, uint256 manualSwapAmountBPS, bool shouldCorrectTicks ) external view override returns (RebalanceParams memory params) { IUniswapV3Pool pool = island.pool(); IUniswapV3Factory factory = IUniswapV3Factory(pool.factory()); if (shouldCorrectTicks) { int24 tickSpacing = factory.feeAmountTickSpacing(pool.fee()); (lowerTick, upperTick) = correctTicks( lowerTick, upperTick, tickSpacing ); } (uint160 sqrtPriceX96, , , , , , ) = pool.slot0(); (uint256 amount0, uint256 amount1) = island.getUnderlyingBalances(); LiquidityData memory liquidityData = getLiquidityAmounts( amount0, amount1, lowerTick, upperTick, sqrtPriceX96 ); params.zeroForOne = liquidityData.bpsLeftOver0 > liquidityData.bpsLeftOver1; params.optimumSwapAmountBPS = getSwapAmountBPS( liquidityData.usedAmount0, liquidityData.usedAmount1, sqrtPriceX96, params.zeroForOne ); params.leftOver0 = liquidityData.leftOver0; params.leftOver1 = liquidityData.leftOver1; params.manualSwapAmount = manualSwapAmountBPS > 0 ? ( params.zeroForOne ? (liquidityData.leftOver0 * manualSwapAmountBPS) / BPS_PRECISION : (liquidityData.leftOver1 * manualSwapAmountBPS) / BPS_PRECISION ) : 0; params.optimumSwapAmount = params.zeroForOne ? (liquidityData.leftOver0 * params.optimumSwapAmountBPS) / BPS_PRECISION : (liquidityData.leftOver1 * params.optimumSwapAmountBPS) / BPS_PRECISION; uint256 swapAmount = params.manualSwapAmount > 0 ? params.manualSwapAmount : params.optimumSwapAmount; params.worstAmountOut = getWorstAmountOut( island, params.zeroForOne, swapAmount ); } function getWorstAmountOut( IKodiakIslandWithRouter island, bool zeroForOne, uint256 amountIn ) public view override returns (uint256 worstAmountOut) { uint160 avgPrice = island.getAvgPrice( island.compounderSlippageInterval() ); uint16 compounderSlippageBPS = island.compounderSlippageBPS(); worstAmountOut = island.worstAmountOut( amountIn, compounderSlippageBPS, avgPrice, zeroForOne ); } function getLiquidityAmounts( uint256 amount0, uint256 amount1, int24 _lowerTick, int24 _upperTick, uint160 sqrtPriceX96 ) public pure override returns (LiquidityData memory liquidityData) { uint128 liquidity = LiquidityAmounts.getLiquidityForAmounts( sqrtPriceX96, _lowerTick.getSqrtRatioAtTick(), _upperTick.getSqrtRatioAtTick(), amount0, amount1 ); ( liquidityData.usedAmount0, liquidityData.usedAmount1 ) = LiquidityAmounts.getAmountsForLiquidity( sqrtPriceX96, _lowerTick.getSqrtRatioAtTick(), _upperTick.getSqrtRatioAtTick(), liquidity ); liquidityData.leftOver0 = amount0 - liquidityData.usedAmount0; liquidityData.leftOver1 = amount1 - liquidityData.usedAmount1; liquidityData.bpsLeftOver0 = (liquidityData.leftOver0 * 10000) / amount0; liquidityData.bpsLeftOver1 = (liquidityData.leftOver1 * 10000) / amount1; } function getSwapAmountBPS( uint256 amount0Used, uint256 amount1Used, uint160 sqrtPriceX96, bool zeroForOne ) public pure override returns (uint256 swapAmountBPS) { uint256 priceX96 = (uint256(sqrtPriceX96) * uint256(sqrtPriceX96)) / X96; uint256 amount0In1 = (amount0Used * priceX96) / X96; uint256 bps0 = (amount0In1 * 10000) / (amount1Used + amount0In1); swapAmountBPS = zeroForOne ? (10000 - bps0) : bps0; } function correctTicks( int24 _lowerTick, int24 _upperTick, int24 tickSpacing ) public pure override returns (int24 newLowerTick, int24 newUpperTick) { newLowerTick = _lowerTick; newUpperTick = _upperTick; if (newLowerTick < MIN_TICK) { newLowerTick = MIN_TICK; } if (newUpperTick > MAX_TICK) { newUpperTick = MAX_TICK; } newLowerTick = (newLowerTick / tickSpacing) * tickSpacing; newUpperTick = (newUpperTick / tickSpacing) * tickSpacing; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity =0.8.19 ^0.8.0; // lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval( address indexed owner, address indexed spender, uint256 value ); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance( address owner, address spender ) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // src/vaults/interfaces/IUniswapV3MintCallback.sol /// @title Callback for IUniswapV3PoolActions#mint /// @notice Any contract that calls IUniswapV3PoolActions#mint must implement this interface interface IUniswapV3MintCallback { /// @notice Called to `msg.sender` after minting liquidity to a position from IUniswapV3Pool#mint. /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#mint call function uniswapV3MintCallback( uint256 amount0Owed, uint256 amount1Owed, bytes calldata data ) external; } // src/vaults/interfaces/IUniswapV3Pool.sol interface IUniswapV3Pool { function initialize(uint160 sqrtPriceX96) external; function mint( address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data ) external returns (uint256 amount0, uint256 amount1); function positions( bytes32 key ) external view returns ( uint128 _liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external returns (int256 amount0, int256 amount1); function burn( int24 tickLower, int24 tickUpper, uint128 amount ) external returns (uint256 amount0, uint256 amount1); function collect( address recipient, int24 tickLower, int24 tickUpper, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint32 feeProtocol, bool unlocked ); function feeGrowthGlobal0X128() external view returns (uint256); function feeGrowthGlobal1X128() external view returns (uint256); function ticks( int24 tick ) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128, int56 tickCumulativeOutside, uint160 secondsPerLiquidityOutsideX128, uint32 secondsOutside, bool initialized ); function observe( uint32[] calldata secondsAgos ) external view returns ( int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s ); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function fee() external view returns (uint24); function tickSpacing() external view returns (int24); function maxLiquidityPerTick() external view returns (uint128); } // src/vaults/interfaces/IUniswapV3SwapCallback.sol /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } // src/vaults/interfaces/IKodiakIsland.sol interface IKodiakIsland is IUniswapV3MintCallback, IUniswapV3SwapCallback { event Minted( address receiver, uint256 mintAmount, uint256 amount0In, uint256 amount1In, uint128 liquidityMinted ); event Burned( address receiver, uint256 burnAmount, uint256 amount0Out, uint256 amount1Out, uint128 liquidityBurned ); event Rebalance( address indexed compounder, int24 lowerTick_, int24 upperTick_, uint128 liquidityBefore, uint128 liquidityAfter ); event FeesEarned(uint256 feesEarned0, uint256 feesEarned1); // User functions function mint( uint256 mintAmount, address receiver ) external returns (uint256 amount0, uint256 amount1, uint128 liquidityMinted); event UpdateManagerParams( uint16 managerFeeBPS, address managerTreasury, uint16 compounderSlippageBPS, uint32 compounderSlippageInterval ); event PauserSet(address indexed pauser, bool status); event RestrictedMintSet(bool status); function burn( uint256 burnAmount, address receiver ) external returns (uint256 amount0, uint256 amount1, uint128 liquidityBurned); function updateManagerParams( int16 newManagerFeeBPS, address newManagerTreasury, int16 newSlippageBPS, int32 newSlippageInterval ) external; function setRestrictedMint(bool enabled) external; function setPauser(address _pauser, bool enabled) external; function pause() external; function unpause() external; function renounceOwnership() external; function transferOwnership(address newOwner) external; // Additional view functions that might be useful to expose: function managerBalance0() external view returns (uint256); function managerBalance1() external view returns (uint256); function managerTreasury() external view returns (address); function getUnderlyingBalancesAtPrice( uint160 sqrtRatioX96 ) external view returns (uint256 amount0Current, uint256 amount1Current); function manager() external view returns (address); function getMintAmounts( uint256 amount0Max, uint256 amount1Max ) external view returns (uint256 amount0, uint256 amount1, uint256 mintAmount); function getUnderlyingBalances() external view returns (uint256 amount0, uint256 amount1); function getPositionID() external view returns (bytes32 positionID); function token0() external view returns (IERC20); function token1() external view returns (IERC20); function upperTick() external view returns (int24); function lowerTick() external view returns (int24); function pool() external view returns (IUniswapV3Pool); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function managerFeeBPS() external view returns (uint16); function withdrawManagerBalance() external; function executiveRebalance( int24 newLowerTick, int24 newUpperTick, uint160 swapThresholdPrice, uint256 swapAmountBPS, bool zeroForOne ) external; function rebalance() external; function initialize( string memory _name, string memory _symbol, address _pool, uint16 _managerFeeBPS, int24 _lowerTick, int24 _upperTick, address _manager_ ) external; function compounderSlippageInterval() external view returns (uint32); function compounderSlippageBPS() external view returns (uint16); function restrictedMint() external view returns (bool); } // src/vaults/interfaces/IKodiakIslandWithRouter.sol struct SwapData { address router; uint256 amountIn; uint256 minAmountOut; bool zeroForOne; bytes routeData; } interface IKodiakIslandWithRouter is IKodiakIsland { // Manager Functions function setRouter(address swapRouter, bool enabled) external; function executiveRebalanceWithRouter( int24 newLowerTick, int24 newUpperTick, SwapData calldata swapData ) external; // View Functions function swapRouter(address router) external view returns (bool); function worstAmountOut( uint256 amountIn, uint16 slippageBPS, uint160 avgSqrtPriceX96, bool zeroForOne ) external pure returns (uint256); function getAvgPrice( uint32 interval ) external view returns (uint160 avgSqrtPriceX96); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0; import {FullMath} from "./FullMath.sol"; import "@kodiak-finance/v3-core/contracts/libraries/FixedPoint96.sol"; /// @title Liquidity amount functions /// @notice Provides functions for computing liquidity amounts from token amounts and prices library LiquidityAmounts { function toUint128(uint256 x) private pure returns (uint128 y) { require((y = uint128(x)) == x); } /// @notice Computes the amount of liquidity received for a given amount of token0 and price range /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower)). /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param amount0 The amount0 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount0( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96); return toUint128( FullMath.mulDiv( amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96 ) ); } /// @notice Computes the amount of liquidity received for a given amount of token1 and price range /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)). /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param amount1 The amount1 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount1( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount1 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return toUint128( FullMath.mulDiv( amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96 ) ); } /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current /// pool prices and the prices at the tick boundaries function getLiquidityForAmounts( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount0, uint256 amount1 ) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); if (sqrtRatioX96 < sqrtRatioAX96) { liquidity = getLiquidityForAmount0( sqrtRatioAX96, sqrtRatioBX96, amount0 ); } else if (sqrtRatioX96 < sqrtRatioBX96) { uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0); uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1); liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1; } else { liquidity = getLiquidityForAmount1( sqrtRatioAX96, sqrtRatioBX96, amount1 ); } } /// @notice Computes the amount of token0 for a given amount of liquidity and a price range /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The liquidity being valued /// @return amount0 The amount0 function getAmount0ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount0) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return FullMath.mulDiv( uint256(liquidity) << FixedPoint96.RESOLUTION, sqrtRatioBX96 - sqrtRatioAX96, sqrtRatioBX96 ) / sqrtRatioAX96; } /// @notice Computes the amount of token1 for a given amount of liquidity and a price range /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The liquidity being valued /// @return amount1 The amount1 function getAmount1ForLiquidity( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount1) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return FullMath.mulDiv( liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96 ); } /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current /// pool prices and the prices at the tick boundaries function getAmountsForLiquidity( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity ) internal pure returns (uint256 amount0, uint256 amount1) { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); if (sqrtRatioX96 < sqrtRatioAX96) { amount0 = getAmount0ForLiquidity( sqrtRatioAX96, sqrtRatioBX96, liquidity ); } else if (sqrtRatioX96 < sqrtRatioBX96) { amount0 = getAmount0ForLiquidity( sqrtRatioX96, sqrtRatioBX96, liquidity ); amount1 = getAmount1ForLiquidity( sqrtRatioAX96, sqrtRatioX96, liquidity ); } else { amount1 = getAmount1ForLiquidity( sqrtRatioAX96, sqrtRatioBX96, liquidity ); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.19; /// @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)); // EDIT: 0.8 compatibility require(absTick <= uint256(int256(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; /// @title The interface for the Uniswap V3 Factory /// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees interface IUniswapV3Factory { /// @notice Emitted when the owner of the factory is changed /// @param oldOwner The owner before the owner was changed /// @param newOwner The owner after the owner was changed event OwnerChanged(address indexed oldOwner, address indexed newOwner); /// @notice Emitted when a pool is created /// @param token0 The first token of the pool by address sort order /// @param token1 The second token of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool ); /// @notice Emitted when a new fee amount is enabled for pool creation via the factory /// @param fee The enabled fee, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing); /// @notice Returns the current owner of the factory /// @dev Can be changed by the current owner via setOwner /// @return The address of the factory owner function owner() external view returns (address); /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee /// @return The tick spacing function feeAmountTickSpacing(uint24 fee) external view returns (int24); /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @return pool The pool address function getPool( address tokenA, address tokenB, uint24 fee ) external view returns (address pool); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param fee The desired fee for the pool /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments /// are invalid. /// @return pool The address of the newly created pool function createPool( address tokenA, address tokenB, uint24 fee ) external returns (address pool); /// @notice Updates the owner of the factory /// @dev Must be called by the current owner /// @param _owner The new owner of the factory function setOwner(address _owner) external; /// @notice Enables a fee amount with the given tickSpacing /// @dev Fee amounts may never be removed once enabled /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6) /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount function enableFeeAmount(uint24 fee, int24 tickSpacing) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity =0.8.19; import {IKodiakIslandWithRouter} from "./IKodiakIslandWithRouter.sol"; struct RebalanceParams { bool zeroForOne; uint256 optimumSwapAmountBPS; uint256 worstAmountOut; uint256 leftOver0; uint256 leftOver1; uint256 optimumSwapAmount; uint256 manualSwapAmount; } struct LiquidityData { uint256 bpsLeftOver0; uint256 bpsLeftOver1; uint256 usedAmount0; uint256 usedAmount1; uint256 leftOver0; uint256 leftOver1; } interface IIslandRebalanceHelper { function getRebalanceParams( IKodiakIslandWithRouter island, int24 lowerTick, int24 upperTick, uint256 manualSwapAmountBPS, bool shouldCorrectTicks ) external view returns (RebalanceParams memory params); function getWorstAmountOut( IKodiakIslandWithRouter island, bool zeroForOne, uint256 amountIn ) external view returns (uint256 worstAmountOut); function getLiquidityAmounts( uint256 amount0, uint256 amount1, int24 _lowerTick, int24 _upperTick, uint160 sqrtPriceX96 ) external pure returns (LiquidityData memory liquidityData); function getSwapAmountBPS( uint256 amount0Used, uint256 amount1Used, uint160 sqrtPriceX96, bool zeroForOne ) external pure returns (uint256 swapAmountBPS); function correctTicks( int24 _lowerTick, int24 _upperTick, int24 tickSpacing ) external pure returns (int24 newLowerTick, int24 newUpperTick); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity =0.8.19; /// @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) { unchecked { // 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. // EDIT for 0.8 compatibility: // see: https://ethereum.stackexchange.com/questions/96642/unary-operator-cannot-be-applied-to-type-uint256 uint256 twos = denominator & (~denominator + 1); // 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.4.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "@uniswap/lib/=lib/solidity-lib/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "base64-sol/=lib/base64/", "@kodiak-finance/v3-periphery/contracts/=src/pools/v3-periphery/", "@kodiak-finance/v2-periphery/contracts/=src/pools/v2-periphery/", "@kodiak-finance/v2-core/contracts/=lib/v2-core/contracts/", "@kodiak-finance/v3-core/contracts/libraries/=lib/v3-core/contracts/libraries/", "@kodiak-finance/v3-core/contracts/interfaces/=lib/@kodiak-finance/v3-core/contracts/interfaces/", "@openzeppelin-8/contracts/=lib/openzeppelin-contracts-new/contracts/", "base64/=lib/base64/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-new/lib/erc4626-tests/", "openzeppelin-contracts-new/=lib/openzeppelin-contracts-new/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin/=lib/openzeppelin-contracts-new/contracts/", "solidity-lib/=lib/solidity-lib/contracts/", "v2-core/=lib/v2-core/contracts/", "v3-core/=lib/v3-core/", "@kodiak-finance/v3-periphery/contracts/=src/pools/v3-periphery/", "@kodiak-finance/v2-periphery/contracts/=src/pools/v2-periphery/", "@kodiak-finance/v2-core/contracts/=lib/v2-core/contracts/", "@kodiak-finance/v3-core/contracts/libraries/=lib/v3-core/contracts/libraries/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"BPS_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TICK","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TICK","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"X96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"_lowerTick","type":"int24"},{"internalType":"int24","name":"_upperTick","type":"int24"},{"internalType":"int24","name":"tickSpacing","type":"int24"}],"name":"correctTicks","outputs":[{"internalType":"int24","name":"newLowerTick","type":"int24"},{"internalType":"int24","name":"newUpperTick","type":"int24"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"int24","name":"_lowerTick","type":"int24"},{"internalType":"int24","name":"_upperTick","type":"int24"},{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"}],"name":"getLiquidityAmounts","outputs":[{"components":[{"internalType":"uint256","name":"bpsLeftOver0","type":"uint256"},{"internalType":"uint256","name":"bpsLeftOver1","type":"uint256"},{"internalType":"uint256","name":"usedAmount0","type":"uint256"},{"internalType":"uint256","name":"usedAmount1","type":"uint256"},{"internalType":"uint256","name":"leftOver0","type":"uint256"},{"internalType":"uint256","name":"leftOver1","type":"uint256"}],"internalType":"struct LiquidityData","name":"liquidityData","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IKodiakIslandWithRouter","name":"island","type":"address"},{"internalType":"int24","name":"lowerTick","type":"int24"},{"internalType":"int24","name":"upperTick","type":"int24"},{"internalType":"uint256","name":"manualSwapAmountBPS","type":"uint256"},{"internalType":"bool","name":"shouldCorrectTicks","type":"bool"}],"name":"getRebalanceParams","outputs":[{"components":[{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"uint256","name":"optimumSwapAmountBPS","type":"uint256"},{"internalType":"uint256","name":"worstAmountOut","type":"uint256"},{"internalType":"uint256","name":"leftOver0","type":"uint256"},{"internalType":"uint256","name":"leftOver1","type":"uint256"},{"internalType":"uint256","name":"optimumSwapAmount","type":"uint256"},{"internalType":"uint256","name":"manualSwapAmount","type":"uint256"}],"internalType":"struct RebalanceParams","name":"params","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Used","type":"uint256"},{"internalType":"uint256","name":"amount1Used","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"bool","name":"zeroForOne","type":"bool"}],"name":"getSwapAmountBPS","outputs":[{"internalType":"uint256","name":"swapAmountBPS","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IKodiakIslandWithRouter","name":"island","type":"address"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"getWorstAmountOut","outputs":[{"internalType":"uint256","name":"worstAmountOut","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50611656806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a5e4d75a11610066578063a5e4d75a146100f1578063b88595a31461015c578063c0332bad1461016f578063e083d2fb146101ce578063e41de313146101fb57600080fd5b806324a1d0c6146100985780636882a888146100be57806384863ffc146100db578063a1634b14146100e6575b600080fd5b6100ab6100a63660046111a5565b610204565b6040519081526020015b60405180910390f35b6100c8620d89e881565b60405160029190910b81526020016100b5565b6100ab600160601b81565b6100c8620d89e71981565b6101046100ff3660046111fe565b61028f565b6040516100b59190600060e0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b6100ab61016a366004611266565b61069a565b61018261017d3660046112a7565b61086b565b6040516100b59190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6101e16101dc3660046112f8565b610967565b60408051600293840b81529190920b6020820152016100b5565b6100ab61271081565b600080600160601b61021f6001600160a01b03861680611359565b610229919061138c565b90506000600160601b61023c8389611359565b610246919061138c565b9050600061025482886113a0565b61026083612710611359565b61026a919061138c565b9050846102775780610283565b610283816127106113b3565b98975050505050505050565b6102d16040518060e001604052806000151581526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610311573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033591906113c6565b90506000816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039b91906113c6565b9050831561048e576000816001600160a01b03166322afcccb846001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041691906113e3565b6040516001600160e01b031960e084901b16815262ffffff9091166004820152602401602060405180830381865afa158015610456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047a9190611408565b9050610487888883610967565b9098509650505b6000826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156104ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f2919061144b565b50505050505090506000808a6001600160a01b0316631322d9546040518163ffffffff1660e01b81526004016040805180830381865afa15801561053a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055e91906114da565b91509150600061057183838d8d8861086b565b6020810151815111808952604082015160608301519293506105969290918790610204565b6020880152608080820151606089015260a082015190880152886105bb576000610600565b86516105e357612710898260a001516105d49190611359565b6105de919061138c565b610600565b6127108982608001516105f69190611359565b610600919061138c565b60c088015286516106315761271087602001518260a001516106229190611359565b61062c919061138c565b610652565b612710876020015182608001516106489190611359565b610652919061138c565b60a088015260c087015160009061066d578760a00151610673565b8760c001515b90506106848d89600001518361069a565b604089015250959b9a5050505050505050505050565b600080846001600160a01b03166351a2dc92866001600160a01b031663385033456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070e91906114fe565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401602060405180830381865afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077491906113c6565b90506000856001600160a01b031663dcf0ff286040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190611519565b60405163d8329c3560e01b81526004810186905261ffff821660248201526001600160a01b03848116604483015287151560648301529192509087169063d8329c3590608401602060405180830381865afa15801561083d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108619190611534565b9695505050505050565b6108a46040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60006108c9836108b68760020b6109cc565b6108c28760020b6109cc565b8a8a610df0565b90506108ed836108db8760020b6109cc565b6108e78760020b6109cc565b84610eb5565b60608401526040830181905261090390886113b3565b6080830152606082015161091790876113b3565b60a08301526080820151879061092f90612710611359565b610939919061138c565b825260a0820151869061094e90612710611359565b610958919061138c565b60208301525095945050505050565b8282620d89e719600283900b121561098157620d89e71991505b620d89e8600282900b13156109965750620d89e85b826109a1818461154d565b6109ab9190611587565b9150826109b8818361154d565b6109c29190611587565b9050935093915050565b60008060008360020b126109e3578260020b6109f0565b8260020b6109f0906115ae565b90506109ff620d89e7196115ca565b60020b811115610a395760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640160405180910390fd5b600081600116600003610a5057600160801b610a62565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610aa1576080610a9c826ffff97272373d413259a46990580e213a611359565b901c90505b6004821615610acb576080610ac6826ffff2e50f5f656932ef12357cf3c7fdcc611359565b901c90505b6008821615610af5576080610af0826fffe5caca7e10e4e61c3624eaa0941cd0611359565b901c90505b6010821615610b1f576080610b1a826fffcb9843d60f6159c9db58835c926644611359565b901c90505b6020821615610b49576080610b44826fff973b41fa98c081472e6896dfb254c0611359565b901c90505b6040821615610b73576080610b6e826fff2ea16466c96a3843ec78b326b52861611359565b901c90505b6080821615610b9d576080610b98826ffe5dee046a99a2a811c461f1969c3053611359565b901c90505b610100821615610bc8576080610bc3826ffcbe86c7900a88aedcffc83b479aa3a4611359565b901c90505b610200821615610bf3576080610bee826ff987a7253ac413176f2b074cf7815e54611359565b901c90505b610400821615610c1e576080610c19826ff3392b0822b70005940c7a398e4b70f3611359565b901c90505b610800821615610c49576080610c44826fe7159475a2c29b7443b29c7fa6e889d9611359565b901c90505b611000821615610c74576080610c6f826fd097f3bdfd2022b8845ad8f792aa5825611359565b901c90505b612000821615610c9f576080610c9a826fa9f746462d870fdf8a65dc1f90e061e5611359565b901c90505b614000821615610cca576080610cc5826f70d869a156d2a1b890bb3df62baf32f7611359565b901c90505b618000821615610cf5576080610cf0826f31be135f97d08fd981231505542fcfa6611359565b901c90505b62010000821615610d21576080610d1c826f09aa508b5b7a84e1c677de54f3e99bc9611359565b901c90505b62020000821615610d4c576080610d47826e5d6af8dedb81196699c329225ee604611359565b901c90505b62040000821615610d76576080610d71826d2216e584f5fa1ea926041bedfe98611359565b901c90505b62080000821615610d9e576080610d99826b048a170391f7dc42444e8fa2611359565b901c90505b60008460020b1315610db957610db68160001961138c565b90505b610dc8640100000000826115ec565b15610dd4576001610dd7565b60005b610de89060ff16602083901c6113a0565b949350505050565b6000836001600160a01b0316856001600160a01b03161115610e10579293925b846001600160a01b0316866001600160a01b03161015610e3c57610e35858585610f52565b9050610eac565b836001600160a01b0316866001600160a01b03161015610e9e576000610e63878686610f52565b90506000610e72878986610fc7565b9050806001600160801b0316826001600160801b031610610e935780610e95565b815b92505050610eac565b610ea9858584610fc7565b90505b95945050505050565b600080836001600160a01b0316856001600160a01b03161115610ed6579293925b846001600160a01b0316866001600160a01b03161015610f0257610efb858585610ffd565b9150610f49565b836001600160a01b0316866001600160a01b03161015610f3b57610f27868585610ffd565b9150610f34858785611070565b9050610f49565b610f46858585611070565b90505b94509492505050565b6000826001600160a01b0316846001600160a01b03161115610f72579192915b6000610f95856001600160a01b0316856001600160a01b0316600160601b6110b6565b9050610fbc610fb78483610fa98989611600565b6001600160a01b03166110b6565b611164565b9150505b9392505050565b6000826001600160a01b0316846001600160a01b03161115610fe7579192915b610de8610fb783600160601b610fa98888611600565b6000826001600160a01b0316846001600160a01b0316111561101d579192915b6001600160a01b0384166110666fffffffffffffffffffffffffffffffff60601b606085901b1661104e8787611600565b6001600160a01b0316866001600160a01b03166110b6565b610de8919061138c565b6000826001600160a01b0316846001600160a01b03161115611090579192915b610de86001600160801b0383166110a78686611600565b6001600160a01b0316600160601b5b60008080600019858709858702925082811083820303915050806000036110ef57600084116110e457600080fd5b508290049050610fc0565b8084116110fb57600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b806001600160801b038116811461117a57600080fd5b919050565b6001600160a01b038116811461119457600080fd5b50565b801515811461119457600080fd5b600080600080608085870312156111bb57600080fd5b843593506020850135925060408501356111d48161117f565b915060608501356111e481611197565b939692955090935050565b8060020b811461119457600080fd5b600080600080600060a0868803121561121657600080fd5b85356112218161117f565b94506020860135611231816111ef565b93506040860135611241816111ef565b925060608601359150608086013561125881611197565b809150509295509295909350565b60008060006060848603121561127b57600080fd5b83356112868161117f565b9250602084013561129681611197565b929592945050506040919091013590565b600080600080600060a086880312156112bf57600080fd5b853594506020860135935060408601356112d8816111ef565b925060608601356112e8816111ef565b915060808601356112588161117f565b60008060006060848603121561130d57600080fd5b8335611318816111ef565b92506020840135611328816111ef565b91506040840135611338816111ef565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761137057611370611343565b92915050565b634e487b7160e01b600052601260045260246000fd5b60008261139b5761139b611376565b500490565b8082018082111561137057611370611343565b8181038181111561137057611370611343565b6000602082840312156113d857600080fd5b8151610fc08161117f565b6000602082840312156113f557600080fd5b815162ffffff81168114610fc057600080fd5b60006020828403121561141a57600080fd5b8151610fc0816111ef565b805161ffff8116811461117a57600080fd5b805163ffffffff8116811461117a57600080fd5b600080600080600080600060e0888a03121561146657600080fd5b87516114718161117f565b6020890151909750611482816111ef565b955061149060408901611425565b945061149e60608901611425565b93506114ac60808901611425565b92506114ba60a08901611437565b915060c08801516114ca81611197565b8091505092959891949750929550565b600080604083850312156114ed57600080fd5b505080516020909101519092909150565b60006020828403121561151057600080fd5b610fc082611437565b60006020828403121561152b57600080fd5b610fc082611425565b60006020828403121561154657600080fd5b5051919050565b60008160020b8360020b8061156457611564611376565b627fffff1982146000198214161561157e5761157e611343565b90059392505050565b60008260020b8260020b028060020b91508082146115a7576115a7611343565b5092915050565b6000600160ff1b82016115c3576115c3611343565b5060000390565b60008160020b627fffff1981036115e3576115e3611343565b60000392915050565b6000826115fb576115fb611376565b500690565b6001600160a01b038281168282160390808211156115a7576115a761134356fea264697066735822122053076b42be091661e9968c71bfc774e4f39661a439bc6c5ec36c153cb2c2a55c64736f6c63430008130033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063a5e4d75a11610066578063a5e4d75a146100f1578063b88595a31461015c578063c0332bad1461016f578063e083d2fb146101ce578063e41de313146101fb57600080fd5b806324a1d0c6146100985780636882a888146100be57806384863ffc146100db578063a1634b14146100e6575b600080fd5b6100ab6100a63660046111a5565b610204565b6040519081526020015b60405180910390f35b6100c8620d89e881565b60405160029190910b81526020016100b5565b6100ab600160601b81565b6100c8620d89e71981565b6101046100ff3660046111fe565b61028f565b6040516100b59190600060e0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b6100ab61016a366004611266565b61069a565b61018261017d3660046112a7565b61086b565b6040516100b59190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6101e16101dc3660046112f8565b610967565b60408051600293840b81529190920b6020820152016100b5565b6100ab61271081565b600080600160601b61021f6001600160a01b03861680611359565b610229919061138c565b90506000600160601b61023c8389611359565b610246919061138c565b9050600061025482886113a0565b61026083612710611359565b61026a919061138c565b9050846102775780610283565b610283816127106113b3565b98975050505050505050565b6102d16040518060e001604052806000151581526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610311573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033591906113c6565b90506000816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039b91906113c6565b9050831561048e576000816001600160a01b03166322afcccb846001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041691906113e3565b6040516001600160e01b031960e084901b16815262ffffff9091166004820152602401602060405180830381865afa158015610456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047a9190611408565b9050610487888883610967565b9098509650505b6000826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156104ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f2919061144b565b50505050505090506000808a6001600160a01b0316631322d9546040518163ffffffff1660e01b81526004016040805180830381865afa15801561053a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055e91906114da565b91509150600061057183838d8d8861086b565b6020810151815111808952604082015160608301519293506105969290918790610204565b6020880152608080820151606089015260a082015190880152886105bb576000610600565b86516105e357612710898260a001516105d49190611359565b6105de919061138c565b610600565b6127108982608001516105f69190611359565b610600919061138c565b60c088015286516106315761271087602001518260a001516106229190611359565b61062c919061138c565b610652565b612710876020015182608001516106489190611359565b610652919061138c565b60a088015260c087015160009061066d578760a00151610673565b8760c001515b90506106848d89600001518361069a565b604089015250959b9a5050505050505050505050565b600080846001600160a01b03166351a2dc92866001600160a01b031663385033456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070e91906114fe565b6040516001600160e01b031960e084901b16815263ffffffff919091166004820152602401602060405180830381865afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077491906113c6565b90506000856001600160a01b031663dcf0ff286040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190611519565b60405163d8329c3560e01b81526004810186905261ffff821660248201526001600160a01b03848116604483015287151560648301529192509087169063d8329c3590608401602060405180830381865afa15801561083d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108619190611534565b9695505050505050565b6108a46040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60006108c9836108b68760020b6109cc565b6108c28760020b6109cc565b8a8a610df0565b90506108ed836108db8760020b6109cc565b6108e78760020b6109cc565b84610eb5565b60608401526040830181905261090390886113b3565b6080830152606082015161091790876113b3565b60a08301526080820151879061092f90612710611359565b610939919061138c565b825260a0820151869061094e90612710611359565b610958919061138c565b60208301525095945050505050565b8282620d89e719600283900b121561098157620d89e71991505b620d89e8600282900b13156109965750620d89e85b826109a1818461154d565b6109ab9190611587565b9150826109b8818361154d565b6109c29190611587565b9050935093915050565b60008060008360020b126109e3578260020b6109f0565b8260020b6109f0906115ae565b90506109ff620d89e7196115ca565b60020b811115610a395760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640160405180910390fd5b600081600116600003610a5057600160801b610a62565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610aa1576080610a9c826ffff97272373d413259a46990580e213a611359565b901c90505b6004821615610acb576080610ac6826ffff2e50f5f656932ef12357cf3c7fdcc611359565b901c90505b6008821615610af5576080610af0826fffe5caca7e10e4e61c3624eaa0941cd0611359565b901c90505b6010821615610b1f576080610b1a826fffcb9843d60f6159c9db58835c926644611359565b901c90505b6020821615610b49576080610b44826fff973b41fa98c081472e6896dfb254c0611359565b901c90505b6040821615610b73576080610b6e826fff2ea16466c96a3843ec78b326b52861611359565b901c90505b6080821615610b9d576080610b98826ffe5dee046a99a2a811c461f1969c3053611359565b901c90505b610100821615610bc8576080610bc3826ffcbe86c7900a88aedcffc83b479aa3a4611359565b901c90505b610200821615610bf3576080610bee826ff987a7253ac413176f2b074cf7815e54611359565b901c90505b610400821615610c1e576080610c19826ff3392b0822b70005940c7a398e4b70f3611359565b901c90505b610800821615610c49576080610c44826fe7159475a2c29b7443b29c7fa6e889d9611359565b901c90505b611000821615610c74576080610c6f826fd097f3bdfd2022b8845ad8f792aa5825611359565b901c90505b612000821615610c9f576080610c9a826fa9f746462d870fdf8a65dc1f90e061e5611359565b901c90505b614000821615610cca576080610cc5826f70d869a156d2a1b890bb3df62baf32f7611359565b901c90505b618000821615610cf5576080610cf0826f31be135f97d08fd981231505542fcfa6611359565b901c90505b62010000821615610d21576080610d1c826f09aa508b5b7a84e1c677de54f3e99bc9611359565b901c90505b62020000821615610d4c576080610d47826e5d6af8dedb81196699c329225ee604611359565b901c90505b62040000821615610d76576080610d71826d2216e584f5fa1ea926041bedfe98611359565b901c90505b62080000821615610d9e576080610d99826b048a170391f7dc42444e8fa2611359565b901c90505b60008460020b1315610db957610db68160001961138c565b90505b610dc8640100000000826115ec565b15610dd4576001610dd7565b60005b610de89060ff16602083901c6113a0565b949350505050565b6000836001600160a01b0316856001600160a01b03161115610e10579293925b846001600160a01b0316866001600160a01b03161015610e3c57610e35858585610f52565b9050610eac565b836001600160a01b0316866001600160a01b03161015610e9e576000610e63878686610f52565b90506000610e72878986610fc7565b9050806001600160801b0316826001600160801b031610610e935780610e95565b815b92505050610eac565b610ea9858584610fc7565b90505b95945050505050565b600080836001600160a01b0316856001600160a01b03161115610ed6579293925b846001600160a01b0316866001600160a01b03161015610f0257610efb858585610ffd565b9150610f49565b836001600160a01b0316866001600160a01b03161015610f3b57610f27868585610ffd565b9150610f34858785611070565b9050610f49565b610f46858585611070565b90505b94509492505050565b6000826001600160a01b0316846001600160a01b03161115610f72579192915b6000610f95856001600160a01b0316856001600160a01b0316600160601b6110b6565b9050610fbc610fb78483610fa98989611600565b6001600160a01b03166110b6565b611164565b9150505b9392505050565b6000826001600160a01b0316846001600160a01b03161115610fe7579192915b610de8610fb783600160601b610fa98888611600565b6000826001600160a01b0316846001600160a01b0316111561101d579192915b6001600160a01b0384166110666fffffffffffffffffffffffffffffffff60601b606085901b1661104e8787611600565b6001600160a01b0316866001600160a01b03166110b6565b610de8919061138c565b6000826001600160a01b0316846001600160a01b03161115611090579192915b610de86001600160801b0383166110a78686611600565b6001600160a01b0316600160601b5b60008080600019858709858702925082811083820303915050806000036110ef57600084116110e457600080fd5b508290049050610fc0565b8084116110fb57600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b806001600160801b038116811461117a57600080fd5b919050565b6001600160a01b038116811461119457600080fd5b50565b801515811461119457600080fd5b600080600080608085870312156111bb57600080fd5b843593506020850135925060408501356111d48161117f565b915060608501356111e481611197565b939692955090935050565b8060020b811461119457600080fd5b600080600080600060a0868803121561121657600080fd5b85356112218161117f565b94506020860135611231816111ef565b93506040860135611241816111ef565b925060608601359150608086013561125881611197565b809150509295509295909350565b60008060006060848603121561127b57600080fd5b83356112868161117f565b9250602084013561129681611197565b929592945050506040919091013590565b600080600080600060a086880312156112bf57600080fd5b853594506020860135935060408601356112d8816111ef565b925060608601356112e8816111ef565b915060808601356112588161117f565b60008060006060848603121561130d57600080fd5b8335611318816111ef565b92506020840135611328816111ef565b91506040840135611338816111ef565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761137057611370611343565b92915050565b634e487b7160e01b600052601260045260246000fd5b60008261139b5761139b611376565b500490565b8082018082111561137057611370611343565b8181038181111561137057611370611343565b6000602082840312156113d857600080fd5b8151610fc08161117f565b6000602082840312156113f557600080fd5b815162ffffff81168114610fc057600080fd5b60006020828403121561141a57600080fd5b8151610fc0816111ef565b805161ffff8116811461117a57600080fd5b805163ffffffff8116811461117a57600080fd5b600080600080600080600060e0888a03121561146657600080fd5b87516114718161117f565b6020890151909750611482816111ef565b955061149060408901611425565b945061149e60608901611425565b93506114ac60808901611425565b92506114ba60a08901611437565b915060c08801516114ca81611197565b8091505092959891949750929550565b600080604083850312156114ed57600080fd5b505080516020909101519092909150565b60006020828403121561151057600080fd5b610fc082611437565b60006020828403121561152b57600080fd5b610fc082611425565b60006020828403121561154657600080fd5b5051919050565b60008160020b8360020b8061156457611564611376565b627fffff1982146000198214161561157e5761157e611343565b90059392505050565b60008260020b8260020b028060020b91508082146115a7576115a7611343565b5092915050565b6000600160ff1b82016115c3576115c3611343565b5060000390565b60008160020b627fffff1981036115e3576115e3611343565b60000392915050565b6000826115fb576115fb611376565b500690565b6001600160a01b038281168282160390808211156115a7576115a761134356fea264697066735822122053076b42be091661e9968c71bfc774e4f39661a439bc6c5ec36c153cb2c2a55c64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.