diff --git a/contracts/interfaces/external/IRamsesV3Factory.sol b/contracts/interfaces/external/IRamsesV3Factory.sol new file mode 100644 index 0000000..2c28cf7 --- /dev/null +++ b/contracts/interfaces/external/IRamsesV3Factory.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title The interface for the Ramses V3 Factory +/// @notice The Ramses V3 Factory facilitates creation of Ramses V3 pools and control over the protocol fees +interface IRamsesV3Factory { + error IT(); + /// @dev Fee Too Large + error FTL(); + error A0(); + error F0(); + error PE(); + + /// @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 tickspacing amount is enabled for pool creation via the factory + /// @dev unlike UniswapV3, we map via the tickSpacing rather than the fee tier + /// @param tickSpacing The minimum number of ticks between initialized ticks + /// @param fee The fee, denominated in hundredths of a bip + event TickSpacingEnabled(int24 indexed tickSpacing, uint24 indexed fee); + + /// @notice Emitted when the protocol fee is changed + /// @param feeProtocolOld The previous value of the protocol fee + /// @param feeProtocolNew The updated value of the protocol fee + event SetFeeProtocol(uint8 feeProtocolOld, uint8 feeProtocolNew); + + /// @notice Emitted when the protocol fee is changed + /// @param pool The pool address + /// @param feeProtocolOld The previous value of the protocol fee + /// @param feeProtocolNew The updated value of the protocol fee + event SetPoolFeeProtocol(address pool, uint8 feeProtocolOld, uint8 feeProtocolNew); + + /// @notice Emitted when a pool's fee is changed + /// @param pool The pool address + /// @param newFee The updated value of the protocol fee + event FeeAdjustment(address pool, uint24 newFee); + + /// @notice Emitted when the fee collector is changed + /// @param oldFeeCollector The previous implementation + /// @param newFeeCollector The new implementation + event FeeCollectorChanged(address indexed oldFeeCollector, address indexed newFeeCollector); + + /// @notice Returns the PoolDeployer address + /// @return The address of the PoolDeployer contract + function ramsesV3PoolDeployer() external returns (address); + + /// @notice Returns the fee amount for a given tickSpacing, if enabled, or 0 if not enabled + /// @dev A tickSpacing can never be removed, so this value should be hard coded or cached in the calling context + /// @dev unlike UniswapV3, we map via the tickSpacing rather than the fee tier + /// @param tickSpacing The enabled tickSpacing. Returns 0 in case of unenabled tickSpacing + /// @return initialFee The initial fee + function tickSpacingInitialFee(int24 tickSpacing) external view returns (uint24 initialFee); + + /// @notice Returns the pool address for a given pair of tokens and a tickSpacing, or address 0 if it does not exist + /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order + /// @dev unlike UniswapV3, we map via the tickSpacing rather than the fee tier + /// @param tokenA The contract address of either token0 or token1 + /// @param tokenB The contract address of the other token + /// @param tickSpacing The tickSpacing of the pool + /// @return pool The pool address + function getPool(address tokenA, address tokenB, int24 tickSpacing) external view returns (address pool); + + /// @notice Creates a pool for the given two tokens and fee + /// @dev unlike UniswapV3, we map via the tickSpacing rather than the fee tier + /// @param tokenA One of the two tokens in the desired pool + /// @param tokenB The other of the two tokens in the desired pool + /// @param tickSpacing The desired tickSpacing for the pool + /// @param sqrtPriceX96 initial sqrtPriceX96 of the pool + /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. + /// @dev The call will revert if the pool already exists, the tickSpacing is invalid, or the token arguments are invalid. + /// @return pool The address of the newly created pool + function createPool( + address tokenA, + address tokenB, + int24 tickSpacing, + uint160 sqrtPriceX96 + ) external returns (address pool); + + /// @notice Enables a tickSpacing with the given initialFee amount + /// @dev unlike UniswapV3, we map via the tickSpacing rather than the fee tier + /// @dev tickSpacings may never be removed once enabled + /// @param tickSpacing The spacing between ticks to be enforced for all pools created + /// @param initialFee The initial fee amount, denominated in hundredths of a bip (i.e. 1e-6) + function enableTickSpacing(int24 tickSpacing, uint24 initialFee) external; + + /// @notice returns the default protocol fee. + /// @return _feeProtocol the default feeProtocol + function feeProtocol() external view returns (uint8 _feeProtocol); + + /// @notice returns the % of fees directed to governance + /// @dev if the fee is 0, or the pool is uninitialized this will return the Factory's default feeProtocol + /// @param pool the address of the pool + /// @return _feeProtocol the feeProtocol for the pool + function poolFeeProtocol(address pool) external view returns (uint8 _feeProtocol); + + /// @notice Sets the default protocol's % share of the fees + /// @param _feeProtocol new default protocol fee for token0 and token1 + function setFeeProtocol(uint8 _feeProtocol) external; + + /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation. + /// @dev Called by the pool constructor to fetch the parameters of the pool + /// @return factory The factory address + /// @return token0 The first token of the pool by address sort order + /// @return token1 The second token of the pool by address sort order + /// @return fee The initialized feetier of the pool, denominated in hundredths of a bip + /// @return tickSpacing The minimum number of ticks between initialized ticks + function parameters() + external + view + returns (address factory, address token0, address token1, uint24 fee, int24 tickSpacing); + + /// @notice Sets the fee collector address + /// @param _feeCollector the fee collector address + function setFeeCollector(address _feeCollector) external; + + /// @notice sets the swap fee for a specific pool + /// @param _pool address of the pool + /// @param _fee the fee to be assigned to the pool, scaled to 1_000_000 = 100% + function setFee(address _pool, uint24 _fee) external; + + /// @notice Returns the address of the fee collector contract + /// @dev Fee collector decides where the protocol fees go (fee distributor, treasury, etc.) + function feeCollector() external view returns (address); + + /// @notice sets the feeProtocol of a specific pool + /// @param pool address of the pool + /// @param _feeProtocol the fee protocol to assign + function setPoolFeeProtocol(address pool, uint8 _feeProtocol) external; + + /// @notice sets the feeProtocol upon a gauge's creation + /// @param pool address of the pool + function gaugeFeeSplitEnable(address pool) external; + + /// @notice sets the the voter address + /// @param _voter the address of the voter + function setVoter(address _voter) external; + + function initialize(address poolDeployer) external; +} \ No newline at end of file diff --git a/contracts/interfaces/external/IRamsesV3Pool.sol b/contracts/interfaces/external/IRamsesV3Pool.sol new file mode 100644 index 0000000..313edd6 --- /dev/null +++ b/contracts/interfaces/external/IRamsesV3Pool.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +import {IRamsesV3PoolImmutables} from './shadow-cl/IRamsesV3PoolImmutables.sol'; +import {IRamsesV3PoolState} from './shadow-cl/IRamsesV3PoolState.sol'; +import {IRamsesV3PoolDerivedState} from './shadow-cl/IRamsesV3PoolDerivedState.sol'; +import {IRamsesV3PoolActions} from './shadow-cl/IRamsesV3PoolActions.sol'; +import {IRamsesV3PoolOwnerActions} from './shadow-cl/IRamsesV3PoolOwnerActions.sol'; +import {IRamsesV3PoolErrors} from './shadow-cl/IRamsesV3PoolErrors.sol'; +import {IRamsesV3PoolEvents} from './shadow-cl/IRamsesV3PoolEvents.sol'; + +/// @title The interface for a Ramses V3 Pool +/// @notice A Ramses pool facilitates swapping and automated market making between any two assets that strictly conform +/// to the ERC20 specification +/// @dev The pool interface is broken up into many smaller pieces +interface IRamsesV3Pool is + IRamsesV3PoolImmutables, + IRamsesV3PoolState, + IRamsesV3PoolDerivedState, + IRamsesV3PoolActions, + IRamsesV3PoolOwnerActions, + IRamsesV3PoolErrors, + IRamsesV3PoolEvents +{ + /// @notice if a new period, advance on interaction + function _advancePeriod() external; +} \ No newline at end of file diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolActions.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolActions.sol new file mode 100644 index 0000000..fdf992a --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolActions.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Permissionless pool actions +/// @notice Contains pool methods that can be called by anyone +interface IRamsesV3PoolActions { + /// @notice Sets the initial price for the pool + /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value + /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96 + function initialize(uint160 sqrtPriceX96) external; + + /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position + /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback + /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends + /// on tickLower, tickUpper, the amount of liquidity, and the current price. + /// @param recipient The address for which the liquidity will be created + /// @param index The index for which the liquidity will be created + /// @param tickLower The lower tick of the position in which to add liquidity + /// @param tickUpper The upper tick of the position in which to add liquidity + /// @param amount The 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 + function mint( + address recipient, + uint256 index, + int24 tickLower, + int24 tickUpper, + uint128 amount, + bytes calldata data + ) external returns (uint256 amount0, uint256 amount1); + + /// @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 index The index of the position to be collected + /// @param tickLower The lower tick of the position for which to collect fees + /// @param tickUpper 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, + uint256 index, + int24 tickLower, + int24 tickUpper, + 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 index The index for which the liquidity will be burned + /// @param tickLower The lower tick of the position for which to burn liquidity + /// @param tickUpper 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( + uint256 index, + int24 tickLower, + int24 tickUpper, + 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 IUniswapV3SwapCallback#uniswapV3SwapCallback + /// @param recipient The address to receive the output of the swap + /// @param zeroForOne 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 sqrtPriceLimitX96 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 + /// @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 zeroForOne, + int256 amountSpecified, + uint160 sqrtPriceLimitX96, + 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 IUniswapV3FlashCallback#uniswapV3FlashCallback + /// @dev Can be used to donate underlying tokens pro-rata 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; + + + /// @notice Increase the maximum number of price and liquidity observations that this pool will store + /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to + /// the input observationCardinalityNext. + /// @param observationCardinalityNext The desired minimum number of observations for the pool to store + function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external; +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDeployer.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDeployer.sol new file mode 100644 index 0000000..0682924 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDeployer.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title An interface for a contract that is capable of deploying Ramses V3 Pools +/// @notice A contract that constructs a pool must implement this to pass arguments to the pool +/// @dev This is used to avoid having constructor arguments in the pool contract, which results in the init code hash +/// of the pool being constant allowing the CREATE2 address of the pool to be cheaply computed on-chain +interface IRamsesV3PoolDeployer { + /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation. + /// @dev Called by the pool constructor to fetch the parameters of the pool + /// Returns factory The factory address + /// Returns token0 The first token of the pool by address sort order + /// Returns token1 The second token of the pool by address sort order + /// Returns fee The fee collected upon every swap in the pool, denominated in hundredths of a bip + /// Returns tickSpacing The minimum number of ticks between initialized ticks + function parameters() + external + view + returns (address factory, address token0, address token1, uint24 fee, int24 tickSpacing); + + /// @dev Deploys a pool with the given parameters by transiently setting the parameters storage slot and then + /// clearing it after deploying the pool. + /// @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 tickSpacing The tickSpacing of the pool + function deploy(address token0, address token1, int24 tickSpacing) external returns (address pool); + + function RamsesV3Factory() external view returns (address factory); +} \ No newline at end of file diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDerivedState.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDerivedState.sol new file mode 100644 index 0000000..69f4c68 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolDerivedState.sol @@ -0,0 +1,35 @@ +// 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. +interface IRamsesV3PoolDerivedState { + /// @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 secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block + /// timestamp + function observe( + uint32[] calldata secondsAgos + ) external view returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s); + + /// @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 tickLower The lower tick of the range + /// @param tickUpper The upper tick of the range + /// @return tickCumulativeInside The snapshot of the tick accumulator for the range + /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range + /// @return secondsInside The snapshot of seconds per liquidity for the range + function snapshotCumulativesInside( + int24 tickLower, + int24 tickUpper + ) external view returns (int56 tickCumulativeInside, uint160 secondsPerLiquidityInsideX128, uint32 secondsInside); +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolErrors.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolErrors.sol new file mode 100644 index 0000000..e22f1ca --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolErrors.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Errors emitted by a pool +/// @notice Contains all events emitted by the pool +interface IRamsesV3PoolErrors { + error LOK(); + error TLU(); + error TLM(); + error TUM(); + error AI(); + error M0(); + error M1(); + error AS(); + error IIA(); + error L(); + error F0(); + error F1(); + error SPL(); +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolEvents.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolEvents.sol new file mode 100644 index 0000000..31592f5 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolEvents.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Events emitted by a pool +/// @notice Contains all events emitted by the pool +interface IRamsesV3PoolEvents { + /// @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 sqrtPriceX96 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 sqrtPriceX96, 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 tickLower The lower tick of the position + /// @param tickUpper The upper tick of the position + /// @param amount 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 tickLower, + int24 indexed tickUpper, + uint128 amount, + 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 tickLower The lower tick of the position + /// @param tickUpper 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 tickLower, + int24 indexed tickUpper, + 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 tickLower The lower tick of the position + /// @param tickUpper The upper tick of the position + /// @param amount 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 tickLower, + int24 indexed tickUpper, + uint128 amount, + 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 sqrtPriceX96 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 sqrtPriceX96, + 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 by the pool for increases to the number of observations that can be stored + /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index + /// just before a mint/swap/burn. + /// @param observationCardinalityNextOld The previous value of the next observation cardinality + /// @param observationCardinalityNextNew The updated value of the next observation cardinality + event IncreaseObservationCardinalityNext( + uint16 observationCardinalityNextOld, + uint16 observationCardinalityNextNew + ); + + /// @notice Emitted when the protocol fee is changed by the pool + /// @param feeProtocol0Old The previous value of the token0 protocol fee + /// @param feeProtocol1Old The previous value of the token1 protocol fee + /// @param feeProtocol0New The updated value of the token0 protocol fee + /// @param feeProtocol1New The updated value of the token1 protocol fee + event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New); + + /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner + /// @param sender The address that collects the protocol fees + /// @param recipient The address that receives the collected protocol fees + /// @param amount0 The amount of token0 protocol fees that is withdrawn + /// @param amount0 The amount of token1 protocol fees that is withdrawn + event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1); +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolImmutables.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolImmutables.sol new file mode 100644 index 0000000..b447a1e --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolImmutables.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Pool state that never changes +/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values +interface IRamsesV3PoolImmutables { + /// @notice The contract that deployed the pool, which must adhere to the IRamsesV3Factory 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's fee in hundredths of a bip, i.e. 1e-6 + /// @return The fee + function fee() external view returns (uint24); + + /// @notice The pool tick spacing + /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive + /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ... + /// 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); +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolOwnerActions.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolOwnerActions.sol new file mode 100644 index 0000000..3573a03 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolOwnerActions.sol @@ -0,0 +1,23 @@ +// 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 +interface IRamsesV3PoolOwnerActions { + /// @notice Set the denominator of the protocol's % share of the fees + function setFeeProtocol() external; + + /// @notice Collect the protocol fee accrued to the pool + /// @param recipient The address to which collected protocol fees should be sent + /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1 + /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0 + /// @return amount0 The protocol fee collected in token0 + /// @return amount1 The protocol fee collected in token1 + function collectProtocol( + address recipient, + uint128 amount0Requested, + uint128 amount1Requested + ) external returns (uint128 amount0, uint128 amount1); + + function setFee(uint24 _fee) external; +} diff --git a/contracts/interfaces/external/shadow-cl/IRamsesV3PoolState.sol b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolState.sol new file mode 100644 index 0000000..b7affb5 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IRamsesV3PoolState.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Pool state that can change +/// @notice These methods compose the pool's state, and can change with any frequency including multiple times +/// per transaction +interface IRamsesV3PoolState { + /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas + /// when accessed externally. + /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value + /// @return tick The current tick of the pool, i.e. according to the last tick transition that was run. + /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick + /// boundary. + /// @return observationIndex The index of the last oracle observation that was written, + /// @return observationCardinality The current maximum number of observations stored in the pool, + /// @return observationCardinalityNext The next maximum number of observations, to be updated when the observation. + /// @return feeProtocol The protocol fee for both tokens of the pool. + /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0 + /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee. + /// unlocked Whether the pool is currently locked to reentrancy + function slot0() + external + view + returns ( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + 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 feeGrowthGlobal0X128() 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 feeGrowthGlobal1X128() external view returns (uint256); + + /// @notice The amounts of token0 and token1 that are owed to the protocol + /// @dev Protocol fees will never exceed uint128 max in either token + function protocolFees() external view returns (uint128 token0, uint128 token1); + + /// @notice The currently in range liquidity available to the pool + /// @dev This value has no relationship to the total liquidity across all ticks + /// @return The liquidity at the current price of the pool + function liquidity() external view returns (uint128); + + /// @notice Look up information about a specific tick in the pool + /// @param tick The tick to look up + /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or + /// tick upper + /// @return liquidityNet how much liquidity changes when the pool price crosses the tick, + /// @return feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0, + /// @return feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1, + /// @return tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick + /// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick, + /// @return secondsOutside the seconds spent on the other side of the tick from the current tick, + /// @return initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false. + /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0. + /// 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 liquidityGross, + int128 liquidityNet, + uint256 feeGrowthOutside0X128, + uint256 feeGrowthOutside1X128, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized + ); + + /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information + function tickBitmap(int16 wordPosition) external view returns (uint256); + + /// @notice Returns the information about a position by the position's key + /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper + /// @return liquidity The amount of liquidity in the position, + /// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke, + /// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke, + /// @return tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke, + /// @return tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke + function positions( + bytes32 key + ) + external + view + returns ( + uint128 liquidity, + uint256 feeGrowthInside0LastX128, + uint256 feeGrowthInside1LastX128, + uint128 tokensOwed0, + uint128 tokensOwed1 + ); + + /// @notice Returns data about a specific observation index + /// @param index The element of the observations array to fetch + /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time + /// ago, rather than at a specific index in the array. + /// @return blockTimestamp The timestamp of the observation, + /// @return tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, + /// @return secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp, + /// @return initialized whether the observation has been initialized and the values are safe to use + function observations( + uint256 index + ) + external + view + returns ( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized + ); + + + /// @notice get the period seconds in range of a specific position + /// @param period the period number + /// @param owner owner address + /// @param index position index + /// @param tickLower lower bound of range + /// @param tickUpper upper bound of range + /// @return periodSecondsInsideX96 seconds the position was not in range for the period + function positionPeriodSecondsInRange( + uint256 period, + address owner, + uint256 index, + int24 tickLower, + int24 tickUpper + ) external view returns (uint256 periodSecondsInsideX96); +} diff --git a/contracts/interfaces/external/shadow-cl/IVoteModule.sol b/contracts/interfaces/external/shadow-cl/IVoteModule.sol new file mode 100644 index 0000000..582efb6 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IVoteModule.sol @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +interface IVoteModule { + /** + * Events + */ + event Deposit(address indexed from, uint256 amount); + + event Withdraw(address indexed from, uint256 amount); + + event NotifyReward(address indexed from, uint256 amount); + + event ClaimRewards(address indexed from, uint256 amount); + + event ExemptedFromCooldown(address indexed candidate, bool status); + + event NewDuration(uint256 oldDuration, uint256 newDuration); + + event NewCooldown(uint256 oldCooldown, uint256 newCooldown); + + event Delegate(address indexed delegator, address indexed delegatee, bool indexed isAdded); + + event SetAdmin(address indexed owner, address indexed operator, bool indexed isAdded); + + /** + * Functions + */ + function delegates(address) external view returns (address); + /// @notice mapping for admins for a specific address + /// @param owner the owner to check against + /// @return operator the address that is designated as an admin/operator + function admins(address owner) external view returns (address operator); + + function accessHub() external view returns (address); + + /// @notice reward supply for a period + function rewardSupply(uint256 period) external view returns (uint256); + + /// @notice user claimed reward amount for a period + /// @dev same mapping order as FeeDistributor so the name is a bit odd + function userClaimed(uint256 period, address owner) external view returns (uint256); + + /// @notice last claimed period for a user + function userLastClaimPeriod(address owner) external view returns (uint256); + + /// @notice returns the current period + function getPeriod() external view returns (uint256); + + /// @notice returns the amount of unclaimed rebase earned by the user + function earned(address account) external view returns (uint256 _reward); + + /// @notice returns the amount of unclaimed rebase earned by the user for a period + function periodEarned(uint256 period, address user) external view returns (uint256 amount); + + /// @notice the time which users can deposit and withdraw + function unlockTime() external view returns (uint256 _timestamp); + + /// @notice claims pending rebase rewards + function getReward() external; + + /// @notice claims pending rebase rewards for a period + function getPeriodReward(uint256 period) external; + + /// @notice allows users to set their own last claimed period in case they haven't claimed in a while + /// @param period the new period to start loops from + function setUserLastClaimPeriod(uint256 period) external; + + /// @notice deposits all xShadow in the caller's wallet + function depositAll() external; + + /// @notice deposit a specified amount of xShadow + function deposit(uint256 amount) external; + + /// @notice withdraw all xShadow + function withdrawAll() external; + + /// @notice withdraw a specified amount of xShadow + function withdraw(uint256 amount) external; + + /// @notice check for admin perms + /// @param operator the address to check + /// @param owner the owner to check against for permissions + function isAdminFor(address operator, address owner) external view returns (bool approved); + + /// @notice check for delegations + /// @param delegate the address to check + /// @param owner the owner to check against for permissions + function isDelegateFor(address delegate, address owner) external view returns (bool approved); + + /// @notice used by the xShadow contract to notify pending rebases + /// @param amount the amount of Shadow to be notified from exit penalties + function notifyRewardAmount(uint256 amount) external; + + /// @notice the address of the xShadow token (staking/voting token) + /// @return _xShadow the address + function xShadow() external view returns (address _xShadow); + + /// @notice address of the voter contract + /// @return _voter the voter contract address + function voter() external view returns (address _voter); + + /// @notice returns the total voting power (equal to total supply in the VoteModule) + /// @return _totalSupply the total voting power + function totalSupply() external view returns (uint256 _totalSupply); + + /// @notice voting power + /// @param user the address to check + /// @return amount the staked balance + function balanceOf(address user) external view returns (uint256 amount); + + /// @notice delegate voting perms to another address + /// @param delegatee who you delegate to + /// @dev set address(0) to revoke + function delegate(address delegatee) external; + + /// @notice give admin permissions to a another address + /// @param operator the address to give administrative perms to + /// @dev set address(0) to revoke + function setAdmin(address operator) external; + + function cooldownExempt(address) external view returns (bool); + + function setCooldownExemption(address, bool) external; + + /// @notice lock period after rebase starts accruing + function cooldown() external returns (uint256); + + function setNewCooldown(uint256) external; +} diff --git a/contracts/interfaces/external/shadow-cl/IVoter.sol b/contracts/interfaces/external/shadow-cl/IVoter.sol new file mode 100644 index 0000000..9921aa9 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/IVoter.sol @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; +pragma abicoder v2; + +interface IVoter { + event GaugeCreated(address indexed gauge, address creator, address feeDistributor, address indexed pool); + + event GaugeKilled(address indexed gauge); + + event GaugeRevived(address indexed gauge); + + event Voted(address indexed owner, uint256 weight, address indexed pool); + + event Abstained(address indexed owner, uint256 weight); + + event Deposit(address indexed lp, address indexed gauge, address indexed owner, uint256 amount); + + event Withdraw(address indexed lp, address indexed gauge, address indexed owner, uint256 amount); + + event NotifyReward(address indexed sender, address indexed reward, uint256 amount); + + event DistributeReward(address indexed sender, address indexed gauge, uint256 amount); + + event EmissionsRatio(address indexed caller, uint256 oldRatio, uint256 newRatio); + + event NewGovernor(address indexed sender, address indexed governor); + + event Whitelisted(address indexed whitelister, address indexed token); + + event WhitelistRevoked(address indexed forbidder, address indexed token, bool status); + + event MainTickSpacingChanged(address indexed token0, address indexed token1, int24 indexed newMainTickSpacing); + + event Poke(address indexed user); + + event EmissionsRedirected(address indexed sourceGauge, address indexed destinationGauge); + + struct InitializationParams { + address shadow; + address legacyFactory; + address gauges; + address feeDistributorFactory; + address minter; + address msig; + address xShadow; + address clFactory; + address clGaugeFactory; + address nfpManager; + address feeRecipientFactory; + address voteModule; + address launcherPlugin; + address poolUpdater; + } + + function initialize(InitializationParams memory inputs) external; + + /// @notice denominator basis + function BASIS() external view returns (uint256); + + /// @notice ratio of xShadow emissions globally + function xRatio() external view returns (uint256); + + /// @notice xShadow contract address + function xShadow() external view returns (address); + + /// @notice legacy factory address (uni-v2/stableswap) + function legacyFactory() external view returns (address); + + /// @notice concentrated liquidity factory + function clFactory() external view returns (address); + + /// @notice gauge factory for CL + function clGaugeFactory() external view returns (address); + + /// @notice pool updater for CL + function poolUpdater() external view returns (address); + + /// @notice legacy fee recipient factory + function feeRecipientFactory() external view returns (address); + + /// @notice peripheral NFPManager contract + function nfpManager() external view returns (address); + + /// @notice returns the address of the current governor + /// @return _governor address of the governor + function governor() external view returns (address _governor); + + /// @notice the address of the vote module + /// @return _voteModule the vote module contract address + function voteModule() external view returns (address _voteModule); + + /// @notice address of the central access Hub + function accessHub() external view returns (address); + + /// @notice the address of the shadow launcher plugin to enable third party launchers + /// @return _launcherPlugin the address of the plugin + function launcherPlugin() external view returns (address _launcherPlugin); + + /// @notice distributes emissions from the minter to the voter + /// @param amount the amount of tokens to notify + function notifyRewardAmount(uint256 amount) external; + + /// @notice distributes the emissions for a specific gauge + /// @param _gauge the gauge address + function distribute(address _gauge) external; + + /// @notice returns the address of the gauge factory + /// @param _gaugeFactory gauge factory address + function gaugeFactory() external view returns (address _gaugeFactory); + + /// @notice returns the address of the feeDistributor factory + /// @return _feeDistributorFactory feeDist factory address + function feeDistributorFactory() external view returns (address _feeDistributorFactory); + + /// @notice returns the address of the minter contract + /// @return _minter address of the minter + function minter() external view returns (address _minter); + + /// @notice check if the gauge is active for governance use + /// @param _gauge address of the gauge + /// @return _trueOrFalse if the gauge is alive + function isAlive(address _gauge) external view returns (bool _trueOrFalse); + + /// @notice allows the token to be paired with other whitelisted assets to participate in governance + /// @param _token the address of the token + function whitelist(address _token) external; + + /// @notice effectively disqualifies a token from governance + /// @param _token the address of the token + function revokeWhitelist(address _token) external; + + /// @notice returns if the address is a gauge + /// @param gauge address of the gauge + /// @return _trueOrFalse boolean if the address is a gauge + function isGauge(address gauge) external view returns (bool _trueOrFalse); + + /// @notice disable a gauge from governance + /// @param _gauge address of the gauge + function killGauge(address _gauge) external; + + /// @notice re-activate a dead gauge + /// @param _gauge address of the gauge + function reviveGauge(address _gauge) external; + + /// @notice re-cast a tokenID's votes + /// @param owner address of the owner + function poke(address owner) external; + + /// @notice sets the main destinationGauge of a token pairing + /// @param tokenA address of tokenA + /// @param tokenB address of tokenB + /// @param destinationGauge the main gauge to set to + function redirectEmissions(address tokenA, address tokenB, address destinationGauge) external; + + /// @notice returns if the address is a fee distributor + /// @param _feeDistributor address of the feeDist + /// @return _trueOrFalse if the address is a fee distributor + function isFeeDistributor(address _feeDistributor) external view returns (bool _trueOrFalse); + + /// @notice returns the address of the emission's token + /// @return _shadow emissions token contract address + function shadow() external view returns (address _shadow); + + /// @notice returns the address of the pool's gauge, if any + /// @param _pool pool address + /// @return _gauge gauge address + function gaugeForPool(address _pool) external view returns (address _gauge); + + /// @notice returns the address of the pool's feeDistributor, if any + /// @param _gauge address of the gauge + /// @return _feeDistributor address of the pool's feedist + function feeDistributorForGauge(address _gauge) external view returns (address _feeDistributor); + + /// @notice returns the gauge address of a CL pool + /// @param tokenA address of token A in the pair + /// @param tokenB address of token B in the pair + /// @param tickSpacing tickspacing of the pool + /// @return gauge address of the gauge + function gaugeForClPool(address tokenA, address tokenB, int24 tickSpacing) external view returns (address gauge); + + /// @notice returns the array of all tickspacings for the tokenA/tokenB combination + /// @param tokenA address of token A in the pair + /// @param tokenB address of token B in the pair + /// @return _ts array of all the tickspacings + function tickSpacingsForPair(address tokenA, address tokenB) external view returns (int24[] memory _ts); + + /// @notice returns the destination of a gauge redirect + /// @param gauge address of gauge + function gaugeRedirect(address gauge) external view returns (address); + + /// @notice returns the block.timestamp divided by 1 week in seconds + /// @return period the period used for gauges + function getPeriod() external view returns (uint256 period); + + /// @notice cast a vote to direct emissions to gauges and earn incentives + /// @param owner address of the owner + /// @param _pools the list of pools to vote on + /// @param _weights an arbitrary weight per pool which will be normalized to 100% regardless of numerical inputs + function vote(address owner, address[] calldata _pools, uint256[] calldata _weights) external; + + /// @notice reset the vote of an address + /// @param owner address of the owner + function reset(address owner) external; + + /// @notice set the governor address + /// @param _governor the new governor address + function setGovernor(address _governor) external; + + /// @notice recover stuck emissions + /// @param _gauge the gauge address + /// @param _period the period + function stuckEmissionsRecovery(address _gauge, uint256 _period) external; + + /// @notice creates a legacy gauge for the pool + /// @param _pool pool's address + /// @return _gauge address of the new gauge + function createGauge(address _pool) external returns (address _gauge); + + /// @notice create a concentrated liquidity gauge + /// @param tokenA the address of tokenA + /// @param tokenB the address of tokenB + /// @param tickSpacing the tickspacing of the pool + /// @return _clGauge address of the new gauge + function createCLGauge(address tokenA, address tokenB, int24 tickSpacing) external returns (address _clGauge); + + /// @notice claim concentrated liquidity gauge rewards for specific NFP token ids + /// @param _gauges array of gauges + /// @param _tokens two dimensional array for the tokens to claim + /// @param _nfpTokenIds two dimensional array for the NFPs + function claimClGaugeRewards( + address[] calldata _gauges, + address[][] calldata _tokens, + uint256[][] calldata _nfpTokenIds + ) external; + + /// @notice claim arbitrary rewards from specific feeDists + /// @param owner address of the owner + /// @param _feeDistributors address of the feeDists + /// @param _tokens two dimensional array for the tokens to claim + function claimIncentives(address owner, address[] calldata _feeDistributors, address[][] calldata _tokens) + external; + + /// @notice claim arbitrary rewards from specific feeDists and break up legacy pairs + /// @param owner address of the owner + /// @param _feeDistributors address of the feeDists + /// @param _tokens two dimensional array for the tokens to claim + function claimLegacyIncentives(address owner, address[] calldata _feeDistributors, address[][] calldata _tokens) + external; + + /// @notice claim arbitrary rewards from specific gauges + /// @param _gauges address of the gauges + /// @param _tokens two dimensional array for the tokens to claim + function claimRewards(address[] calldata _gauges, address[][] calldata _tokens) external; + + /// @notice claim arbitrary rewards from specific legacy gauges, and exit to shadow + /// @param _gauges address of the gauges + /// @param _tokens two dimensional array for the tokens to claim + function claimLegacyRewardsAndExit(address[] calldata _gauges, address[][] calldata _tokens) external; + + /// @notice claim arbitrary rewards from specific cl gauges, and exit to shadow + /// @param _gauges address of the gauges + /// @param _tokens two dimensional array for the tokens to claim + /// @param _nfpTokenIds two dimensional array for the nfp to claim + function claimClGaugeRewardsAndExit( + address[] memory _gauges, + address[][] memory _tokens, + uint256[][] memory _nfpTokenIds + ) external; + + /// @notice distribute emissions to a gauge for a specific period + /// @param _gauge address of the gauge + /// @param _period value of the period + function distributeForPeriod(address _gauge, uint256 _period) external; + + /// @notice attempt distribution of emissions to all gauges + function distributeAll() external; + + /// @notice distribute emissions to gauges by index + /// @param startIndex start of the loop + /// @param endIndex end of the loop + function batchDistributeByIndex(uint256 startIndex, uint256 endIndex) external; + + /// @notice lets governance update lastDistro period for a gauge + /// @dev should only be used if distribute() is running out of gas + /// @dev gaugePeriodDistributed will stop double claiming + /// @param _gauge gauge to update + /// @param _period period to update to + function updateLastDistro(address _gauge, uint256 _period) external; + + /// @notice returns the votes cast for a tokenID + /// @param owner address of the owner + /// @return votes an array of votes casted + /// @return weights an array of the weights casted per pool + function getVotes(address owner, uint256 period) + external + view + returns (address[] memory votes, uint256[] memory weights); + + /// @notice returns an array of all the pools + /// @return _pools the array of pools + function getAllPools() external view returns (address[] memory _pools); + + /// @notice returns the length of pools + function getPoolsLength() external view returns (uint256); + + /// @notice returns the pool at index + function getPool(uint256 index) external view returns (address); + + /// @notice returns an array of all the gauges + /// @return _gauges the array of gauges + function getAllGauges() external view returns (address[] memory _gauges); + + /// @notice returns the length of gauges + function getGaugesLength() external view returns (uint256); + + /// @notice returns the gauge at index + function getGauge(uint256 index) external view returns (address); + + /// @notice returns an array of all the feeDists + /// @return _feeDistributors the array of feeDists + function getAllFeeDistributors() external view returns (address[] memory _feeDistributors); + + /// @notice sets the xShadowRatio default + function setGlobalRatio(uint256 _xRatio) external; + + /// @notice whether the token is whitelisted in governance + function isWhitelisted(address _token) external view returns (bool _tf); + + /// @notice function for removing malicious or stuffed tokens + function removeFeeDistributorReward(address _feeDist, address _token) external; + + /// @notice returns the total votes for a pool in a specific period + /// @param pool the pool address to check + /// @param period the period to check + /// @return votes the total votes for the pool in that period + function poolTotalVotesPerPeriod(address pool, uint256 period) external view returns (uint256 votes); + + /// @notice returns the pool address for a given gauge + /// @param gauge address of the gauge + /// @return pool address of the pool + function poolForGauge(address gauge) external view returns (address pool); + + /// @notice returns the pool address for a given feeDistributor + /// @param feeDistributor address of the feeDistributor + /// @return pool address of the pool + function poolForFeeDistributor(address feeDistributor) external view returns (address pool); + + /// @notice returns the voting power used by a voter for a period + /// @param user address of the user + /// @param period the period to check + function userVotingPowerPerPeriod(address user, uint256 period) external view returns (uint256 votingPower); + + /// @notice returns the total votes for a specific period + /// @param period the period to check + /// @return weight the total votes for that period + function totalVotesPerPeriod(uint256 period) external view returns (uint256 weight); + + /// @notice returns the total rewards allocated for a specific period + /// @param period the period to check + /// @return amount the total rewards for that period + function totalRewardPerPeriod(uint256 period) external view returns (uint256 amount); + + /// @notice returns the last distribution period for a gauge + /// @param _gauge address of the gauge + /// @return period the last period distributions occurred + function lastDistro(address _gauge) external view returns (uint256 period); + + /// @notice returns if the gauge is a Cl gauge + /// @param gauge the gauge to check + function isClGauge(address gauge) external view returns (bool); + + /// @notice returns if the gauge is a legacy gauge + /// @param gauge the gauge to check + function isLegacyGauge(address gauge) external view returns (bool); + + /// @notice sets a new NFP manager + function setNfpManager(address _nfpManager) external; + + /// @notice returns all voters for a period + function getAllVotersPerPeriod(uint256 period) external view returns (address[] memory); + + /// @notice returns the length of all voters for a period + function getAllVotersPerPeriodLength(uint256 period) external view returns (uint256); + + /// @notice returns voter at index for a period + function getAllVotersPerPeriodAt(uint256 period, uint256 index) external view returns (address); +} diff --git a/contracts/interfaces/external/shadow-cl/periphery/IPeripheryErrors.sol b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryErrors.sol new file mode 100644 index 0000000..572aff4 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryErrors.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Errors emitted by the NonFungiblePositionManager +/// @notice Contains all events emitted by the NfpManager +interface IPeripheryErrors { + error InvalidTokenId(uint256 tokenId); + error CheckSlippage(); + error NotCleared(); +} diff --git a/contracts/interfaces/external/shadow-cl/periphery/IPeripheryImmutableState.sol b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryImmutableState.sol new file mode 100644 index 0000000..e1c1df7 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryImmutableState.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Immutable state +/// @notice Functions that return immutable state of the router +interface IPeripheryImmutableState { + /// @return Returns the address of the Uniswap V3 deployer + function deployer() external view returns (address); + + /// @return Returns the address of WETH9 + function WETH9() external view returns (address); +} diff --git a/contracts/interfaces/external/shadow-cl/periphery/IPeripheryPayments.sol b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryPayments.sol new file mode 100644 index 0000000..ac74f8c --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/periphery/IPeripheryPayments.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.7.5; + +/// @title Periphery Payments +/// @notice Functions to ease deposits and withdrawals of ETH +interface IPeripheryPayments { + /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH. + /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users. + /// @param amountMinimum The minimum amount of WETH9 to unwrap + /// @param recipient The address receiving ETH + function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; + + /// @notice Refunds any ETH balance held by this contract to the `msg.sender` + /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps + /// that use ether for the input amount + function refundETH() external payable; + + /// @notice Transfers the full amount of a token held by this contract to recipient + /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users + /// @param token The contract address of the token which will be transferred to `recipient` + /// @param amountMinimum The minimum amount of token required for a transfer + /// @param recipient The destination address of the token + function sweepToken( + address token, + uint256 amountMinimum, + address recipient + ) external payable; +} diff --git a/contracts/interfaces/external/shadow-cl/periphery/IShadowCLNonfungiblePositionManager.sol b/contracts/interfaces/external/shadow-cl/periphery/IShadowCLNonfungiblePositionManager.sol new file mode 100644 index 0000000..d3b6b68 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/periphery/IShadowCLNonfungiblePositionManager.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.7.5; +pragma abicoder v2; + +import {IShadowPoolInitializer} from './IShadowPoolInitializer.sol'; +import {IPeripheryPayments} from './IPeripheryPayments.sol'; +import {IPeripheryImmutableState} from './IPeripheryImmutableState.sol'; +import {ShadowPoolAddress} from '../../../../libraries/ShadowPoolAddress.sol'; + +import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; +import {IERC721Metadata} from '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol'; +import {IERC721Enumerable} from '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol'; + +import {IPeripheryErrors} from './IPeripheryErrors.sol'; + +/// @title Non-fungible token for positions +/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred +/// and authorized. +interface IShadowCLNonfungiblePositionManager is + IPeripheryErrors, + IShadowPoolInitializer, + IPeripheryPayments, + IPeripheryImmutableState, + IERC721, + IERC721Metadata, + IERC721Enumerable +{ + /// @notice Emitted when liquidity is increased for a position NFT + /// @dev Also emitted when a token is minted + /// @param tokenId The ID of the token for which liquidity was increased + /// @param liquidity The amount by which liquidity for the NFT position was increased + /// @param amount0 The amount of token0 that was paid for the increase in liquidity + /// @param amount1 The amount of token1 that was paid for the increase in liquidity + event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); + /// @notice Emitted when liquidity is decreased for a position NFT + /// @param tokenId The ID of the token for which liquidity was decreased + /// @param liquidity The amount by which liquidity for the NFT position was decreased + /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity + /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity + event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); + /// @notice Emitted when tokens are collected for a position NFT + /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior + /// @param tokenId The ID of the token for which underlying tokens were collected + /// @param recipient The address of the account that received the collected tokens + /// @param amount0 The amount of token0 owed to the position that was collected + /// @param amount1 The amount of token1 owed to the position that was collected + event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1); + + /// @notice Returns the position information associated with a given token ID. + /// @dev Throws if the token ID is not valid. + /// @param tokenId The ID of the token that represents the position + /// @return token0 The address of the token0 for a specific pool + /// @return token1 The address of the token1 for a specific pool + /// @return tickSpacing The tickSpacing the pool + /// @return tickLower The lower end of the tick range for the position + /// @return tickUpper The higher end of the tick range for the position + /// @return liquidity The liquidity of the position + /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position + /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position + /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation + /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation + function positions( + uint256 tokenId + ) + external + view + returns ( + address token0, + address token1, + int24 tickSpacing, + int24 tickLower, + int24 tickUpper, + uint128 liquidity, + uint256 feeGrowthInside0LastX128, + uint256 feeGrowthInside1LastX128, + uint128 tokensOwed0, + uint128 tokensOwed1 + ); + + struct MintParams { + address token0; + address token1; + int24 tickSpacing; + int24 tickLower; + int24 tickUpper; + uint256 amount0Desired; + uint256 amount1Desired; + uint256 amount0Min; + uint256 amount1Min; + address recipient; + uint256 deadline; + } + + /// @notice Creates a new position wrapped in a NFT + /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized + /// a method does not exist, i.e. the pool is assumed to be initialized. + /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata + /// @return tokenId The ID of the token that represents the minted position + /// @return liquidity The amount of liquidity for this position + /// @return amount0 The amount of token0 + /// @return amount1 The amount of token1 + function mint( + MintParams calldata params + ) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); + + struct IncreaseLiquidityParams { + uint256 tokenId; + uint256 amount0Desired; + uint256 amount1Desired; + uint256 amount0Min; + uint256 amount1Min; + uint256 deadline; + } + + /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` + /// @param params tokenId The ID of the token for which liquidity is being increased, + /// amount0Desired The desired amount of token0 to be spent, + /// amount1Desired The desired amount of token1 to be spent, + /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, + /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, + /// deadline The time by which the transaction must be included to effect the change + /// @return liquidity The new liquidity amount as a result of the increase + /// @return amount0 The amount of token0 to acheive resulting liquidity + /// @return amount1 The amount of token1 to acheive resulting liquidity + function increaseLiquidity( + IncreaseLiquidityParams calldata params + ) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1); + + struct DecreaseLiquidityParams { + uint256 tokenId; + uint128 liquidity; + uint256 amount0Min; + uint256 amount1Min; + uint256 deadline; + } + + /// @notice Decreases the amount of liquidity in a position and accounts it to the position + /// @param params tokenId The ID of the token for which liquidity is being decreased, + /// amount The amount by which liquidity will be decreased, + /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, + /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, + /// deadline The time by which the transaction must be included to effect the change + /// @return amount0 The amount of token0 accounted to the position's tokens owed + /// @return amount1 The amount of token1 accounted to the position's tokens owed + function decreaseLiquidity( + DecreaseLiquidityParams calldata params + ) external payable returns (uint256 amount0, uint256 amount1); + + struct CollectParams { + uint256 tokenId; + address recipient; + uint128 amount0Max; + uint128 amount1Max; + } + + /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient + /// @param params tokenId The ID of the NFT for which tokens are being collected, + /// recipient The account that should receive the tokens, + /// amount0Max The maximum amount of token0 to collect, + /// amount1Max The maximum amount of token1 to collect + /// @return amount0 The amount of fees collected in token0 + /// @return amount1 The amount of fees collected in token1 + function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); + + /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens + /// must be collected first. + /// @param tokenId The ID of the token that is being burned + function burn(uint256 tokenId) external payable; + + /// @notice Claims gauge rewards from liquidity incentives for a specific tokenId + /// @param tokenId The ID of the token to claim rewards from + /// @param tokens an array of reward tokens to claim + function getReward(uint256 tokenId, address[] calldata tokens) external; +} diff --git a/contracts/interfaces/external/shadow-cl/periphery/IShadowPoolInitializer.sol b/contracts/interfaces/external/shadow-cl/periphery/IShadowPoolInitializer.sol new file mode 100644 index 0000000..7e9bd00 --- /dev/null +++ b/contracts/interfaces/external/shadow-cl/periphery/IShadowPoolInitializer.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.7.5; +pragma abicoder v2; + +/// @title Creates and initializes V3 Pools +/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that +/// require the pool to exist. +interface IShadowPoolInitializer { + /// @notice Creates a new pool if it does not exist, then initializes if not initialized + /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool + /// @param token0 The contract address of token0 of the pool + /// @param token1 The contract address of token1 of the pool + /// @param tickSpacing The tickSpacing of the v3 pool for the specified token pair + /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value + /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary + function createAndInitializePoolIfNecessary( + address token0, + address token1, + int24 tickSpacing, + uint160 sqrtPriceX96 + ) external payable returns (address pool); +} diff --git a/contracts/libraries/ShadowCallbackValidation.sol b/contracts/libraries/ShadowCallbackValidation.sol new file mode 100644 index 0000000..bdeb710 --- /dev/null +++ b/contracts/libraries/ShadowCallbackValidation.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +import '../interfaces/external/IRamsesV3Pool.sol'; +import './ShadowPoolAddress.sol'; + +/// @notice Provides validation for callbacks from Ramses V3 Pools +library ShadowCallbackValidation { + /// @notice Returns the address of a valid Ramses V3 Pool + /// @param deployer The contract address of the Ramses V3 deployer + /// @param tokenA The contract address of either token0 or token1 + /// @param tokenB The contract address of the other token + /// @param tickSpacing The tickSpacing of the pool + /// @return pool The V3 pool contract address + function verifyCallback( + address deployer, + address tokenA, + address tokenB, + int24 tickSpacing + ) internal view returns (IRamsesV3Pool pool) { + return verifyCallback(deployer, ShadowPoolAddress.getPoolKey(tokenA, tokenB, tickSpacing)); + } + + /// @notice Returns the address of a valid Ramses V3 Pool + /// @param deployer The contract address of the Ramses V3 deployer + /// @param poolKey The identifying key of the V3 pool + /// @return pool The V3 pool contract address + function verifyCallback( + address deployer, + ShadowPoolAddress.PoolKey memory poolKey + ) internal view returns (IRamsesV3Pool pool) { + pool = IRamsesV3Pool(ShadowPoolAddress.computeAddress(deployer, poolKey)); + require(msg.sender == address(pool)); + } +} diff --git a/contracts/libraries/ShadowPoolAddress.sol b/contracts/libraries/ShadowPoolAddress.sol new file mode 100644 index 0000000..c58dcfe --- /dev/null +++ b/contracts/libraries/ShadowPoolAddress.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Provides functions for deriving a pool address from the deployer, tokens, and the fee +library ShadowPoolAddress { + bytes32 internal constant POOL_INIT_CODE_HASH = 0xc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d; + + /// @notice The identifying key of the pool + struct PoolKey { + address token0; + address token1; + int24 tickSpacing; + } + + /// @notice Returns PoolKey: the ordered tokens with the matched fee levels + /// @param tokenA The first token of a pool, unsorted + /// @param tokenB The second token of a pool, unsorted + /// @param tickSpacing The tickSpacing of the pool + /// @return Poolkey The pool details with ordered token0 and token1 assignments + function getPoolKey(address tokenA, address tokenB, int24 tickSpacing) internal pure returns (PoolKey memory) { + if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); + return PoolKey({token0: tokenA, token1: tokenB, tickSpacing: tickSpacing}); + } + + /// @notice Deterministically computes the pool address given the deployer and PoolKey + /// @param deployer The Uniswap V3 deployer contract address + /// @param key The PoolKey + /// @return pool The contract address of the V3 pool + function computeAddress(address deployer, PoolKey memory key) internal pure returns (address pool) { + require(key.token0 < key.token1, "!TokenOrder"); + pool = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex'ff', + deployer, + keccak256(abi.encode(key.token0, key.token1, key.tickSpacing)), + POOL_INIT_CODE_HASH + ) + ) + ) + ) + ); + } +} diff --git a/contracts/libraries/ShadowPoolTicksCounter.sol b/contracts/libraries/ShadowPoolTicksCounter.sol new file mode 100644 index 0000000..f071c26 --- /dev/null +++ b/contracts/libraries/ShadowPoolTicksCounter.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.6.0; + +import '../interfaces/external/IRamsesV3Pool.sol'; + +library ShadowPoolTicksCounter { + /// @dev This function counts the number of initialized ticks that would incur a gas cost between tickBefore and tickAfter. + /// When tickBefore and/or tickAfter themselves are initialized, the logic over whether we should count them depends on the + /// direction of the swap. If we are swapping upwards (tickAfter > tickBefore) we don't want to count tickBefore but we do + /// want to count tickAfter. The opposite is true if we are swapping downwards. + function countInitializedTicksCrossed( + IRamsesV3Pool self, + int24 tickBefore, + int24 tickAfter + ) internal view returns (uint32 initializedTicksCrossed) { + int16 wordPosLower; + int16 wordPosHigher; + uint8 bitPosLower; + uint8 bitPosHigher; + bool tickBeforeInitialized; + bool tickAfterInitialized; + + { + /// @dev Get the key and offset in the tick bitmap of the active tick before and after the swap. + int16 wordPos = int16((tickBefore / self.tickSpacing()) >> 8); + uint8 bitPos = uint8(int8((tickBefore / self.tickSpacing()) % 256)); + + int16 wordPosAfter = int16((tickAfter / self.tickSpacing()) >> 8); + uint8 bitPosAfter = uint8(int8((tickAfter / self.tickSpacing()) % 256)); + + /// @dev In the case where tickAfter is initialized, we only want to count it if we are swapping downwards. + /// @dev If the initializable tick after the swap is initialized, our original tickAfter is a + /// @dev multiple of tick spacing, and we are swapping downwards we know that tickAfter is initialized + /// @dev and we shouldn't count it. + tickAfterInitialized = + ((self.tickBitmap(wordPosAfter) & (1 << bitPosAfter)) > 0) && + ((tickAfter % self.tickSpacing()) == 0) && + (tickBefore > tickAfter); + + /// @dev In the case where tickBefore is initialized, we only want to count it if we are swapping upwards. + /// @dev Use the same logic as above to decide whether we should count tickBefore or not. + tickBeforeInitialized = + ((self.tickBitmap(wordPos) & (1 << bitPos)) > 0) && + ((tickBefore % self.tickSpacing()) == 0) && + (tickBefore < tickAfter); + + if (wordPos < wordPosAfter || (wordPos == wordPosAfter && bitPos <= bitPosAfter)) { + wordPosLower = wordPos; + bitPosLower = bitPos; + wordPosHigher = wordPosAfter; + bitPosHigher = bitPosAfter; + } else { + wordPosLower = wordPosAfter; + bitPosLower = bitPosAfter; + wordPosHigher = wordPos; + bitPosHigher = bitPos; + } + } + + /// @dev Count the number of initialized ticks crossed by iterating through the tick bitmap. + /// @dev Our first mask should include the lower tick and everything to its left. + uint256 mask = type(uint256).max << bitPosLower; + while (wordPosLower <= wordPosHigher) { + /// @dev If we're on the final tick bitmap page, ensure we only count up to our + /// @dev ending tick. + if (wordPosLower == wordPosHigher) { + mask = mask & (type(uint256).max >> (255 - bitPosHigher)); + } + + uint256 masked = self.tickBitmap(wordPosLower) & mask; + initializedTicksCrossed += countOneBits(masked); + wordPosLower++; + /// @dev Reset our mask so we consider all bits on the next iteration. + mask = type(uint256).max; + } + + if (tickAfterInitialized) { + initializedTicksCrossed -= 1; + } + + if (tickBeforeInitialized) { + initializedTicksCrossed -= 1; + } + + return initializedTicksCrossed; + } + + function countOneBits(uint256 x) private pure returns (uint16) { + uint16 bits = 0; + while (x != 0) { + bits++; + x &= (x - 1); + } + return bits; + } +} diff --git a/contracts/routes/ShadowCL.sol b/contracts/routes/ShadowCL.sol new file mode 100644 index 0000000..8ab13bf --- /dev/null +++ b/contracts/routes/ShadowCL.sol @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.8.0; + +import '@gammaswap/v1-core/contracts/libraries/GSMath.sol'; +import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; +import '@uniswap/v3-core/contracts/libraries/SafeCast.sol'; +import '../interfaces/IProtocolRoute.sol'; +import '../interfaces/external/IRamsesV3Pool.sol'; +import '../interfaces/external/IRamsesV3Factory.sol'; +import '../libraries/ShadowCallbackValidation.sol'; +import '../libraries/ShadowPoolAddress.sol'; +import '../libraries/ShadowPoolTicksCounter.sol'; +import '../libraries/BytesLib2.sol'; +import '../libraries/Path2.sol'; +import '../libraries/TickMath.sol'; +import './CPMMRoute.sol'; + +contract ShadowCL is CPMMRoute, IUniswapV3SwapCallback { + using BytesLib2 for bytes; + using Path2 for bytes; + using ShadowPoolTicksCounter for IRamsesV3Pool; + using SafeCast for uint256; + + struct SwapCallbackData { + bytes path; + address payer; + } + + struct SwapParams { + address tokenIn; + address tokenOut; + uint24 tickSpacing; + uint256 amount; + address recipient; + } + + uint256 private amountOutCached; + + constructor(uint16 _protocolId, address _factory, address _WETH) Transfers(_WETH) { + protocolId = _protocolId; + factory = _factory; // this is the ramsesV3PoolDeployer + } + + function quote(uint256 amountIn, address tokenIn, address tokenOut, uint24 fee) public override view returns (uint256 amountOut) { + (uint256 sqrtPriceX96,,,,,,) = IRamsesV3Pool(_pairFor(tokenIn, tokenOut, fee)).slot0(); + if (tokenIn < tokenOut) { + uint256 decimals = 10**GammaSwapLibrary.decimals(tokenIn); + uint256 price = decodePrice(sqrtPriceX96, decimals); + amountOut = amountIn * price / decimals; + } else { + uint256 decimals = 10**GammaSwapLibrary.decimals(tokenOut); + uint256 price = decodePrice(sqrtPriceX96, decimals); + amountOut = price == 0 ? type(uint128).max : amountIn * decimals / price; + } + } + + function getFee(address tokenIn, address tokenOut, uint24 fee) external override view returns (uint256) { + (address pair,,) = pairFor(tokenIn, tokenOut, fee); + return IRamsesV3Pool(pair).fee(); + } + + function decodePrice(uint256 sqrtPriceX96, uint256 decimals) internal pure returns (uint256 price) { + uint256 sqrtPrice = sqrtPriceX96 * GSMath.sqrt(decimals) / (2**96); + price = sqrtPrice * sqrtPrice; + } + + function pairFor(address tokenA, address tokenB, uint24 fee) public override view returns (address pair, address token0, address token1) { + int24 tickSpacing = int24(fee); + (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); + pair = ShadowPoolAddress.computeAddress(factory, ShadowPoolAddress.PoolKey({token0: token0, token1: token1, tickSpacing: tickSpacing})); + require(GammaSwapLibrary.isContract(pair), 'ShadowCL: AMM_DOES_NOT_EXIST'); + } + + function _pairFor(address token0, address token1, uint24 fee) internal view returns (address pair) { + (pair,,) = pairFor(token0, token1, fee); + } + + function getOrigin(address tokenA, address tokenB, uint24 fee) external override view returns (address pair, address origin) { + (pair,,) = pairFor(tokenA, tokenB, fee); + origin = address(this); + } + + function getAmountOut(uint256 amountIn, address tokenIn, address tokenOut, uint256 fee) public override returns (uint256 amountOut, address pair, uint24 swapFee) { + swapFee = uint24(fee); + (amountOut, pair) = _quoteAmountOut(amountIn, tokenIn, tokenOut, swapFee); + } + + function _quoteAmountOut(uint256 amountIn, address tokenIn, address tokenOut, uint24 fee) internal returns (uint256 amountOut, address pair) { + bool zeroForOne = tokenIn < tokenOut; + (pair,,) = pairFor(tokenIn, tokenOut, fee); + try IRamsesV3Pool(pair).swap( + address(this), + zeroForOne, + amountIn.toInt256(), + zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1, + abi.encode(SwapCallbackData({path: abi.encodePacked(tokenIn, protocolId, fee, tokenOut), payer: address(0)})) + ) {} catch (bytes memory reason) { + (amountOut,,) = handleRevert(reason, pair); + } + } + + function getAmountIn(uint256 amountOut, address tokenIn, address tokenOut, uint256 fee) public override returns (uint256 amountIn, address pair, uint24 swapFee) { + swapFee = uint24(fee); + (amountIn, pair) = _quoteAmountIn(amountOut, tokenIn, tokenOut, swapFee); + } + + function _quoteAmountIn(uint256 amountOut, address tokenIn, address tokenOut, uint24 fee) internal returns (uint256 amountIn, address pair) { + (pair,,) = pairFor(tokenIn, tokenOut, fee); + amountOutCached = amountOut; + try IRamsesV3Pool(pair).swap( + address(this), + tokenIn < tokenOut, + -amountOut.toInt256(), + tokenIn < tokenOut ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1, + abi.encode(SwapCallbackData({path: abi.encodePacked(tokenOut, protocolId, fee, tokenIn), payer: address(0)})) + ) {} catch (bytes memory reason) { + delete amountOutCached; + (amountIn,,) = handleRevert(reason, pair); + } + } + + function handleRevert(bytes memory reason, address pair) private view returns (uint256 amount, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed) { + int24 tickBefore; + int24 tickAfter; + (,tickBefore,,,,,) = IRamsesV3Pool(pair).slot0(); + (amount, sqrtPriceX96After, tickAfter) = parseRevertReason(reason); + initializedTicksCrossed = IRamsesV3Pool(pair).countInitializedTicksCrossed(tickBefore, tickAfter); + } + + function parseRevertReason(bytes memory reason) private pure returns (uint256 amount, uint160 sqrtPriceX96After, int24 tickAfter) { + if (reason.length != 96) { + if (reason.length < 68) revert('Unexpected error'); + assembly { reason := add(reason, 0x04) } + revert(abi.decode(reason, (string))); + } + return abi.decode(reason, (uint256, uint160, int24)); + } + + function swap(address from, address to, uint24 fee, address dest) external override { + uint256 inputAmount = GammaSwapLibrary.balanceOf(from, address(this)); + require(inputAmount > 0, 'ZERO_AMOUNT'); + + exactInputSwap(SwapParams({ + tokenIn: from, + tokenOut: to, + tickSpacing: fee, + amount: inputAmount, + recipient: dest + })); + } + + function exactInputSwap(SwapParams memory params) private returns (uint256) { + require(params.amount < 2**255, 'INVALID_AMOUNT'); + require(params.recipient != address(0), 'INVALID_RECIPIENT'); + + bool zeroForOne = params.tokenIn < params.tokenOut; + (int256 amount0, int256 amount1) = IRamsesV3Pool(_pairFor(params.tokenIn, params.tokenOut, params.tickSpacing)).swap( + params.recipient, + zeroForOne, + int256(params.amount), + (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1), + abi.encode(SwapCallbackData({path: abi.encodePacked(params.tokenIn, protocolId, params.tickSpacing, params.tokenOut), payer: address(this)})) + ); + + return uint256(-(zeroForOne ? amount1 : amount0)); + } + + function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes memory _data) external override { + require(amount0Delta > 0 || amount1Delta > 0); + SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData)); + (address tokenIn, address tokenOut,, uint24 fee) = data.path.decodeFirstPool(); + ShadowCallbackValidation.verifyCallback(factory, tokenIn, tokenOut, int24(fee)); + + (bool isExactInput, uint256 amountToPay, uint256 amountReceived) = amount0Delta > 0 + ? (tokenIn < tokenOut, uint256(amount0Delta), uint256(-amount1Delta)) + : (tokenOut < tokenIn, uint256(amount1Delta), uint256(-amount0Delta)); + + (uint160 sqrtPriceX96After, int24 tickAfter,,,,,) = IRamsesV3Pool(_pairFor(tokenIn, tokenOut, fee)).slot0(); + + if (isExactInput) { + if (data.payer != address(0)) { + send(tokenIn, data.payer, msg.sender, amountToPay); + } else { + assembly { + let ptr := mload(0x40) + mstore(ptr, amountReceived) + mstore(add(ptr, 0x20), sqrtPriceX96After) + mstore(add(ptr, 0x40), tickAfter) + revert(ptr, 96) + } + } + } else { + if (amountOutCached != 0) require(amountReceived == amountOutCached); + assembly { + let ptr := mload(0x40) + mstore(ptr, amountToPay) + mstore(add(ptr, 0x20), sqrtPriceX96After) + mstore(add(ptr, 0x40), tickAfter) + revert(ptr, 96) + } + } + } +} diff --git a/contracts/test/IShadowCLPositionManagerMintable.sol b/contracts/test/IShadowCLPositionManagerMintable.sol new file mode 100644 index 0000000..17500be --- /dev/null +++ b/contracts/test/IShadowCLPositionManagerMintable.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +interface IShadowCLPositionManagerMintable { + struct MintParams { + address token0; + address token1; + int24 tickSpacing; + int24 tickLower; + int24 tickUpper; + uint256 amount0Desired; + uint256 amount1Desired; + uint256 amount0Min; + uint256 amount1Min; + address recipient; + uint256 deadline; + } + + function mint( + MintParams calldata params + ) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); +} \ No newline at end of file diff --git a/contracts/test/routes/TestShadowCL.sol b/contracts/test/routes/TestShadowCL.sol new file mode 100644 index 0000000..98e6e3c --- /dev/null +++ b/contracts/test/routes/TestShadowCL.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.8.0; + +import '../../routes/ShadowCL.sol'; + +contract TestShadowCL is ShadowCL { + constructor(uint16 _protocolId, address _factory, address _WETH) + ShadowCL(_protocolId, _factory, _WETH) {} + + function getPairFor(address tokenA, address tokenB, int24 tickSpacing) public view returns (address pair) { + (pair,,) = pairFor(tokenA, tokenB, uint24(tickSpacing)); + } + + function getDecodedPrice(uint256 sqrtPriceX96, uint256 decimals) public pure returns (uint256 price) { + return decodePrice(sqrtPriceX96, decimals); + } +} diff --git a/test/foundry/UniversalRouterTest.t.sol b/test/foundry/UniversalRouterTest.t.sol index 460f907..8f75c1a 100644 --- a/test/foundry/UniversalRouterTest.t.sol +++ b/test/foundry/UniversalRouterTest.t.sol @@ -7,6 +7,7 @@ import '../../contracts/routes/DeltaSwap.sol'; import '../../contracts/routes/Aerodrome.sol'; import '../../contracts/routes/UniswapV3.sol'; import '../../contracts/routes/AerodromeCL.sol'; +import '../../contracts/routes/ShadowCL.sol'; import "../../contracts/interfaces/IRouterExternalCallee.sol"; import '../../contracts/interfaces/IUniversalRouter.sol'; import './fixtures/TestBed.sol'; @@ -25,6 +26,7 @@ contract UniversalRouterTest is TestBed { Aerodrome aeroStableRoute; UniswapV3 uniV3Route; AerodromeCL aeroCLRoute; + ShadowCL shadowCLRoute; Random random; address[] tokens; @@ -64,6 +66,7 @@ contract UniversalRouterTest is TestBed { aeroStableRoute = new Aerodrome(5, address(aeroFactory), true, address(weth)); uniV3Route = new UniswapV3(6, address(uniFactoryV3), address(weth)); aeroCLRoute = new AerodromeCL(7, address(aeroCLFactory), address(weth)); + shadowCLRoute = new ShadowCL(8, address(shadowCLPoolDeployer), address(weth)); // set up routes router.addProtocolRoute(address(uniV2Route)); @@ -73,6 +76,7 @@ contract UniversalRouterTest is TestBed { router.addProtocolRoute(address(aeroStableRoute)); router.addProtocolRoute(address(uniV3Route)); router.addProtocolRoute(address(aeroCLRoute)); + router.addProtocolRoute(address(shadowCLRoute)); } function testAddRemoveProtocol() public { @@ -437,6 +441,8 @@ contract UniversalRouterTest is TestBed { return uniFactoryV3.getPool(from, to, fee); } else if(protocolId == 7) { return aeroCLFactory.getPool(from, to, int24(fee)); + } else if(protocolId == 8) { + return shadowCLFactory.getPool(from, to, int24(shadowCLTickSpacing)); } return address(0); } @@ -456,6 +462,8 @@ contract UniversalRouterTest is TestBed { return address(uniFactoryV3); } else if(protocolId == 7) { return address(aeroCLFactory); + } else if(protocolId == 8) { + return address(shadowCLFactory); } return address(0); } @@ -787,8 +795,8 @@ contract UniversalRouterTest is TestBed { } function testGetPairInfo() public { - for(uint16 protocolId = 1; protocolId < 8; protocolId++) { - uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : 0; + for(uint16 protocolId = 1; protocolId < 9; protocolId++) { + uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : protocolId == 8 ? uint24(shadowCLTickSpacing) : 0; (address token0, address token1) = protocolId == 5 ? (address(usdc), address(usdt)) : (address(weth), address(usdc)); (address _pair0,,,address _factory0) = router.getPairInfo(token0, token1, _poolFee, protocolId); (address _pair1,,,address _factory1) = router.getPairInfo(token1, token0, _poolFee, protocolId); @@ -801,8 +809,8 @@ contract UniversalRouterTest is TestBed { function testTrackPair0() public { assertEq(router.owner(), address(this)); - for(uint16 protocolId = 1; protocolId < 8; protocolId++) { - uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : 0; + for(uint16 protocolId = 1; protocolId < 9; protocolId++) { + uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : protocolId == 8 ? uint24(shadowCLTickSpacing) : 0; (address token0, address token1) = protocolId == 5 ? (address(usdc), address(usdt)) : (address(weth), address(usdc)); (address pair, address _token0, address _token1, address _factory) = router.getPairInfo(token0, token1, _poolFee, protocolId); @@ -827,8 +835,8 @@ contract UniversalRouterTest is TestBed { assertEq(router.trackedPairs(pair), block.timestamp); } - for(uint16 protocolId = 1; protocolId < 8; protocolId++) { - uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : 0; + for(uint16 protocolId = 1; protocolId < 9; protocolId++) { + uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : protocolId == 8 ? uint24(shadowCLTickSpacing) : 0; (address token0, address token1) = protocolId == 5 ? (address(usdc), address(usdt)) : (address(weth), address(usdc)); (address pair, address _token0, address _token1, address _factory) = router.getPairInfo(token0, token1, _poolFee, protocolId); @@ -856,8 +864,8 @@ contract UniversalRouterTest is TestBed { function testTrackPair1() public { assertEq(router.owner(), address(this)); - for(uint16 protocolId = 1; protocolId < 8; protocolId++) { - uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : 0; + for(uint16 protocolId = 1; protocolId < 9; protocolId++) { + uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : protocolId == 8 ? uint24(shadowCLTickSpacing) : 0; (address token0, address token1) = protocolId == 5 ? (address(usdt), address(usdc)) : (address(usdc), address(weth)); (address pair, address _token0, address _token1, address _factory) = router.getPairInfo(token0, token1, _poolFee, protocolId); @@ -882,8 +890,8 @@ contract UniversalRouterTest is TestBed { assertEq(router.trackedPairs(pair), block.timestamp); } - for(uint16 protocolId = 1; protocolId < 8; protocolId++) { - uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : 0; + for(uint16 protocolId = 1; protocolId < 9; protocolId++) { + uint24 _poolFee = protocolId == 6 ? poolFee1 : protocolId == 7 ? uint24(aeroCLTickSpacing) : protocolId == 8 ? uint24(shadowCLTickSpacing) : 0; (address token0, address token1) = protocolId == 5 ? (address(usdt), address(usdc)) : (address(usdc), address(weth)); (address pair, address _token0, address _token1, address _factory) = router.getPairInfo(token0, token1, _poolFee, protocolId); diff --git a/test/foundry/bytecodes/shadow-cl/AccessHub.json b/test/foundry/bytecodes/shadow-cl/AccessHub.json new file mode 100644 index 0000000..d9ff120 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/AccessHub.json @@ -0,0 +1,3 @@ +{ + "bytecode": "6080604052348015600e575f5ffd5b506117328061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106107ae575f3560e01c806380a1ebbb116103f3578063bb511b5e11610213578063d547741f1161012e578063ed4f9a03116100c1578063f4c0081111610090578063f4c0081114610824578063f7553c521461089e578063fa55c8c5146109f5578063fc07a588146107fc578063febf892214610a1f576107ae565b8063ed4f9a0314610824578063eee0fdb414610a11578063efe57a2814610824578063f0f4426014610811576107ae565b8063e6dca2b2116100fd578063e6dca2b214610811578063e74710db14610882578063e95245fd14610811578063eb49215014610992576107ae565b8063d547741f146108fc578063dbb466df146109f5578063dea9776814610811578063df9a29a614610849576107ae565b8063c43faec2116101a6578063ca62573a11610175578063ca62573a14610a03578063d2d9520014610954578063d32af6c114610824578063d33219b414610824576107ae565b8063c43faec2146109e7578063c5f720e414610824578063c9d068fd14610811578063ca15c873146108bf576107ae565b8063c14a6c2f116101e2578063c14a6c2f14610954578063c1ba705814610824578063c1ea4cea14610890578063c415b95c14610824576107ae565b8063bb511b5e14610811578063be02ec38146107fc578063beb7dc3414610849578063c1463c15146109a8576107ae565b806398bbc3c71161030e578063ab0e0192116102a1578063b7ddd88511610270578063b7ddd885146108e0578063b7f02128146109f5578063b890ebf6146108e0578063b94ef2b814610824578063ba013510146108e0576107ae565b8063ab0e019214610811578063b0f2f7e5146109f5578063b5fd14b114610811578063b7923cd01461089e576107ae565b8063a217fddf116102dd578063a217fddf14610992578063a4586d83146109e7578063a56bcb4c14610882578063a71504ad146108e0576107ae565b806398bbc3c7146108245780639987e757146108115780639a17759b146108245780639e3dc42d14610811576107ae565b8063902910581161038657806391d148541161035557806391d14854146109c957806393208a2b1461082457806395117d3f146108245780639647d14114610824576107ae565b8063902910581461092a57806390bcc5a2146107fc57806391742be01461084957806391c168a514610954576107ae565b806385caf28b116103c257806385caf28b14610824578063895f279c146109a85780638cb422f0146109925780639010d07c146109b6576107ae565b806380a1ebbb1461084957806382169aec14610849578063839006f21461081157806383c3712914610890576107ae565b8063456f3079116105de57806361ff374b116104f957806374dd07b61161048c5780637bebe3811161045b5780637bebe381146108245780637c972e2e146108495780637f63feb8146108245780637fe1dc3f146108115780638019b6b71461099a576107ae565b806374dd07b614610824578063750520781461095457806378b1a8c7146109925780637a707730146108e0576107ae565b806369e0bc05116104c857806369e0bc05146108495780636ded527f146108115780636e57f00e146108115780637121392d14610984576107ae565b806361ff374b146109545780636379808f14610811578063649b80ff1461095c578063687b0135146108e0576107ae565b8063523af7c1116105715780635b083d4c116105405780635b083d4c146108115780635cb62a08146108e05780635cb76f621461081157806361d027b314610824576107ae565b8063523af7c1146108e05780635261aef3146108ee57806352e0970f14610811578063553fcea414610946576107ae565b80634b9880c1116105ad5780634b9880c1146108e05780634cb4d827146108495780634d4ce1c11461092a5780634e7267c214610938576107ae565b8063456f30791461081157806346c96aac1461082457806347f377b81461081157806349fe822814610811576107ae565b80631f2d0329116106ce57806336568abe116106615780634135afbe116106305780634135afbe146108115780634219dc40146108245780634256f5e7146108245780634345f59a14610849576107ae565b806336568abe146108fc5780633928ca761461090a5780633abdbf2a146108115780633eadd56e146108e0576107ae565b80632ea4e5db1161069d5780632ea4e5db146108ee5780632f2ff15d146108fc578063315cfc2814610824578063320e684014610811576107ae565b80631f2d0329146107fc578063248a9ca3146108bf57806327ef1fa3146108115780632a59c806146108e0576107ae565b80630c2e061f1161074657806316358806116107155780631635880614610811578063177af2c5146108905780631cff79cd1461089e5780631eadbd8b146108b1576107ae565b80630c2e061f146108825780630d52333c146108245780631050f077146107fc5780631344390114610824576107ae565b806308cedcde1161078257806308cedcde146108115780630952c8ee1461085c578063095958721461082457806309651f7d1461086f576107ae565b80620c07c7146107fc57806302be9a90146108115780630754617214610824578063083eebfc14610849575b5f3660606107f083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610a3492505050565b80519350602001915050f35b61080f61080a366004610ed0565b610b56565b005b61080f61081f366004610f36565b610b7d565b61082c610ba3565b6040516001600160a01b0390911681526020015b60405180910390f35b61080f610857366004610f51565b610bcb565b61080f61086a366004610fbd565b610bf4565b61080f61087d36600461103f565b610c1e565b61080f61080a3660046110de565b61080f61080a3660046111d1565b61080f6108ac36600461125c565b610c49565b61080f61080a3660046112bc565b6108d26108cd3660046112ef565b610c71565b604051908152602001610840565b61080f61081f3660046112ef565b61080f61081f366004611306565b61080f61080a366004611320565b61091d61091836600461134e565b610a34565b6040516108409190611388565b61080f61081f3660046113bd565b61080f6108573660046113d6565b61082c6108cd3660046112ef565b61080f610c9b565b61096f61096a366004610f36565b610cc0565b60408051928352602083019190915201610840565b61080f61081f36600461143a565b6108d2610ba3565b61080f61080a366004611550565b61080f6108ac366004611570565b61082c6109c4366004611550565b610ceb565b6109d76109c4366004611320565b6040519015158152602001610840565b61080f6108ac3660046115af565b61080f61080a3660046115ec565b61080f61081f366004611618565b61080f61080a366004611638565b610a27610d16565b6040516108409190611670565b60607fd3433e2ecf019e7839d3fa6d20b123561a6ea91df0afa4cf6f2c4f62a69852105f610a6182610d3b565b90505f5b81811015610b3c575f80610a798584610d4a565b6001600160a01b031687604051610a9091906116bb565b5f60405180830381855af49150503d805f8114610ac8576040519150601f19603f3d011682016040523d82523d5f602084013e610acd565b606091505b509150915081610adf573d5f5f3e3d5ffd5b80516020141580610b2557507fa38b45c70495df5d1b49c0fdebe350e18f9fee4fe88a50a904eca9e5b46cca805f1b81806020019051810190610b2291906116d1565b14155b15610b32573d5f5f3e3d5ff35b5050600101610a65565b5060405163c1e07e6560e01b815260040160405180910390fd5b604051368082525f60208301373660405101602001604052610b7781610a34565b50505050565b604051368082525f60208301373660405101602001604052610b9e81610a34565b505050565b604051368082525f91908260208301373660405101602001604052610bc781610d5c565b5090565b604051368082525f60208301373660405101602001604052610bec81610a34565b505050505050565b604051368082525f60208301373660405101602001604052610c1581610a34565b50505050505050565b604051368082525f60208301373660405101602001604052610c3f81610a34565b5050505050505050565b604051368082525f60208301373660405101602001604052610c6a81610a34565b5050505050565b604051368082525f91908260208301373660405101602001604052610c9581610d5c565b50919050565b604051368082525f60208301373660405101602001604052610cbc81610a34565b5050565b604051368082525f9182918260208301373660405101602001604052610ce581610d5c565b50915091565b604051368082525f91908260208301373660405101602001604052610d0f81610d5c565b5092915050565b60405136808252606091905f60208301373660405101602001604052610bc781610d5c565b5f610d44825490565b92915050565b5f610d558383610e62565b9392505050565b5f5f306001600160a01b0316306001600160a01b0316633928ca7685604051602401610d889190611388565b60408051601f198184030181529181526020820180516001600160e01b031660e09490941b939093179092529051610dc092506116bb565b5f60405180830381855afa9150503d805f8114610df8576040519150601f19603f3d011682016040523d82523d5f602084013e610dfd565b606091505b509150915081610e0f573d5f5f3e3d5ffd5b80516020141580610e5557507fa38b45c70495df5d1b49c0fdebe350e18f9fee4fe88a50a904eca9e5b46cca805f1b81806020019051810190610e5291906116d1565b14155b15610b9e573d5f5f3e3d5ff35b5f825f018281548110610e7757610e776116e8565b905f5260205f200154905092915050565b5f5f83601f840112610e98575f5ffd5b50813567ffffffffffffffff811115610eaf575f5ffd5b6020830191508360208260051b8501011115610ec9575f5ffd5b9250929050565b5f5f60208385031215610ee1575f5ffd5b823567ffffffffffffffff811115610ef7575f5ffd5b610f0385828601610e88565b90969095509350505050565b6001600160a01b0381168114610f23575f5ffd5b50565b8035610f3181610f0f565b919050565b5f60208284031215610f46575f5ffd5b8135610d5581610f0f565b5f5f5f5f60408587031215610f64575f5ffd5b843567ffffffffffffffff811115610f7a575f5ffd5b610f8687828801610e88565b909550935050602085013567ffffffffffffffff811115610fa5575f5ffd5b610fb187828801610e88565b95989497509550505050565b5f5f5f5f5f60608688031215610fd1575f5ffd5b8535610fdc81610f0f565b9450602086013567ffffffffffffffff811115610ff7575f5ffd5b61100388828901610e88565b909550935050604086013567ffffffffffffffff811115611022575f5ffd5b61102e88828901610e88565b969995985093965092949392505050565b5f5f5f5f5f5f60608789031215611054575f5ffd5b863567ffffffffffffffff81111561106a575f5ffd5b61107689828a01610e88565b909750955050602087013567ffffffffffffffff811115611095575f5ffd5b6110a189828a01610e88565b909550935050604087013567ffffffffffffffff8111156110c0575f5ffd5b6110cc89828a01610e88565b979a9699509497509295939492505050565b5f5f604083850312156110ef575f5ffd5b82356110fa81610f0f565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516101c0810167ffffffffffffffff8111828210171561114057611140611108565b60405290565b5f82601f830112611155575f5ffd5b813567ffffffffffffffff81111561116f5761116f611108565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561119e5761119e611108565b6040528181528382016020018510156111b5575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156111e2575f5ffd5b82356111ed81610f0f565b9150602083013567ffffffffffffffff811115611208575f5ffd5b61121485828601611146565b9150509250929050565b5f5f83601f84011261122e575f5ffd5b50813567ffffffffffffffff811115611245575f5ffd5b602083019150836020828501011115610ec9575f5ffd5b5f5f5f6040848603121561126e575f5ffd5b833561127981610f0f565b9250602084013567ffffffffffffffff811115611294575f5ffd5b6112a08682870161121e565b9497909650939450505050565b80358015158114610f31575f5ffd5b5f5f604083850312156112cd575f5ffd5b82356112d881610f0f565b91506112e6602084016112ad565b90509250929050565b5f602082840312156112ff575f5ffd5b5035919050565b5f610200828403128015611318575f5ffd5b509092915050565b5f5f60408385031215611331575f5ffd5b82359150602083013561134381610f0f565b809150509250929050565b5f6020828403121561135e575f5ffd5b813567ffffffffffffffff811115611374575f5ffd5b61138084828501611146565b949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f602082840312156113cd575f5ffd5b610d55826112ad565b5f5f5f5f606085870312156113e9575f5ffd5b84356113f481610f0f565b9350602085013567ffffffffffffffff81111561140f575f5ffd5b61141b87828801610e88565b909450925050604085013561142f81610f0f565b939692955090935050565b5f6101c082840312801561144c575f5ffd5b5061145561111c565b61145e83610f26565b815261146c60208401610f26565b602082015261147d60408401610f26565b604082015261148e60608401610f26565b606082015261149f60808401610f26565b60808201526114b060a08401610f26565b60a08201526114c160c08401610f26565b60c08201526114d260e08401610f26565b60e08201526114e46101008401610f26565b6101008201526114f76101208401610f26565b61012082015261150a6101408401610f26565b61014082015261151d6101608401610f26565b6101608201526115306101808401610f26565b6101808201526115436101a08401610f26565b6101a08201529392505050565b5f5f60408385031215611561575f5ffd5b50508035926020909101359150565b5f5f5f60608486031215611582575f5ffd5b833561158d81610f0f565b92506020840135915060408401356115a481610f0f565b809150509250925092565b5f5f5f606084860312156115c1575f5ffd5b83356115cc81610f0f565b925060208401356115dc81610f0f565b915060408401356115a481610f0f565b5f5f604083850312156115fd575f5ffd5b823561160881610f0f565b9150602083013561134381610f0f565b5f60208284031215611628575f5ffd5b813560ff81168114610d55575f5ffd5b5f5f60408385031215611649575f5ffd5b82358060020b8114611659575f5ffd5b9150602083013562ffffff81168114611343575f5ffd5b602080825282518282018190525f918401906040840190835b818110156116b05783516001600160a01b0316835260209384019390920191600101611689565b509095945050505050565b5f82518060208501845e5f920191825250919050565b5f602082840312156116e1575f5ffd5b5051919050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220a2b0c78bbff807b5c7434fbfcfb6d53cd97b5193c596c820539544f366a2d2b964736f6c634300081c0033" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/CLGaugeFactory.json b/test/foundry/bytecodes/shadow-cl/CLGaugeFactory.json new file mode 100644 index 0000000..ece02dd --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/CLGaugeFactory.json @@ -0,0 +1,3 @@ +{ + "bytecode": "6080604052348015600e575f5ffd5b50604051615fff380380615fff833981016040819052602b916085565b600280546001600160a01b039485166001600160a01b0319918216179091555f8054938516938216939093179092556001805491909316911617905560be565b80516001600160a01b03811681146080575f5ffd5b919050565b5f5f5f606084860312156096575f5ffd5b609d84606b565b925060a960208501606b565b915060b560408501606b565b90509250925092565b615f34806100cb5f395ff3fe608060405234801561000f575f5ffd5b506004361061009b575f3560e01c8063a42dce8011610063578063a42dce801461011b578063a5f4301e1461012e578063b1c6f0e914610141578063c415b95c14610169578063d784d4261461017c575f5ffd5b8063320e68401461009f57806346c96aac146100b45780634bc2a657146100e25780635c60da1b146100f557806398bbc3c714610108575b5f5ffd5b6100b26100ad366004610811565b61018f565b005b5f546100c6906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6100b26100f0366004610811565b610229565b6003546100c6906001600160a01b031681565b6002546100c6906001600160a01b031681565b6100b2610129366004610811565b61032d565b6100c661013c366004610811565b610433565b6100c661014f366004610811565b60046020525f90815260409020546001600160a01b031681565b6001546100c6906001600160a01b031681565b6100b261018a366004610811565b6106da565b5f5433906001600160a01b031681146101cc57604051632bc10c3360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b506002546040516001600160a01b03918216918316907f91b28bee5dc86f5ce41c22a3057286afb3358d566c69a2a3bb4294bdb754c560905f90a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b5f5f9054906101000a90046001600160a01b03166001600160a01b031663e7589b396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610278573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029c9190610833565b33906001600160a01b031681146102d257604051632bc10c3360e01b81526001600160a01b0390911660048201526024016101c3565b505f80546040516001600160a01b0391821692918416917fcdd5998a5de8d7c793ad6455c4ee5a5498fe1c7e483acb0efd9974d1fa816f2d91a35f80546001600160a01b0319166001600160a01b0392909216919091179055565b5f5f9054906101000a90046001600160a01b03166001600160a01b031663e7589b396040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a09190610833565b33906001600160a01b031681146103d657604051632bc10c3360e01b81526001600160a01b0390911660048201526024016101c3565b506001546040516001600160a01b03918216918316907f649c5e3d0ed183894196148e193af316452b0037e77d2ff0fef23b7dc722bed0905f90a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f805433906001600160a01b0316811461046c57604051632bc10c3360e01b81526001600160a01b0390911660048201526024016101c3565b506001600160a01b038281165f90815260046020526040902054839116156104b35760405163e0ad9f6b60e01b81526001600160a01b0390911660048201526024016101c3565b506003546001600160a01b03166105f1575f805460408051632b18028f60e21b815290516001600160a01b039092169163ac600a3c916004808201926020929091908290030181865afa15801561050c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105309190610833565b6001600160a01b031603610557576040516359b186bf60e11b815260040160405180910390fd5b5f546001546040516001600160a01b039283169290911690610578906107e3565b6001600160a01b03928316815291166020820152604001604051809103905ff0801580156105a8573d5f5f3e3d5ffd5b50600380546001600160a01b0319166001600160a01b039290921691821790556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a25b600254604080516001600160a01b03928316602482015291841660448084019190915281518084039091018152606490920181526020820180516001600160e01b031663485cc95560e01b1790525130919061064c906107f0565b61065792919061084e565b604051809103905ff080158015610670573d5f5f3e3d5ffd5b506001600160a01b038381165f8181526004602090815260409182902080546001600160a01b03191694861694851790559051928352929350917fbc0aff029cf899fe358381e295caa21dd2e8c1a6607e2b9e6c7ec915db15bd53910160405180910390a2919050565b5f5f9054906101000a90046001600160a01b03166001600160a01b031663e7589b396040518163ffffffff1660e01b8152600401602060405180830381865afa158015610729573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061074d9190610833565b33906001600160a01b0316811461078357604051632bc10c3360e01b81526001600160a01b0390911660048201526024016101c3565b506003546001600160a01b038281169116146107e057600380546001600160a01b0319166001600160a01b0383169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a25b50565b6150f48061089483390190565b6105778061598883390190565b6001600160a01b03811681146107e0575f5ffd5b5f60208284031215610821575f5ffd5b813561082c816107fd565b9392505050565b5f60208284031215610843575f5ffd5b815161082c816107fd565b6001600160a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f830116840101915050939250505056fe610100604052348015610010575f5ffd5b506040516150f43803806150f483398101604081905261002f916101f9565b61003761012c565b6001600160a01b03808316608081905290821660e05260408051632b18028f60e21b815290515f928392909163ac600a3c916004808201926020929091908290030181865afa15801561008c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100b0919061022a565b846001600160a01b0316634256f5e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100ec573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610110919061022a565b6001600160a01b0391821660a0521660c0525061024a92505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561017c5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101db5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b80516001600160a01b03811681146101f4575f5ffd5b919050565b5f5f6040838503121561020a575f5ffd5b610213836101de565b9150610221602084016101de565b90509250929050565b5f6020828403121561023a575f5ffd5b610243826101de565b9392505050565b60805160a05160c05160e051614e236102d15f395f81816104e80152611cf701525f81816102ec01528181610eab015261263801525f81816104690152610e7d01525f81816103130152818161067801528181610bb5015281816110f9015281816113c301528181611413015281816124c70152818161251701526128650152614e235ff3fe608060405234801561000f575f5ffd5b5060043610610213575f3560e01c8063a7852afa1161011f578063c64cef64116100a9578063e3161ddd11610079578063e3161ddd146105da578063e92a9fa9146105e2578063eb6ebc2714610636578063f515740e14610649578063f5f8d36514610651575f5ffd5b8063c64cef6414610546578063c6cee75814610559578063c7deeca61461056c578063e102dac41461057f575f5ffd5b8063b66503cf116100ef578063b66503cf146104bd578063be171c5e146104d0578063c415b95c146104e3578063c4e3a63b1461050a578063c4f59f9b14610531575f5ffd5b8063a7852afa1461043e578063aa89d99b14610451578063ac600a3c14610464578063b5caf3861461048b575f5ffd5b8063485cc955116101a05780639096a35d116101705780639096a35d146103c257806398bbc3c7146103d557806399bcc052146104055780639a32421a14610418578063a23057561461042b575f5ffd5b8063485cc9551461033557806362da4afd146103485780637af618331461035b5780638ed6a18c146103af575f5ffd5b806329b2f637116101e657806329b2f6371461029e5780633af32abf146102b15780633e491d47146102d45780634256f5e7146102e757806346c96aac1461030e575f5ffd5b8063160b194b1461021757806316f0115b146102215780631b9e88b11461026a578063221ca18c1461027d575b5f5ffd5b61021f610664565b005b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7302546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b61021f610278366004614327565b61077c565b61029061028b366004614359565b6109c2565b604051908152602001610261565b61021f6102ac3660046143c3565b610a2a565b6102c46102bf366004614359565b610b94565b6040519015158152602001610261565b6102906102e236600461445f565b610c26565b61024d7f000000000000000000000000000000000000000000000000000000000000000081565b61024d7f000000000000000000000000000000000000000000000000000000000000000081565b61021f610343366004614489565b610d50565b6102906103563660046144c0565b61100e565b61029061036936600461445f565b6001600160a01b03919091165f9081527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730a60209081526040808320938352929052205490565b61021f6103bd3660046144f5565b6110b7565b61021f6103d036600461455b565b6110f7565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7303546001600160a01b031661024d565b610290610413366004614359565b61124e565b61021f610426366004614659565b6112e9565b6102906104393660046146c2565b61131e565b61021f61044c366004614712565b611372565b61021f61045f366004614756565b61157d565b61024d7f000000000000000000000000000000000000000000000000000000000000000081565b61049e6104993660046147cd565b61191c565b6040805192151583526001600160a01b03909116602083015201610261565b61021f6104cb36600461445f565b611ced565b6102906104de3660046147f1565b61206a565b61024d7f000000000000000000000000000000000000000000000000000000000000000081565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730154610290565b610539612383565b6040516102619190614870565b6102c4610554366004614359565b6123b3565b61021f6105673660046148bb565b6123de565b61021f61057a3660046147cd565b612476565b61029061058d36600461493a565b5f9283527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7309602090815260408085209385529281528284206001600160a01b039290921684525290205490565b61021f6126ab565b6102906105f036600461455b565b5f9182527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7306602090815260408084206001600160a01b0393909316845291905290205490565b610290610644366004614970565b612a3b565b610539612b30565b61021f61065f366004614712565b612b5b565b5f5f516020614dce5f395f51905f5290505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166398bbc3c76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106d2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f691906149ce565b60038301549091506001600160a01b038083169116146107785760038201546040516001600160a01b03918216918316907f91b28bee5dc86f5ce41c22a3057286afb3358d566c69a2a3bb4294bdb754c560905f90a36003820180546001600160a01b0319166001600160a01b0383161790556107766004830182612dce565b505b5050565b5f516020614dce5f395f51905f52805460ff166107ac576040516350dfbc4360e11b815260040160405180910390fd5b805460ff191681556107bc6126ab565b82806107e757604051631f61a80560e21b81526004016107de91815260200190565b60405180910390fd5b506107f184610b94565b849061081c57604051630b7b234960e01b81526001600160a01b0390911660048201526024016107de565b506040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610861573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088591906149e9565b905061089c6001600160a01b038616333087612de2565b6040516370a0823160e01b81523060048201525f906001600160a01b038716906370a0823190602401602060405180830381865afa1580156108e0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090491906149e9565b90506109108282614a14565b5f8581527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7306602090815260408083206001600160a01b038b168452909152812080549297508792909190610965908490614a27565b909155505060408051868152602081018690526001600160a01b0388169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a35050805460ff19166001179055505050565b5f806109d162093a8042614a4e565b5f8181527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7306602090815260408083206001600160a01b0388168452909152902054909150610a239062093a8090614a4e565b9392505050565b5f516020614dce5f395f51905f52805460ff16610a5a576040516350dfbc4360e11b815260040160405180910390fd5b805460ff19168155610a6a6126ab565b336001600160a01b0387168114610aa057604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b505f610aae8787878761131e565b90505f5b88811015610b7d57610ac762093a8042614a4e565b8b1015610b3f578a7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730a5f8c8c85818110610b0357610b03614a6d565b9050602002016020810190610b189190614359565b6001600160a01b0316815260208082019290925260409081015f9081208682529092529020555b610b758b8b8b84818110610b5557610b55614a6d565b9050602002016020810190610b6a9190614359565b8a8a8a8a888b612e49565b600101610ab2565b5050805460ff191660011790555050505050505050565b604051633af32abf60e01b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690633af32abf90602401602060405180830381865afa158015610bfc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c209190614a81565b92915050565b5f805f516020614dce5f395f51905f52600381015460405163133f757160e31b8152600481018690529192506001600160a01b0316905f90819083906399fbab889060240161014060405180830381865afa158015610c87573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cab9190614ac0565b5050505050945094505050505f610cc48488858561131e565b6001600160a01b0389165f908152600a87016020908152604080832084845290915281205460018801549293509091610cfd9190612f37565b90505f610d0d62093a8042614a4e565b9050815b818111610d4257610d26818c898d8a8a612a3b565b610d30908a614a27565b9850610d3b81614b75565b9050610d11565b505050505050505092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f81158015610d955750825b90505f8267ffffffffffffffff166001148015610db15750303b155b905081158015610dbf575080155b15610ddd5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610e0757845460ff60401b1916600160401b1785555b5f516020614dce5f395f51905f52805460ff19166001178155610e2d62093a8042614a4e565b60018201556002810180546001600160a01b03808a166001600160a01b031992831617909255600383018054928b1692909116919091179055610e736004820189612dce565b50610ea1600e82017f0000000000000000000000000000000000000000000000000000000000000000612dce565b50610ecf600e82017f0000000000000000000000000000000000000000000000000000000000000000612dce565b505f876001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610f0d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f319190614b9e565b505050935050505061012c8161ffff161015610fa3576040516332148f6760e01b815261012c60048201526001600160a01b038916906332148f67906024015f604051808303815f87803b158015610f87575f5ffd5b505af1158015610f99573d5f5f3e3d5ffd5b5050505061012c90505b61ffff81166010830155610fb5612f46565b82601101819055505050831561100557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f805f516020614dce5f395f51905f526003015460405163133f757160e31b8152600481018590526001600160a01b0390911691505f90819083906399fbab889060240161014060405180830381865afa15801561106e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110929190614ac0565b5050505050945094505050506110ac878785888686612a3b565b979650505050505050565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7303546110f0906001600160a01b0316868686868661157d565b5050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7589b396040518163ffffffff1660e01b8152600401602060405180830381865afa158015611153573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061117791906149ce565b6001600160a01b0316336001600160a01b0316146111a85760405163eb41813b60e01b815260040160405180910390fd5b5f8281527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730b6020908152604080832080546001600160a01b0319166001600160a01b0386161790557fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730d909152812080545f516020614dce5f395f51905f529290919061123383614b75565b909155506112449050836001614a27565b6011909101555050565b5f8061125d62093a8042614a4e565b90505f4261126c836001614a27565b6112799062093a80614c22565b6112839190614a14565b5f8381527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7306602090815260408083206001600160a01b038916845290915290205490915062093a80906112d7908390614c22565b6112e19190614a4e565b949350505050565b815f5b818110156110f05761131685858381811061130957611309614a6d565b9050602002013584612b5b565b6001016112ec565b6040805160609590951b6bffffffffffffffffffffffff1916602080870191909152603486019490945260e892831b6054860152911b60578401528051603a818503018152605a9093019052815191012090565b5f516020614dce5f395f51905f52805460ff166113a2576040516350dfbc4360e11b815260040160405180910390fd5b805460ff191681556113b26126ab565b5f516020614dce5f395f51905f525f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146113f75733611406565b60038201546001600160a01b03165b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061144757506114476004830133612f54565b339061147257604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b506040516331a9108f60e11b8152600481018690525f906001600160a01b03831690636352211e90602401602060405180830381865afa1580156114b8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114dc91906149ce565b90505f5f836001600160a01b03166399fbab88896040518263ffffffff1660e01b815260040161150e91815260200190565b61014060405180830381865afa15801561152a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154e9190614ac0565b505050505094509450505050611568848984848b88612f75565b5050835460ff19166001179093555050505050565b5f516020614dce5f395f51905f52805460ff166115ad576040516350dfbc4360e11b815260040160405180910390fd5b805460ff191681556115bd6126ab565b5f516020614dce5f395f51905f526115d862093a8042614a4e565b8711156115f85760405163f21ef34360e01b815260040160405180910390fd5b6116056004820189612f54565b889061163057604051632300a4b360e01b81526001600160a01b0390911660048201526024016107de565b506040516331a9108f60e11b81526004810185905288905f906001600160a01b03831690636352211e90602401602060405180830381865afa158015611678573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061169c91906149ce565b60405163020604bf60e21b8152600481018890529091505f906001600160a01b0384169063081812fc90602401602060405180830381865afa1580156116e4573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061170891906149ce565b9050336001600160a01b03831614806117295750336001600160a01b038216145b8061179d575060405163e985e9c560e01b81526001600160a01b03838116600483015233602483015284169063e985e9c590604401602060405180830381865afa158015611779573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061179d9190614a81565b33906117c857604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b505060405163133f757160e31b8152600481018790525f915081906001600160a01b038416906399fbab889060240161014060405180830381865afa158015611813573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118379190614ac0565b5050505050945094505050505f6118508489858561131e565b90505f5b898110156119025761186962093a8042614a4e565b8c10156118c4578b86600a015f8d8d8581811061188857611888614a6d565b905060200201602081019061189d9190614359565b6001600160a01b0316815260208082019290925260409081015f9081208682529092529020555b6118fa8c8c8c848181106118da576118da614a6d565b90506020020160208101906118ef9190614359565b878c8888888f612e49565b600101611854565b5050845460ff191660011790945550505050505050505050565b5f805f516020614dce5f395f51905f5281600261193a866001614a27565b6119479062093a80614c22565b6119519190614a14565b600283015460408051633850c7bd60e01b8152905192935042926001600160a01b03909216915f9182918491633850c7bd9160048083019260e09291908290030181865afa1580156119a5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c99190614b9e565b5050604080516080810182525f80825260208201819052918101829052606081019190915261ffff92831697509190921694509250611a06915050565b604080516080810182525f808252602082018190529181018290526060810182905290846001850181611a3b57611a3b614a3a565b0690505f19858201015f805b6020811015611c1a576010811115611a7257604051631d3fd47b60e21b815260040160405180910390fd5b6002848401049150886001600160a01b031663252c09d7898481611a9857611a98614a3a565b066040518263ffffffff1660e01b8152600401611ab791815260200190565b608060405180830381865afa158015611ad2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af69190614c39565b151560608a018190526001600160a01b0390911660408a015263ffffffff909216885250611b2957816001019350611c12565b886001600160a01b031663252c09d7898460010181611b4a57611b4a614a3a565b066040518263ffffffff1660e01b8152600401611b6991815260200190565b608060405180830381865afa158015611b84573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ba89190614c39565b151560608901526001600160a01b031660408801525063ffffffff16855285515f90611bd6908c908e6130b5565b9050808015611bee5750611bee8b8d885f01516130b5565b15611bf95750611c1a565b80611c0957600183039350611c10565b8260010194505b505b600101611a47565b505f886001600160a01b031663252c09d7898460020181611c3d57611c3d614a3a565b066040518263ffffffff1660e01b8152600401611c5c91815260200190565b608060405180830381865afa158015611c77573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c9b9190614c39565b50505063ffffffff16905080855f015163ffffffff1603611cd1575f85604001519d509d50505050505050505050505050915091565b600185604001519d509d50505050505050505050505050915091565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016632a54db015f516020614dce5f395f51905f526002015460405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b0390911660048201526024015f604051808303815f87803b158015611d84575f5ffd5b505af1158015611d96573d5f5f3e3d5ffd5b505050505f611daf5f516020614dce5f395f51905f5290565b805490915060ff16611dd4576040516350dfbc4360e11b815260040160405180910390fd5b805460ff19168155611de46126ab565b5f516020614dce5f395f51905f528280611e1457604051631f61a80560e21b81526004016107de91815260200190565b50611e1e84610b94565b8490611e4957604051630b7b234960e01b81526001600160a01b0390911660048201526024016107de565b50806002015f9054906101000a90046001600160a01b03166001600160a01b031663c2e0f9b26040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611e98575f5ffd5b505af1158015611eaa573d5f5f3e3d5ffd5b505050505f62093a8042611ebe9190614a4e565b9050611ecd600e830186612f54565b611ee057611ede600e830186612dce565b505b6040516370a0823160e01b81523060048201525f906001600160a01b038716906370a0823190602401602060405180830381865afa158015611f24573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4891906149e9565b9050611f5f6001600160a01b038716333088612de2565b6040516370a0823160e01b81523060048201525f906001600160a01b038816906370a0823190602401602060405180830381865afa158015611fa3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fc791906149e9565b9050611fd38282614a14565b5f84815260068601602090815260408083206001600160a01b038c16845290915281208054929850889290919061200b908490614a27565b909155505060408051878152602081018590526001600160a01b0389169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a35050825460ff191660011790925550505050565b5f5f516020614dce5f395f51905f5281806120878989898961131e565b5f8c815260078501602090815260408083208484528252808320548f8452600d88019092529091205491925090808210806120c0575081155b156122ab575f8d8152600c8601602052604090205460ff1680612104575060016120ea8e82614a27565b6120f79062093a80614c22565b6121019190614a14565b42105b15612219575f5f866002015f9054906101000a90046001600160a01b03166001600160a01b03168f8e8e8e8e6040516024016121719594939291909485526001600160a01b039390931660208501526040840191909152600290810b60608401520b608082015260a00190565b60408051601f198184030181529181526020820180516001600160e01b0316634c8c7ddb60e11b179052516121a69190614c98565b5f60405180830381855afa9150503d805f81146121de576040519150601f19603f3d011682016040523d82523d5f602084013e6121e3565b606091505b5091509150816121fc575f9750505050505050506110ac565b8080602001905181019061221091906149e9565b95505050612254565b5f8d8152600b860160205260408120546001600160a01b03169003612245575f955050505050506110ac565b6122518d848b8b613175565b93505b61226162093a8042614a4e565b8d10801561226c5750865b156122a6575f8d8152600786016020908152604080832086845282528083208490558f835260088801825280832086845290915290208490555b6122c9565b5f8d8152600886016020908152604080832086845290915290205493505b61230d856006015f8f81526020019081526020015f205f8e6001600160a01b03166001600160a01b031681526020019081526020015f20548561127560671b613488565b95505f856009015f8f81526020019081526020015f205f8581526020019081526020015f205f8e6001600160a01b03166001600160a01b031681526020019081526020015f2054905080871061236e576123678188614a14565b9650612372565b5f96505b505050505050979650505050505050565b60606123ae7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730e613532565b905090565b5f610c207fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a730e83612f54565b5f516020614dce5f395f51905f52805460ff1661240e576040516350dfbc4360e11b815260040160405180910390fd5b805460ff1916815561241e6126ab565b336001600160a01b038816811461245457604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b50612463878787878787612f75565b805460ff19166001179055505050505050565b5f516020614dce5f395f51905f52805460ff166124a6576040516350dfbc4360e11b815260040160405180910390fd5b805460ff191681556124b66126ab565b5f516020614dce5f395f51905f525f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146124fb573361250a565b60038201546001600160a01b03165b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061254b575061254b6004830133612f54565b339061257657604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b5060405163133f757160e31b8152600481018590525f9081906001600160a01b038416906399fbab889060240161014060405180830381865afa1580156125bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125e39190614ac0565b5050505050945094505050505f600167ffffffffffffffff81111561260a5761260a61457e565b604051908082528060200260200182016040528015612633578160200160208202803683370190505b5090507f0000000000000000000000000000000000000000000000000000000000000000815f8151811061266957612669614a6d565b60200260200101906001600160a01b031690816001600160a01b031681525050612697848885858533612f75565b5050835460ff191660011790935550505050565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7310545f516020614dce5f395f51905f5290610e108110156127d357600282015460408051633850c7bd60e01b815290516001600160a01b03909216918291633850c7bd9160048083019260e09291908290030181865afa158015612731573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127559190614b9e565b50505061ffff16945061276f9250600a9150849050614a27565b6040516332148f6760e01b815261ffff821660048201529092506001600160a01b038216906332148f67906024015f604051808303815f87803b1580156127b4575f5ffd5b505af11580156127c6573d5f5f3e3d5ffd5b5050505060108301829055505b5f6127dc612f46565b6011840154909150808214612a35576002840154604080516369a077c560e11b815290516001600160a01b03909216918491839163d340ef8a916004808201926020929091908290030181865afa158015612839573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061285d91906149e9565b146129be575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637dc688596040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128e391906149ce565b604051637b46c54f60e01b81526001600160a01b03848116600483015291925090821690637b46c54f906024015f604051808303815f87803b158015612927575f5ffd5b505af1158015612939573d5f5f3e3d5ffd5b5050505083826001600160a01b031663d340ef8a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561297a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061299e91906149e9565b146129bc5760405163013b9f2360e31b815260040160405180910390fd5b505b6129c78261191c565b5f848152600c880160209081526040808320600b8b01835281842080546001600160a01b0319166001600160a01b039690961695909517909455835460ff191694151594909417909255600d8801909152908120805491612a2783614b75565b909155505050601184018290555b50505050565b60408051602481018890526001600160a01b0387811660448301528616606482015260848101859052600284810b60a483015283900b60c48201525f60e48083018290528351808403909101815261010490920183526020820180516001600160e01b0316635f0b8e2f60e11b1790529151829182913091612abc91614c98565b5f60405180830381855afa9150503d805f8114612af4576040519150601f19603f3d011682016040523d82523d5f602084013e612af9565b606091505b509150915081612b0d575f92505050612b26565b80806020019051810190612b2191906149e9565b925050505b9695505050505050565b60606123ae7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7304613532565b5f516020614dce5f395f51905f52805460ff16612b8b576040516350dfbc4360e11b815260040160405180910390fd5b805460ff19168155612b9b6126ab565b5f5f516020614dce5f395f51905f52600301546040516331a9108f60e11b8152600481018690526001600160a01b0390911691505f908290636352211e90602401602060405180830381865afa158015612bf7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c1b91906149ce565b60405163020604bf60e21b8152600481018790529091505f906001600160a01b0384169063081812fc90602401602060405180830381865afa158015612c63573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c8791906149ce565b9050336001600160a01b0383161480612ca85750336001600160a01b038216145b80612d1c575060405163e985e9c560e01b81526001600160a01b03838116600483015233602483015284169063e985e9c590604401602060405180830381865afa158015612cf8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d1c9190614a81565b3390612d4757604051632bc10c3360e01b81526001600160a01b0390911660048201526024016107de565b5060405163133f757160e31b8152600481018790525f9081906001600160a01b038616906399fbab889060240161014060405180830381865afa158015612d90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612db49190614ac0565b505050505094509450505050611568858984848b33612f75565b5f610a23836001600160a01b03841661353e565b6040516001600160a01b038481166024830152838116604483015260648201839052612a359186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061358a565b5f612e5a898989898989600161206a565b90508015612f2c575f8981527fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a73096020908152604080832086845282528083206001600160a01b038c16845290915281208054839290612eba908490614a27565b90915550612ed490506001600160a01b03891683836135f6565b604080518a8152602081018590526001600160a01b03848116828401528a1660608201526080810183905290517fc8c7ebd754a625a8677ab2031c7674259be1e8c1a7f3521cbf5edbca8f48099c9181900360a00190a15b505050505050505050565b5f828218828411028218610a23565b5f6123ae62093a8042614a4e565b6001600160a01b0381165f9081526001830160205260408120541515610a23565b5f516020614dce5f395f51905f525f612f908888888861131e565b90505f612fa062093a8042614a4e565b90505f805b86518110156130a85761300985600a015f898481518110612fc857612fc8614a6d565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f8681526020019081526020015f20548660010154612f37565b9150815b83811161304d5761303d8189848151811061302a5761302a614a6d565b60200260200101518e8e8e8e8b8e612e49565b61304681614b75565b905061300d565b50613059600184614a14565b85600a015f89848151811061307057613070614a6d565b6020908102919091018101516001600160a01b031682528181019290925260409081015f908120888252909252902055600101612fa5565b5050505050505050505050565b5f8363ffffffff168363ffffffff16111580156130de57508363ffffffff168263ffffffff1611155b156130fa578163ffffffff168363ffffffff1611159050610a23565b5f8463ffffffff168463ffffffff1611613121578363ffffffff1664010000000001613129565b8363ffffffff165b64ffffffffff1690505f8563ffffffff168463ffffffff1611613159578363ffffffff1664010000000001613161565b8363ffffffff165b64ffffffffff169091111595945050505050565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7302545f907ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800906001600160a01b0316826131cd612f46565b9050808811156131f05760405163f21ef34360e01b815260040160405180910390fd5b505f8681526201000a8301602052604081208161320d828b613627565b935090505f819003613226575f955050505050506112e1565b50506040805160018082528183019092525f91829190602080830190803683375050505f8a815260088701602090815260408083208e8452600401909152812082516001820195509293506060929091859185919061328757613287614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0387169063e57c0ca9906132be908690600401614cae565b5f60405180830381865afa1580156132d8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526132ff9190810190614ce5565b9150815f8151811061331357613313614a6d565b602002602001015193505f8460581b60601c90505f6133338e8d8d613ba1565b905061333f8282614d6c565b905082955085855f8151811061335757613357614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca99061338e908890600401614cae565b5f60405180830381865afa1580156133a8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526133cf9190810190614ce5565b93505f845f815181106133e4576133e4614a6d565b60200260200101515f1c905061340988836001600160a01b0316640100000000613488565b9a505f8112806134185750808b115b1561344d575f81126134335761342e818c614a14565b613446565b61343c81614db3565b613446908c614a27565b9a50613451565b5f9a505b61346b6c0100000000000000000000000062093a80614c22565b8b1115613476575f9a505b50505050505050505050949350505050565b5f80805f19858709858702925082811083820303915050805f036134bc575f84116134b1575f5ffd5b508290049050610a23565b8084116134c7575f5ffd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b60605f610a23836142b7565b5f81815260018301602052604081205461358357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610c20565b505f610c20565b5f5f60205f8451602086015f885af1806135a9576040513d5f823e3d81fd5b50505f513d915081156135c05780600114156135cd565b6001600160a01b0384163b155b15612a3557604051635274afe760e01b81526001600160a01b03851660048201526024016107de565b6040516001600160a01b0383811660248301526044820183905261077691859182169063a9059cbb90606401612e17565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7302546040805160018082528183019092525f9283926001600160a01b039091169183918291906020808301908036833701905050905060605f8893505f8460405160200161369791815260200190565b60405160208183030381529060405280519060200120905084845f815181106136c2576136c2614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0387169063e57c0ca9906136f9908790600401614cae565b5f60405180830381865afa158015613713573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261373a9190810190614ce5565b92505f835f8151811061374f5761374f614a6d565b60200260200101515f1c9050805f03613774575f5f9850985050505050505050613b9a565b81955085855f8151811061378a5761378a614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0388169063e57c0ca9906137c1908890600401614cae565b5f60405180830381865afa1580156137db573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526138029190810190614ce5565b9350835f8151811061381657613816614a6d565b60200260200101515f1c98508989111561383c575f5f9850985050505050505050613b9a565b613847600182614a14565b9250600283028201955085855f8151811061386457613864614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0388169063e57c0ca99061389b908890600401614cae565b5f60405180830381865afa1580156138b5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526138dc9190810190614ce5565b9350835f815181106138f0576138f0614a6d565b60200260200101515f1c98505088881115613a2a575f82815b82821115613a1d575f600261391e8585614a14565b6139289190614a4e565b6139329084614a14565b9050600281028501985088885f8151811061394f5761394f614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b038b169063e57c0ca990613986908b90600401614cae565b5f60405180830381865afa1580156139a0573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526139c79190810190614ce5565b9650865f815181106139db576139db614a6d565b60200260200101515f1c9b508c8c036139f957945060019050613a1d565b8c8c1015613a0957809350613a17565b613a14600182614a14565b92505b50613909565b80613a26578294505b5050505b600282028101945084845f81518110613a4557613a45614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0387169063e57c0ca990613a7c908790600401614cae565b5f60405180830381865afa158015613a96573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613abd9190810190614ce5565b9250825f81518110613ad157613ad1614a6d565b60200260200101515f1c9750600160028302820101945084845f81518110613afb57613afb614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0387169063e57c0ca990613b32908790600401614cae565b5f60405180830381865afa158015613b4c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613b739190810190614ce5565b9250825f81518110613b8757613b87614a6d565b60200260200101515f1c96505050505050505b9250929050565b7fddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7302546040805160c0810182525f8082526020808301829052828401829052606083018290526080830182905260a083018290528351600180825281860190955291947ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800946001600160a01b0390911693928692839290828101908036833701905050905060605f5f5f8862010008015f8e63ffffffff1681526020019081526020015f20905080955085855f81518110613c7d57613c7d614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca990613cb4908890600401614cae565b5f60405180830381865afa158015613cce573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613cf59190810190614ce5565b9350835f81518110613d0957613d09614a6d565b60209081029190910181015160028e900b5f90815260068c01835260409081902090516004909101985062ffffff82841c16955063ffffffff9091169350879250613d69918f9184910163ffffffff929092168252602082015260400190565b60405160208183030381529060405280519060200120955085855f81518110613d9457613d94614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca990613dcb908890600401614cae565b5f60405180830381865afa158015613de5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613e0c9190810190614ce5565b9350835f81518110613e2057613e20614a6d565b60209081029190910101516001600160a01b0316604088015250600282810b908c900b13801590613e5c575060408601516001600160a01b0316155b15613f38575f81815262010008890160205260408120855190965086918291879190613e8a57613e8a614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca990613ec1908890600401614cae565b5f60405180830381865afa158015613edb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613f029190810190614ce5565b9350835f81518110613f1657613f16614a6d565b602090810291909101015160501c6001600160a01b0316604088018190529550505b60028a900b5f9081526006890160209081526040918290209151600490920196508691613f7a918f9184910163ffffffff929092168252602082015260400190565b60405160208183030381529060405280519060200120955085855f81518110613fa557613fa5614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca990613fdc908890600401614cae565b5f60405180830381865afa158015613ff6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261401d9190810190614ce5565b9350835f8151811061403157614031614a6d565b60209081029190910101516001600160a01b0316606088015250600282810b908b900b1380159061406d575060608601516001600160a01b0316155b15614149575f8181526201000889016020526040812085519096508691829187919061409b5761409b614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0389169063e57c0ca9906140d2908890600401614cae565b5f60405180830381865afa1580156140ec573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526141139190810190614ce5565b9350835f8151811061412757614127614a6d565b602090810291909101015160501c6001600160a01b0316606088018190529550505b505063ffffffff8a165f9081526201000887016020526040812083519094508491829185919061417b5761417b614a6d565b602090810291909101015260405163e57c0ca960e01b81526001600160a01b0387169063e57c0ca9906141b2908690600401614cae565b5f60405180830381865afa1580156141cc573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526141f39190810190614ce5565b9150815f8151811061420757614207614a6d565b602002602001015193505f8460b01b60e81c90508a60020b8160020b121561424357856060015186604001510398505050505050505050610a23565b8960020b8160020b121561429d57606086015160408701515f516020614dce5f395f51905f5263ffffffff8f165f908152600b9190910160205260409020546001600160a01b031603039850610a23975050505050505050565b856040015186606001510398505050505050505050610a23565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561430457602002820191905f5260205f20905b8154815260200190600101908083116142f0575b50505050509050919050565b6001600160a01b0381168114614324575f5ffd5b50565b5f5f5f60608486031215614339575f5ffd5b833561434481614310565b95602085013595506040909401359392505050565b5f60208284031215614369575f5ffd5b8135610a2381614310565b5f5f83601f840112614384575f5ffd5b50813567ffffffffffffffff81111561439b575f5ffd5b6020830191508360208260051b8501011115613b9a575f5ffd5b8060020b8114614324575f5ffd5b5f5f5f5f5f5f5f5f60e0898b0312156143da575f5ffd5b88359750602089013567ffffffffffffffff8111156143f7575f5ffd5b6144038b828c01614374565b909850965050604089013561441781614310565b945060608901359350608089013561442e816143b5565b925060a089013561443e816143b5565b915060c089013561444e81614310565b809150509295985092959890939650565b5f5f60408385031215614470575f5ffd5b823561447b81614310565b946020939093013593505050565b5f5f6040838503121561449a575f5ffd5b82356144a581614310565b915060208301356144b581614310565b809150509250929050565b5f5f5f606084860312156144d2575f5ffd5b8335925060208401356144e481614310565b929592945050506040919091013590565b5f5f5f5f5f60808688031215614509575f5ffd5b85359450602086013567ffffffffffffffff811115614526575f5ffd5b61453288828901614374565b90955093505060408601359150606086013561454d81614310565b809150509295509295909350565b5f5f6040838503121561456c575f5ffd5b8235915060208301356144b581614310565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156145bb576145bb61457e565b604052919050565b5f67ffffffffffffffff8211156145dc576145dc61457e565b5060051b60200190565b5f82601f8301126145f5575f5ffd5b8135614608614603826145c3565b614592565b8082825260208201915060208360051b860101925085831115614629575f5ffd5b602085015b8381101561464f57803561464181614310565b83526020928301920161462e565b5095945050505050565b5f5f5f6040848603121561466b575f5ffd5b833567ffffffffffffffff811115614681575f5ffd5b61468d86828701614374565b909450925050602084013567ffffffffffffffff8111156146ac575f5ffd5b6146b8868287016145e6565b9150509250925092565b5f5f5f5f608085870312156146d5575f5ffd5b84356146e081614310565b93506020850135925060408501356146f7816143b5565b91506060850135614707816143b5565b939692955090935050565b5f5f60408385031215614723575f5ffd5b82359150602083013567ffffffffffffffff811115614740575f5ffd5b61474c858286016145e6565b9150509250929050565b5f5f5f5f5f5f60a0878903121561476b575f5ffd5b863561477681614310565b955060208701359450604087013567ffffffffffffffff811115614798575f5ffd5b6147a489828a01614374565b9095509350506060870135915060808701356147bf81614310565b809150509295509295509295565b5f602082840312156147dd575f5ffd5b5035919050565b8015158114614324575f5ffd5b5f5f5f5f5f5f5f60e0888a031215614807575f5ffd5b87359650602088013561481981614310565b9550604088013561482981614310565b9450606088013593506080880135614840816143b5565b925060a0880135614850816143b5565b915060c0880135614860816147e4565b8091505092959891949750929550565b602080825282518282018190525f918401906040840190835b818110156148b05783516001600160a01b0316835260209384019390920191600101614889565b509095945050505050565b5f5f5f5f5f5f60c087890312156148d0575f5ffd5b86356148db81614310565b95506020870135945060408701356148f2816143b5565b93506060870135614902816143b5565b9250608087013567ffffffffffffffff81111561491d575f5ffd5b61492989828a016145e6565b92505060a08701356147bf81614310565b5f5f5f6060848603121561494c575f5ffd5b8335925060208401359150604084013561496581614310565b809150509250925092565b5f5f5f5f5f5f60c08789031215614985575f5ffd5b86359550602087013561499781614310565b945060408701356149a781614310565b93506060870135925060808701356149be816143b5565b915060a08701356147bf816143b5565b5f602082840312156149de575f5ffd5b8151610a2381614310565b5f602082840312156149f9575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c2057610c20614a00565b80820180821115610c2057610c20614a00565b634e487b7160e01b5f52601260045260245ffd5b5f82614a6857634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215614a91575f5ffd5b8151610a23816147e4565b80516fffffffffffffffffffffffffffffffff81168114614abb575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f5f6101408b8d031215614ada575f5ffd5b8a51614ae581614310565b60208c0151909a50614af681614310565b60408c0151909950614b07816143b5565b60608c0151909850614b18816143b5565b60808c0151909750614b29816143b5565b9550614b3760a08c01614a9c565b60c08c015160e08d015191965094509250614b556101008c01614a9c565b9150614b646101208c01614a9c565b90509295989b9194979a5092959850565b5f60018201614b8657614b86614a00565b5060010190565b805161ffff81168114614abb575f5ffd5b5f5f5f5f5f5f5f60e0888a031215614bb4575f5ffd5b8751614bbf81614310565b6020890151909750614bd0816143b5565b9550614bde60408901614b8d565b9450614bec60608901614b8d565b9350614bfa60808901614b8d565b925060a088015162ffffff81168114614c11575f5ffd5b60c0890151909250614860816147e4565b8082028115828204841417610c2057610c20614a00565b5f5f5f5f60808587031215614c4c575f5ffd5b845163ffffffff81168114614c5f575f5ffd5b8094505060208501518060060b8114614c76575f5ffd5b6040860151909350614c8781614310565b6060860151909250614707816147e4565b5f82518060208501845e5f920191825250919050565b602080825282518282018190525f918401906040840190835b818110156148b0578351835260209384019390920191600101614cc7565b5f60208284031215614cf5575f5ffd5b815167ffffffffffffffff811115614d0b575f5ffd5b8201601f81018413614d1b575f5ffd5b8051614d29614603826145c3565b8082825260208201915060208360051b850101925086831115614d4a575f5ffd5b6020840193505b82841015612b26578351825260209384019390910190614d51565b601382810b9082900b03737fffffffffffffffffffffffffffffffffffffff198112737fffffffffffffffffffffffffffffffffffffff82131715610c2057610c20614a00565b5f600160ff1b8201614dc757614dc7614a00565b505f039056feddab91076ea92d6a766cefd001b0cf5f73830986b100aa9c6fa6286e6b0a7300a26469706673582212205e8a7cbc28c3831f07312a3c3c6bcd492c3abbb73d47787fedb02ed8e30c402164736f6c634300081c003360a060405260405161057738038061057783398101604081905261002291610354565b61002c828261003e565b506001600160a01b0316608052610445565b610047826100fb565b6040516001600160a01b038316907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e905f90a28051156100ef576100ea826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e49190610416565b82610209565b505050565b6100f761027c565b5050565b806001600160a01b03163b5f0361013557604051631933b43b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b807fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392831617905560408051635c60da1b60e01b815290515f92841691635c60da1b9160048083019260209291908290030181865afa1580156101ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d29190610416565b9050806001600160a01b03163b5f036100f757604051634c9c8ce360e01b81526001600160a01b038216600482015260240161012c565b60605f5f846001600160a01b031684604051610225919061042f565b5f60405180830381855af49150503d805f811461025d576040519150601f19603f3d011682016040523d82523d5f602084013e610262565b606091505b50909250905061027385838361029d565b95945050505050565b341561029b5760405163b398979f60e01b815260040160405180910390fd5b565b6060826102b2576102ad826102fc565b6102f5565b81511580156102c957506001600160a01b0384163b155b156102f257604051639996b31560e01b81526001600160a01b038516600482015260240161012c565b50805b9392505050565b80511561030c5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b80516001600160a01b038116811461033b575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610365575f5ffd5b61036e83610325565b60208401519092506001600160401b03811115610389575f5ffd5b8301601f81018513610399575f5ffd5b80516001600160401b038111156103b2576103b2610340565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103e0576103e0610340565b6040528181528282016020018710156103f7575f5ffd5b8160208401602083015e5f602083830101528093505050509250929050565b5f60208284031215610426575f5ffd5b6102f582610325565b5f82518060208501845e5f920191825250919050565b60805161011b61045c5f395f601d015261011b5ff3fe6080604052600a600c565b005b60186014601a565b609d565b565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156076573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906098919060ba565b905090565b365f5f375f5f365f845af43d5f5f3e80801560b6573d5ff35b3d5ffd5b5f6020828403121560c9575f5ffd5b81516001600160a01b038116811460de575f5ffd5b939250505056fea26469706673582212204d9471f2016d028d1d1f4816bb78c0f5049d528195c75b1745670d8620fd2b0c64736f6c634300081c0033a264697066735822122002c3ea8cec6f8de8364561e9fb19ca414cf8ea119da426a1315ad3f8269914f264736f6c634300081c003300000000000000000000000012e66c8f215ddd5d48d150c8f46ad0c6fb0f44060000000000000000000000009f59398d0a397b2eeb8a6123a6c7295cb0b0062d000000000000000000000000949e7b2f3f66eae761a9397346ddbd719f046c0e" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/NonfungiblePositionManager.json b/test/foundry/bytecodes/shadow-cl/NonfungiblePositionManager.json new file mode 100644 index 0000000..7d75055 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/NonfungiblePositionManager.json @@ -0,0 +1,3 @@ +{ + "bytecode": "610100604052346103ee57614e656080813803918261001d816103f2565b9384928339810103126103ee5761003381610417565b61003f60208301610417565b91610058606061005160408401610417565b9201610417565b9061006360406103f2565b93601785527f536861646f7720563320506f736974696f6e73204e4654000000000000000000602086015261009860406103f2565b600d81526c0534841444f572d56332d4e465609c1b602082015260809490945260a05283516001600160401b038111610302575f54600181811c911680156103e4575b60208210146102e457601f8111610382575b50602094601f8211600114610321579481929394955f92610316575b50508160011b915f199060031b1c1916175f555b82516001600160401b03811161030257600154600181811c911680156102f8575b60208210146102e457601f8111610281575b506020601f821160011461021e57819293945f92610213575b50508160011b915f199060031b1c1916176001555b760100000000000000000000000000000000000000000001600d5560c0526001600160a01b031660e052604051614a39908161042c82396080518181816106e501528181611d5a01528181611f36015281816122760152818161313d015261392f015260a051818181610fdf015281816110fa01528181613300015261408e015260c05181611c77015260e051816111710152f35b015190505f80610169565b601f1982169060015f52805f20915f5b81811061026957509583600195969710610251575b505050811b0160015561017e565b01515f1960f88460031b161c191690555f8080610243565b9192602060018192868b01518155019401920161022e565b60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f830160051c810191602084106102da575b601f0160051c01905b8181106102cf5750610150565b5f81556001016102c2565b90915081906102b9565b634e487b7160e01b5f52602260045260245ffd5b90607f169061013e565b634e487b7160e01b5f52604160045260245ffd5b015190505f80610109565b601f198216955f8052805f20915f5b88811061036a57508360019596979810610352575b505050811b015f5561011d565b01515f1960f88460031b161c191690555f8080610345565b91926020600181928685015181550194019201610330565b5f80527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563601f830160051c810191602084106103da575b601f0160051c01905b8181106103cf57506100ed565b5f81556001016103c2565b90915081906103b9565b90607f16906100db565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761030257604052565b51906001600160a01b03821682036103ee5756fe60806040526004361015610022575b3615610018575f80fd5b6100206132f6565b005b5f3560e01c806301ffc9a71461022157806306fdde031461021c578063081812fc14610217578063095ea7b3146102125780630c49ccbe1461020d57806312210e8a1461020857806318160ddd14610203578063219f5d17146101fe57806323b872dd146101f95780632f745c59146101f457806342842e0e146101ef57806342966c68146101ea57806349404b7c146101e55780634aa4a4fc146101e05780634bc2a657146101db5780634f6ccce7146101d65780636352211e146101d15780636d70c415146101cc57806370a08231146101c757806395d89b41146101c257806399fbab88146101bd578063a22cb465146101b8578063ac9650d8146101b3578063b88d4fde146101ae578063c87b56dd146101a9578063d3487997146101a4578063d5f394881461019f578063df2ab5bb1461019a578063e985e9c514610195578063f126fb6714610190578063f5f8d3651461018b5763fc6f78650361000e5761237c565b6121d0565b611ea5565b611e34565b611d7e565b611d3b565b611cd9565b611c18565b611b88565b6119dc565b611855565b61169e565b6115e9565b6115ba565b6112b9565b61128a565b61120b565b61111e565b6110db565b610f8e565b610eaa565b610e81565b610dee565b610dd7565b610a90565b610a73565b610a57565b610607565b6104db565b61048d565b61039d565b610254565b7fffffffff0000000000000000000000000000000000000000000000000000000081160361025057565b5f80fd5b34610250576020600319360112610250577fffffffff0000000000000000000000000000000000000000000000000000000060043561029281610226565b167f780e9d630000000000000000000000000000000000000000000000000000000081149081156102cc575b506040519015158152602090f35b7f80ac58cd00000000000000000000000000000000000000000000000000000000811491508115610330575b8115610306575b505f6102be565b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150145f6102ff565b7f5b5e139f00000000000000000000000000000000000000000000000000000000811491506102f8565b5f91031261025057565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b90602061039a928181520190610364565b90565b34610250575f600319360112610250576040515f5f548060011c9060018116908115610483575b60208310821461046f5782855260208501919081156104565750600114610406575b610402846103f681860382611b09565b60405191829182610389565b0390f35b5f8080529250907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b818410610442575050016103f6826103e6565b80548484015260209093019260010161042f565b60ff191682525090151560051b0190506103f6826103e6565b634e487b7160e01b5f52602260045260245ffd5b91607f16916103c4565b34610250576020600319360112610250576004356104aa8161336c565b505f52600460205260206001600160a01b0360405f205416604051908152f35b6001600160a01b0381160361025057565b34610250576040600319360112610250576004356104f8816104ca565b602435906105058261336c565b331515806105f4575b806105b4575b610588578261002093610560926001600160a01b0380861691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a45f52600460205260405f2090565b906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b7fa9fbf51f000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b5060ff6105ec336105d6846001600160a01b03165f52600560205260405f2090565b906001600160a01b03165f5260205260405f2090565b541615610514565b50336001600160a01b038216141561050e565b60a060031936011261025057600435805f526002602052610637816001600160a01b0360405f20541633906133b8565b6084354211610a2f5761065b6001600160801b0361065361281e565b161515612842565b61066d815f52600c60205260405f2090565b80549161067a8360801c90565b9161069261068661281e565b6001600160801b031690565b926106a96001600160801b03821694851015612842565b610715610709806106e36106de69ffffffffffffffffffff8a165b69ffffffffffffffffffff165f52600b60205260405f2090565b612849565b7f00000000000000000000000000000000000000000000000000000000000000006134c2565b6001600160a01b031690565b60406107316107278860501c60020b90565b9760681c60020b90565b61073961281e565b82517f6847456a000000000000000000000000000000000000000000000000000000008152600481018890526002998a0b60248201529190980b60448201526001600160801b039097166064880152866084815f855af19485156109c0575f965f966109f8575b50604435871080156109ed575b6109c55760a0610818926107de86546107d66107cc8260501c60020b90565b9160681c60020b90565b90893061363a565b9060405180809681947f514ea4bf000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03915afa9182156109c0575f905f93610989575b506001850182815483039061084091613697565b6001600160801b03166001600160801b038a8116919091011660038701908154610870906001600160801b031690565b016001600160801b031681546fffffffffffffffffffffffffffffffff19166001600160801b03909116178155600287019384548603906108b091613697565b81546001600160801b038082169281168c82160116608091821c01901b6fffffffffffffffffffffffffffffffff191617905555556108ed61281e565b90036001600160801b031681546001600160801b031660809190911b6fffffffffffffffffffffffffffffffff1916179055818361092961281e565b60405192839261095392846040919493926001600160801b03606083019616825260208201520152565b037f26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b491a260408051928352602083019190915290f35b90506109ae91925060a03d60a0116109b9575b6109a68183611b09565b8101906128a6565b50509291505f61082c565b503d61099c565b61289b565b7f0c971c7b000000000000000000000000000000000000000000000000000000005f5260045ffd5b5060643586106107ad565b909550610a1e91965060403d604011610a28575b610a168183611b09565b810190612885565b959095945f6107a0565b503d610a0c565b7fb8e3f2bf000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f6003193601126102505747610a6957005b6100204733613833565b34610250575f600319360112610250576020600854604051908152f35b60c06003193601126102505760a4354211610a2f576001600160a01b03600435610ac2815f52600c60205260405f2090565b90610bae8254610ae16106de6106c48369ffffffffffffffffffff1690565b80516001600160a01b031691610b0f6040610b0660208501516001600160a01b031690565b93015160020b90565b90610b206107cc8260501c60020b90565b610b9260243591610b8860443594610b7160643597610b676084355b9a610b57610b48611b2c565b6001600160a01b03909e168e52565b6001600160a01b031660208d0152565b60020b60408b0152565b3060608a0152608089018b905260020b60a0890152565b60020b60c0870152565b60e08501526101008401526101208301526101408201526138f2565b93919590929460a0610c1b825496610be1610bcc8960501c60020b90565b610bd98a60681c60020b90565b90883061363a565b6040519586809481937f514ea4bf000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b0392165afa80156109c05761040295610d1b935f905f93610d84575b50610c6061068660018601936001600160801b03610c59865486039260801c90565b1690613697565b91610caf610c8a6003870194610c7d86546001600160801b031690565b016001600160801b031690565b84906001600160801b03166fffffffffffffffffffffffffffffffff19825416179055565b610d0a6002860193610ce2610cd861068687548903610cd26106868c5460801c90565b90613697565b825460801c610c7d565b6001600160801b036fffffffffffffffffffffffffffffffff1983549260801b169116179055565b5555610ce286610c7d835460801c90565b604080516001600160801b0386168152602081018790529081018390527f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f90606090a2604051938493846040919493926001600160801b03606083019616825260208201520152565b9050610da091925060a03d60a0116109b9576109a68183611b09565b50509291505f610c37565b600319606091011261025057600435610dc3816104ca565b90602435610dd0816104ca565b9060443590565b3461025057610020610de836610dab565b916128e5565b3461025057604060031936011261025057600435610e0b816104ca565b6001600160a01b0360243591610e2081612cbb565b831015610e5257165f52600660205260405f20905f5260205261040260405f2054604051918291829190602083019252565b7fa57d13dc000000000000000000000000000000000000000000000000000000005f521660045260245260445ffd5b3461025057610020610e9236610dab565b9060405192610ea2602085611b09565b5f8452612f43565b602060031936011261025057600435805f526002602052610eda816001600160a01b0360405f20541633906133b8565b805f52600c60205260405f20805460801c1590811591610f77575b8115610f5e575b50610f365780610f31610f1a610020935f52600c60205260405f2090565b60035f918281558260018201558260028201550155565b613b56565b7f92a032ca000000000000000000000000000000000000000000000000000000005f5260045ffd5b60030154610f6f915060801c610686565b15155f610efc565b60038101546001600160801b031615159150610ef5565b604060031936011261025057602435600435610fa9826104ca565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016929091602083602481875afa9283156109c0575f936110a6575b5061102690831015612a89565b8161102d57005b823b15610250575f60405180947f2e1a7d4d00000000000000000000000000000000000000000000000000000000825281838161107288600483019190602083019252565b03925af19283156109c0576100209361108c575b50613833565b8061109a5f6110a093611b09565b8061035a565b5f611086565b6110269193506110cd9060203d6020116110d4575b6110c58183611b09565b810190612a7a565b9290611019565b503d6110bb565b34610250575f6003193601126102505760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102505760206003193601126102505760043561113b816104ca565b6040517fd33219b40000000000000000000000000000000000000000000000000000000081526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156109c0576001600160a01b03915f916111dc575b50163303610250576001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19600e541617600e555f80f35b6111fe915060203d602011611204575b6111f68183611b09565b810190612ad4565b5f6111a9565b503d6111ec565b346102505760206003193601126102505760043560085481101561125b5760085f527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30154604051908152602090f35b7fa57d13dc000000000000000000000000000000000000000000000000000000005f525f60045260245260445ffd5b346102505760206003193601126102505760206112a860043561336c565b6001600160a01b0360405191168152f35b61016060031936011261025057610144354211610a2f5761141375ffffffffffffffffffffffffffffffffffffffffffff61130b600d5475ffffffffffffffffffffffffffffffffffffffffffff1690565b61135782600183011675ffffffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffff00000000000000000000000000000000000000000000600d541617600d55565b166113a4611363612afd565b61136b612b09565b611373612b22565b61137b612b2e565b611383612b3a565b610b9260a43591610b8860c43594610b7160e43597610b6761010435610b3c565b6113bb856113b6979597949394612b15565b613d1d565b60a06001600160a01b036113d86113d0612b2e565b6107d6612b3a565b921691604051809681927f514ea4bf000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b0381845afa9384156109c05761040294611513925f925f9261158e575b5061148e9061143d612afd565b90611489611449612b09565b61147f611454612b22565b9161146f611460611b3e565b6001600160a01b039097168752565b6001600160a01b03166020860152565b60020b6040840152565b613f31565b916114d761149a612b2e565b6114cd6114a5612b3a565b916114c36114b1611b4d565b69ffffffffffffffffffff9098168852565b60020b6020870152565b60020b6040850152565b6001600160801b0389166060840152608083015260a08201525f60c08201525f60e082015261150e865f52600c60205260405f2090565b612b46565b837f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f6040518061155f86868b846040919493926001600160801b03606083019616825260208201520152565b0390a260405194859485909493926001600160801b036060936080840197845216602083015260408201520152565b61148e93506115ad91925060a03d60a0116109b9576109a68183611b09565b5050939150929190611430565b346102505760206003193601126102505760206115e16004356115dc816104ca565b612cbb565b604051908152f35b34610250575f600319360112610250576040515f6001548060011c9060018116908115611694575b60208310821461046f578285526020850191908115610456575060011461164257610402846103f681860382611b09565b60015f9081529250907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b818410611680575050016103f6826103e6565b80548484015260209093019260010161166d565b91607f1691611611565b34610250576020600319360112610250576004356116cc6116c7825f52600c60205260405f2090565b612d05565b9069ffffffffffffffffffff6116ec835169ffffffffffffffffffff1690565b1615611820575061170d6106de6106c4835169ffffffffffffffffffff1690565b9061040261172283516001600160a01b031690565b91611745604061173c60208701516001600160a01b031690565b95015160020b90565b90611754602082015160020b90565b604082015160020b60608301516001600160801b031660808401519160a08501519361179e60e061178f60c08901516001600160801b031690565b9701516001600160801b031690565b966040519a8b9a8b98969492909a99979593916101408a019b6001600160a01b03168a526001600160a01b031660208a015260020b604089015260020b606088015260020b60808701526001600160801b031660a086015260c085015260e08401526001600160801b03166101008301526001600160801b0316906101200152565b7fed15e6cf000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b8015150361025057565b3461025057604060031936011261025057600435611872816104ca565b60243561187e8161184b565b6001600160a01b038216918215611902576118b590335f52600560205260405f20906001600160a01b03165f5260205260405f2090565b60ff1981541660ff831515161790557f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31604051806118fd339482919091602081019215159052565b0390a3005b827f5b08ba18000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9181601f840112156102505782359167ffffffffffffffff8311610250576020808501948460051b01011161025057565b602081016020825282518091526040820191602060408360051b8301019401925f915b83831061199157505050505090565b90919293946020806119cd837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528951610364565b97019301930191939290611982565b60206003193601126102505760043567ffffffffffffffff811161025057611a0890369060040161192e565b90611a1282612de3565b915f5b818110611a2a5760405180610402868261195f565b5f80611a37838587612e2b565b90611a4760405180938193612e90565b0390305af4611a54612e9d565b9015611a7a5790600191611a688287612f2f565b52611a738186612f2f565b5001611a15565b604481511061025057611a9c816024806004611ab49501518301019101612ecc565b60405191829162461bcd60e51b835260048301610389565b0390fd5b634e487b7160e01b5f52604160045260245ffd5b6060810190811067ffffffffffffffff821117611ae857604052565b611ab8565b6040810190811067ffffffffffffffff821117611ae857604052565b90601f601f19910116810190811067ffffffffffffffff821117611ae857604052565b60405190611b3c61016083611b09565b565b60405190611b3c606083611b09565b60405190611b3c61010083611b09565b60405190611b3c604083611b09565b67ffffffffffffffff8111611ae857601f01601f191660200190565b3461025057608060031936011261025057600435611ba5816104ca565b60243590611bb2826104ca565b6044356064359267ffffffffffffffff8411610250573660238501121561025057836004013592611be284611b6c565b93611bf06040519586611b09565b8085523660248288010111610250576020815f92602461002099018389013786010152612f43565b3461025057602060031936011261025057600435611c358161336c565b50604051907fe9dc637500000000000000000000000000000000000000000000000000000000825230600483015260248201525f816044816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156109c057610402915f91611cb7575b5060405191829182610389565b611cd391503d805f833e611ccb8183611b09565b810190612ecc565b5f611caa565b346102505760606003193601126102505760443560243560043567ffffffffffffffff831161025057366023840112156102505782600401359167ffffffffffffffff83116102505736602484860101116102505760246100209401916130bb565b34610250575f6003193601126102505760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b606060031936011261025057600435611d96816104ca565b602435604435611da5816104ca565b604051917f70a082310000000000000000000000000000000000000000000000000000000083523060048401526020836024816001600160a01b0388165afa9283156109c0575f93611e0f575b50611dff908310156131ca565b81611e0657005b610020926141e2565b611dff919350611e2d9060203d6020116110d4576110c58183611b09565b9290611df2565b3461025057604060031936011261025057602060ff611e8e600435611e58816104ca565b6001600160a01b0360243591611e6d836104ca565b165f526005845260405f20906001600160a01b03165f5260205260405f2090565b54166040519015158152f35b8060020b0361025057565b608060031936011261025057600435611ebd816104ca565b60243590611eca826104ca565b604435611ed681611e9a565b60643592611ee3846104ca565b611f006001600160a01b0382166001600160a01b03851610612842565b6040517f9f38f7400000000000000000000000000000000000000000000000000000000081526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156109c0576001600160a01b03915f916121b1575b506040517f28af8d0b0000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015284166024820152600285900b604482015291169190602081606481865afa9081156109c0575f91612192575b506001600160a01b038116806120905750506040517f232aa5ac0000000000000000000000000000000000000000000000000000000081526001600160a01b039485166004820152908416602482015260029290920b604483015292909116606482015290602090829060849082905f905af180156109c057610402915f91612071575b505b6040516001600160a01b0390911681529081906020820190565b61208a915060203d602011611204576111f68183611b09565b5f612055565b9350935050506040517f3850c7bd00000000000000000000000000000000000000000000000000000000815260e081600481855afa80156109c0576001600160a01b03915f9161215d575b5016156120ee575b506104029150612057565b803b15610250576040517ff637731d0000000000000000000000000000000000000000000000000000000081526001600160a01b039390931660048401525f908390602490829084905af19182156109c05761040292156120e3578061109a5f61215793611b09565b5f6120e3565b61217f915060e03d60e01161218b575b6121778183611b09565b810190613224565b5050505050505f6120db565b503d61216d565b6121ab915060203d602011611204576111f68183611b09565b5f611fd1565b6121ca915060203d602011611204576111f68183611b09565b5f611f6e565b346102505760406003193601126102505760043560243567ffffffffffffffff81116102505761220490369060040161192e565b825f939293526002602052612228826001600160a01b0360405f20541633906133b8565b6122df60206122586106de6106c4612248875f52600c60205260405f2090565b5469ffffffffffffffffffff1690565b61229a612273610709610709600e546001600160a01b031690565b917f00000000000000000000000000000000000000000000000000000000000000006134c2565b9060405180809581947f2045be90000000000000000000000000000000000000000000000000000000008352600483019190916001600160a01b036020820193169052565b03915afa80156109c0576001600160a01b03915f9161235d575b5016803b156102505761233f935f8094604051968795869485937fa7852afa0000000000000000000000000000000000000000000000000000000085526004850161328f565b03925af180156109c05761234f57005b8061109a5f61002093611b09565b612376915060203d602011611204576111f68183611b09565b5f6122f9565b608060031936011261025057600435805f5260026020526123ac816001600160a01b0360405f20541633906133b8565b6001600160801b036123bc61282a565b16158015906127f5575b6123cf90612842565b6001600160a01b036123df612b09565b166127e857305b6123f8825f52600c60205260405f2090565b9182549161241b6107096106e36106de6106c48769ffffffffffffffffffff1690565b90600385019485549561243e612437886001600160801b031690565b9760801c90565b87819761244e6106868260801c90565b612671575b50505061245e61282a565b6001600160801b0388811691161115612661578687945b61247d612836565b6001600160801b03898116911611156126535787935b546124a18160501c60020b90565b6040517fa02f10690000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018b9052600292830b604483015260689390931c90910b60648201526001600160801b039a8b16608482015299851660a48b0152168860c4815a6040945f91f19687156109c0575f985f9861260c575b50836125bd87946001600160801b03809c996104029b9996612598837f40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f019b6125f099031685906001600160801b036fffffffffffffffffffffffffffffffff1983549260801b169116179055565b03166001600160801b03166fffffffffffffffffffffffffffffffff19825416179055565b604051938493849160409194936001600160801b0380926001600160a01b03606087019816865216602085015216910152565b0390a26040805191851682529290931660208401528291820190565b8697959294969399508691985060403d60401161264c575b61262e8183611b09565b8101612639916132dd565b969096989194929597509892959861252a565b503d612624565b61265b612836565b93612493565b61266961282a565b968794612475565b9097506126e691985060406001600160a01b038716916126976107cc8260501c60020b90565b82517f6847456a000000000000000000000000000000000000000000000000000000008152600481018b9052600292830b6024820152910b60448201525f606482015292839081906084820190565b03815f855af19182156109c057612727926127ca575b5060a08454916107de6127128460501c60020b90565b61271f8560681c60020b90565b908b3061363a565b03915afa9182156109c05761275d985f915f94612799575b5061276e61278e91610c7d61068660018a019d8e5487039760801c90565b966001600160801b03881690613697565b9a610c7d6106866002890195610cd287548903916001600160801b031690565b9855555f8080612453565b61278e91945061276e92506127bc9060a03d60a0116109b9576109a68183611b09565b50509391509294915061273f565b6127e29060403d604011610a2857610a168183611b09565b506126fc565b6127f0612b09565b6123e6565b506123cf612804610686612836565b151590506123c6565b6001600160801b0381160361025057565b60243561039a8161280d565b60443561039a8161280d565b60643561039a8161280d565b1561025057565b9060405161285681611acc565b6040600182946001600160a01b03815416845201546001600160a01b038116602084015260a01c60020b910152565b9190826040910312610250576020825192015190565b6040513d5f823e3d90fd5b908160a09103126102505780516128bc8161280d565b91602082015191604081015191608060608301516128d98161280d565b92015161039a8161280d565b91906001600160a01b038116928315612a4e576001600160a01b0391835f52600260205261291e60405f206001600160a01b0390541690565b9033612a3e575b848483169687158015612a0e575b61294e846001600160a01b03165f52600360205260405f2090565b6001815401905561296b84610560855f52600260205260405f2090565b82828a7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4156129f8576129a08261494f565b87036129e8575b505050168083036129b757505050565b7f64283d7b000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b6129f1916149ab565b5f846129a7565b8781146129a057612a0982856148cb565b6129a0565b612a17836142c6565b612a32856001600160a01b03165f52600360205260405f2090565b80545f19019055612933565b612a498533846133b8565b612925565b7f64a0ae92000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b90816020910312610250575190565b15612a9057565b606460405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420574554483900000000000000000000000000006044820152fd5b90816020910312610250575161039a816104ca565b634e487b7160e01b5f52603260045260245ffd5b60043561039a816104ca565b60243561039a816104ca565b6101243561039a816104ca565b60443561039a81611e9a565b60643561039a81611e9a565b60843561039a81611e9a565b90610ce260e06003611b3c94612b8569ffffffffffffffffffff865116829069ffffffffffffffffffff1669ffffffffffffffffffff19825416179055565b602085015160020b7fffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffff82549160501b6cffffff00000000000000000000169116178155612c1b612bd9604087015160020b90565b82907fffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffff82549160681b6fffffff00000000000000000000000000169116179055565b612c5b612c3260608701516001600160801b031690565b82546001600160801b031660809190911b6fffffffffffffffffffffffffffffffff1916178255565b6080850151600182015560a085015160028201550192612cad612c8860c08301516001600160801b031690565b85906001600160801b03166fffffffffffffffffffffffffffffffff19825416179055565b01516001600160801b031690565b6001600160a01b03168015612cd9575f52600360205260405f205490565b7f89c62b64000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b9060405161010081019080821067ffffffffffffffff831117611ae857611b3c9160405260e0612dbd60038396612d93612d83825469ffffffffffffffffffff81168852612d63612d598260501c60020b90565b60020b60208a0152565b612d7d612d738260681c60020b90565b60020b60408a0152565b60801c90565b6001600160801b03166060870152565b60018101546080860152600281015460a086015201546001600160801b03811660c0850152612d7d565b6001600160801b0316910152565b67ffffffffffffffff8111611ae85760051b60200190565b90612ded82612dcb565b612dfa6040519182611b09565b828152601f19612e0a8294612dcb565b01905f5b828110612e1a57505050565b806060602080938501015201612e0e565b9190811015612e8b5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561025057019081359167ffffffffffffffff8311610250576020018236038113610250579190565b612ae9565b908092918237015f815290565b3d15612ec7573d90612eae82611b6c565b91612ebc6040519384611b09565b82523d5f602084013e565b606090565b6020818303126102505780519067ffffffffffffffff8211610250570181601f8201121561025057805190612f0082611b6c565b92612f0e6040519485611b09565b8284526020838301011161025057815f9260208093018386015e8301015290565b8051821015612e8b5760209160051b010190565b909291612f518185846128e5565b833b612f5e575b50505050565b602091612f9960405194859384937f150b7a020000000000000000000000000000000000000000000000000000000085523360048601614021565b03815f6001600160a01b0387165af15f918161308a575b506130035750612fbe612e9d565b8051919082612ffc577f64a0ae92000000000000000000000000000000000000000000000000000000005f526001600160a01b03821660045260245ffd5b9050602001fd5b7fffffffff000000000000000000000000000000000000000000000000000000007f150b7a020000000000000000000000000000000000000000000000000000000091160361305657505f808080612f58565b7f64a0ae92000000000000000000000000000000000000000000000000000000005f526001600160a01b031660045260245ffd5b6130ad91925060203d6020116130b4575b6130a58183611b09565b81019061400c565b905f612fb0565b503d61309b565b92918091928101039260808412610250576060604051946130db86611aed565b12610250576131616060604051936130f285611acc565b80356130fd816104ca565b8552602081013561310d816104ca565b6020860152604081013561312081611e9a565b6040860152848752013592613134846104ca565b602086019384527f000000000000000000000000000000000000000000000000000000000000000061404f565b50806131a3575b508161317357505050565b61319c61318e6020611b3c955101516001600160a01b031690565b91516001600160a01b031690565b3391614081565b8351516131c491906001600160a01b031683516001600160a01b031661319c565b5f613168565b156131d157565b606460405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420746f6b656e00000000000000000000000000006044820152fd5b519061ffff8216820361025057565b908160e091031261025057805161323a816104ca565b91602082015161324981611e9a565b9161325660408201613215565b9161326360608301613215565b9161327060808201613215565b9160a082015160ff811681036102505760c09092015161039a8161184b565b9081526040602082018190528101839052606001915f5b8181106132b35750505090565b9091926020806001926001600160a01b0387356132cf816104ca565b1681520194019291016132a6565b919082604091031261025057602082516128d98161280d565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016330361332857565b606460405162461bcd60e51b815260206004820152600960248201527f4e6f7420574554483900000000000000000000000000000000000000000000006044820152fd5b805f5260026020526001600160a01b0360405f20541690811561338d575090565b7f7e273289000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9190916133d66001600160a01b038416801515908161345057501590565b6133df57505050565b6001600160a01b0316613417577f7e273289000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f177e802f000000000000000000000000000000000000000000000000000000005f526001600160a01b0390911660045260245260445ffd5b6001600160a01b0384168082149250821561348f575b50811561347257501590565b9050835f5260046020526001600160a01b0360405f205416141590565b9091505f52600560205260ff6134b98660405f20906001600160a01b03165f5260205260405f2090565b5416905f613466565b906001600160a01b038151169160208201926001600160a01b0384511611156135f6576135496135e761039a948461355761351d6040610b0661350f6107099a516001600160a01b031690565b95516001600160a01b031690565b604080516001600160a01b0395861660208201908152959094169084015260020b606083015281608081015b03601f198101835282611b09565b51902060405192839160208301958690917fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006055937fff00000000000000000000000000000000000000000000000000000000000000845260601b16600183015260158201527fc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d60358201520190565b5190206001600160a01b031690565b606460405162461bcd60e51b815260206004820152600b60248201527f21546f6b656e4f726465720000000000000000000000000000000000000000006044820152fd5b929091604051927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019560601b168552603484015260e81b605483015260e81b6057820152603a8152613691605a82611b09565b51902090565b5f1982820990828102928380841093039280840393146136f05782700100000000000000000000000000000000111561025057700100000000000000000000000000000000910990828211900360801b910360801c1790565b50505060801c90565b5f196c010000000000000000000000008209918160601b9182808510940393808503941461378e576c01000000000000000000000000829161373c868411612842565b0981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50915061379c821515612842565b0490565b5f1982820990828102928380841093039280840393146137f157826c010000000000000000000000001115610250576c01000000000000000000000000910990828211900360a01b910360601c1790565b50505060601c90565b90915f1983830992808302928380861095039480860395146138245790829161373c868411612842565b5050915061379c821515612842565b5f9190829160405190613847602083611b09565b83825260208201915f36843751925af161385f612e9d565b501561386757565b606460405162461bcd60e51b815260206004820152600360248201527f53544500000000000000000000000000000000000000000000000000000000006044820152fd5b929360c0946001600160801b03936001600160a01b0361039a999894168652602086015260020b604085015260020b60608401521660808201528160a08201520190610364565b80516001600160a01b03169061392661391560208301516001600160a01b031690565b61147f611454604085015160020b90565b613953610709837f00000000000000000000000000000000000000000000000000000000000000006134c2565b6001600160a01b038116936040517f3850c7bd00000000000000000000000000000000000000000000000000000000815260e081600481895afa80156109c0576040915f91613b31575b5060a08501966139df6139b96139b48a5160020b90565b614315565b9260c08801936139cd6139b4865160020b90565b60e08a0151916101008b0151936146c9565b975f87613aa5613549613a6f613a1a613a126080613a0760608801516001600160a01b031690565b960151975160020b90565b985160020b90565b9c613a23611b5d565b90815233602082015289519283916020830191909160606001600160a01b03602060808401956040815184815116875284848201511684880152015160020b6040860152015116910152565b8c88519c8d98899788967f8221b8c1000000000000000000000000000000000000000000000000000000008852600488016138ab565b03925af19283156109c0575f945f94613b0a575b50838561012083015111918215613afb575b5050613ad357565b7f7dd37f70000000000000000000000000000000000000000000000000000000005f5260045ffd5b61014001511190505f80613acb565b909350613b2791945060403d604011610a2857610a168183611b09565b939093925f613ab9565b613b4a915060e03d60e01161218b576121778183611b09565b5050505050505f61399d565b805f5260026020526001600160a01b0360405f205416801590811580613ced575b613b89845f52600260205260405f2090565b73ffffffffffffffffffffffffffffffffffffffff198154169055835f837fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a48215613cd95750613bdb8361494f565b6008545f19810190808211613cd457845f5260096020528060405f2054921015612e8b5760085f527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee281015490821015612e8b577ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee382018190555f908152600960205260409020555f838152600960205260408120556008548015613cc0575f19810190600854821015612e8b5760085f8181527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee290920191909155555061338d5750565b634e487b7160e01b5f52603160045260245ffd5b613e5c565b15613bdb57613ce883826148cb565b613bdb565b613cf6846142c6565b613d11826001600160a01b03165f52600360205260405f2090565b80545f19019055613b77565b906001600160a01b038216918215612a4e575f828152600260205260409020546001600160a01b0316916001600160a01b0383169384159485159586613e2c575b613d79856001600160a01b03165f52600360205260405f2090565b60018154019055613d9685610560865f52600260205260405f2090565b8383837fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a415613e1657613dcb8361494f565b03613e06575b505050613dda57565b7f73c6ac6e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b613e0f916149ab565b5f80613dd1565b808214613dcb57613e2783866148cb565b613dcb565b613e35846142c6565b613e50866001600160a01b03165f52600360205260405f2090565b80545f19019055613d5e565b634e487b7160e01b5f52601160045260245ffd5b6001604091613eac6001600160a01b0385511682906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b0191613ee86001600160a01b0360208301511684906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b01517fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff82549160a01b76ffffff0000000000000000000000000000000000000000169116179055565b9190916001600160a01b0381165f52600a60205269ffffffffffffffffffff60405f205416928315613f61575050565b909250600d54908160b01c9169ffffffffffffffffffff8314613cd457826140079175ffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffff000000000000000000000000000000000000000000006001611b3c970160b01b16911617600d556001600160a01b038196165f52600a6020526106c48160405f209069ffffffffffffffffffff1669ffffffffffffffffffff19825416179055565b613e70565b90816020910312610250575161039a81610226565b90926001600160a01b036080938161039a979616845216602083015260408201528160608201520190610364565b6001600160a01b0391614061916134c2565b169081330361025057565b90816020910312610250575161039a8161184b565b9290926001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693846001600160a01b03831614806141d8575b156141af575050823b1561025057604051927fd0e30db00000000000000000000000000000000000000000000000000000000084525f8460048185855af19283156109c05761415f9460209461419b575b505f6040518096819582947fa9059cbb00000000000000000000000000000000000000000000000000000000845260048401602090939291936001600160a01b0360408201951681520152565b03925af180156109c0576141705750565b6141919060203d602011614194575b6141898183611b09565b81019061406c565b50565b503d61417f565b8061109a5f6141a993611b09565b5f614112565b9093509091906001600160a01b03811630036141cf5750611b3c926141e2565b611b3c93614769565b50824710156140c1565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082019081526001600160a01b03909316602482015260448101939093525f9283929083906142398160648101613549565b51925af1614245612e9d565b81614297575b501561425357565b606460405162461bcd60e51b815260206004820152600260248201527f53540000000000000000000000000000000000000000000000000000000000006044820152fd5b80518015925082156142ac575b50505f61424b565b6142bf925060208091830101910161406c565b5f806142a4565b6142d8905f52600460205260405f2090565b805473ffffffffffffffffffffffffffffffffffffffff19169055565b8015614301575f190490565b634e487b7160e01b5f52601260045260245ffd5b60020b5f8112156146c357805f035b620d89e8811161469b576001600160a01b039160018216156146725770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b169160028116614656575b6004811661463a575b6008811661461e575b60108116614602575b602081166145e6575b604081166145ca575b608081166145ae575b6101008116614592575b6102008116614576575b610400811661455a575b610800811661453e575b6110008116614522575b6120008116614506575b61400081166144ea575b61800081166144ce575b6201000081166144b2575b620200008116614497575b62040000811661447c575b6208000016614463575b5f12614455575b61443e6144348260201c90565b9163ffffffff1690565b61444c5760ff5f5b16011690565b60ff6001614446565b61445e906142f5565b614427565b6b048a170391f7dc42444e8fa290910260801c90614420565b6d2216e584f5fa1ea926041bedfe9890920260801c91614416565b916e5d6af8dedb81196699c329225ee6040260801c9161440b565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c91614400565b916f31be135f97d08fd981231505542fcfa60260801c916143f5565b916f70d869a156d2a1b890bb3df62baf32f70260801c916143eb565b916fa9f746462d870fdf8a65dc1f90e061e50260801c916143e1565b916fd097f3bdfd2022b8845ad8f792aa58250260801c916143d7565b916fe7159475a2c29b7443b29c7fa6e889d90260801c916143cd565b916ff3392b0822b70005940c7a398e4b70f30260801c916143c3565b916ff987a7253ac413176f2b074cf7815e540260801c916143b9565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c916143af565b916ffe5dee046a99a2a811c461f1969c30530260801c916143a5565b916fff2ea16466c96a3843ec78b326b528610260801c9161439c565b916fff973b41fa98c081472e6896dfb254c00260801c91614393565b916fffcb9843d60f6159c9db58835c9266440260801c9161438a565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c91614381565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c91614378565b916ffff97272373d413259a46990580e213a0260801c9161436f565b70ffffffffffffffffffffffffffffffffff700100000000000000000000000000000000614364565b7f2bc80f3a000000000000000000000000000000000000000000000000000000005f5260045ffd5b80614324565b936001600160a01b0383166001600160a01b03831611614761575b6001600160a01b0385811695908316861161470557505061039a9350614882565b92909391946001600160a01b038216115f1461475557829161472b916147319594614882565b93614852565b6001600160801b0381166001600160801b038316105f14614750575090565b905090565b91505061039a92614852565b9091906146e4565b905f80949381946001600160a01b03604051928160208501967f23b872dd0000000000000000000000000000000000000000000000000000000088521660248501521660448301526064820152606481526147c5608482611b09565b51925af16147d1612e9d565b81614823575b50156147df57565b606460405162461bcd60e51b815260206004820152600360248201527f53544600000000000000000000000000000000000000000000000000000000006044820152fd5b8051801592508215614838575b50505f6147d7565b61484b925060208091830101910161406c565b5f80614830565b916001600160a01b0361039a93614877938281168383161161487c575b0316906136f9565b6149ef565b9061486f565b916148779161039a936001600160a01b0382166001600160a01b038216116148c5575b6001600160a01b03906148bc8284168383166137a0565b920316916137fa565b906148a5565b5f91614921916148da81612cbb565b9180855260076020526001600160a01b0360408620549216855260066020526040852091838103614924575b5084526007602052836040812055905f5260205260405f2090565b55565b838652826020526040862054818752836020528060408820558652600760205260408620555f614906565b600854815f5260096020528060405f205568010000000000000000811015611ae85760018101600855600854811015612e8b5760085f527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b906149b582612cbb565b5f19810192908311613cd4576001600160a01b03165f52600660205260405f20825f526020528060405f20555f52600760205260405f2055565b906001600160801b0382169182036102505756fea26469706673582212208ee5ed08961e15a268fd3a2c0f76b94f10be796dfc0cad22ffdf71c5f870db4a64736f6c634300081c00330000000000000000000000008bbdc15759a8ecf99a92e004e0c64ea9a5142d59000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38000000000000000000000000fe3244e2f3a672d5287dc5c98be60434802d8c4b0000000000000000000000005e7a9eea6988063a4dbb9ccddb3e04c923e8e37f" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/NonfungibleTokenPositionDescriptor.json b/test/foundry/bytecodes/shadow-cl/NonfungibleTokenPositionDescriptor.json new file mode 100644 index 0000000..a26f799 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/NonfungibleTokenPositionDescriptor.json @@ -0,0 +1,3 @@ +{ + "bytecode": "60a034607457601f6110b138819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607457516001600160a01b0381168103607457608052604051611024908161008d82396080518181816102a8015281816109f10152610ad50152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081634aa4a4fc146109d4575080634be1c7961461097a5780637d4a8689146109a9578063b7af3cdc1461097a578063dee91a2c146109315763e9dc63751461005e575f80fd5b34610674576040600319360112610674576004356001600160a01b038116809103610674576024356040517f99fbab8800000000000000000000000000000000000000000000000000000000815281600482015261014081602481865afa908115610604575f905f945f905f925f9561088a575b506020600491604051928380927fd5f394880000000000000000000000000000000000000000000000000000000082525afa908115610604575f91610850575b50604051916060830183811067ffffffffffffffff82111761060f576040526001600160a01b0385169081845260208401916001600160a01b038a1690818452604086019260020b835210156107f2576001600160a01b038080955116925116905160020b6040519160208301938452604083015260608201526060815261019b608082610a15565b519020604051907fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060208301937fff00000000000000000000000000000000000000000000000000000000000000855260601b16602183015260358201527fc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d60558201526055815261022e607582610a15565b519020169161023c81610aca565b61024587610aca565b1290811596875f146107eb5780975b156107e35750915b604051947f3850c7bd00000000000000000000000000000000000000000000000000000000865260e086600481885afa918215610604575f92610751575b600496506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016936001600160a01b038a1699858b145f1461074257506102e6610a54565b955b6001600160a01b0381169586036107345750610302610a54565b60208b6040519a8b80927f313ce5670000000000000000000000000000000000000000000000000000000082525afa988915610604575f996106f8575b50604051907f313ce5670000000000000000000000000000000000000000000000000000000082526020826004818a5afa918215610604575f926106bc575b50604051977fd0c93a7c0000000000000000000000000000000000000000000000000000000089526020896004818d5afa978815610604575f98610680575b6040517fddca3f43000000000000000000000000000000000000000000000000000000008152995060208a6004818e5afa998a15610604575f9a61063c575b506040519c6101c08e0167ffffffffffffffff81118f82101761060f576040528d5260208d019d8e5260408d0190815260608d0191825260808d0192835260a08d019b60ff168c5260c08d019360ff16845260e08d019485526101008d019560020b86526101208d019660020b87526101408d019760020b88526101608d019860020b89526101808d019962ffffff168a526101a08d019a8b52604051809e819e7fc49917d70000000000000000000000000000000000000000000000000000000083526004830160209052516024830152516001600160a01b03169060440152516001600160a01b031660648d01525160848c016101c090526101e48c0161050491610a8f565b9051908b81037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0160a48d015261053a91610a8f565b985160ff1660c48b01525160ff1660e48a01525115156101048901525160020b6101248801525160020b6101448701525160020b6101648601525160020b6101848501525162ffffff166101a4840152516001600160a01b03166101c48301520381731ca484ee7ae7fe5fd3bc4baef07905796efd6cda91815a935f94f48015610604576105de915f916105e2575b50604051918291602083526020830190610a8f565b0390f35b6105fe91503d805f833e6105f68183610a15565b810190610b80565b5f6105c9565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b9099506020813d602011610678575b8161065860209383610a15565b81010312610674575162ffffff8116810361067457985f6103fc565b5f80fd5b3d915061064b565b97506020893d6020116106b4575b8161069b60209383610a15565b81010312610674576106ae600499610b38565b976103bd565b3d915061068e565b9091506020813d6020116106f0575b816106d860209383610a15565b81010312610674576106e990610b72565b905f61037e565b3d91506106cb565b9098506020813d60201161072c575b8161071460209383610a15565b810103126106745761072590610b72565b975f61033f565b3d9150610707565b61073d90610be3565b610302565b61074b90610be3565b956102e8565b915060e0863d60e0116107db575b8161076c60e09383610a15565b810103126106745785516001600160a01b038116036106745760c061079360208801610b38565b966107a060408201610b63565b506107ad60608201610b63565b506107ba60808201610b63565b506107c760a08201610b72565b50015180151503610674576004959161029a565b3d915061075f565b90509161025c565b8197610254565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21546f6b656e4f726465720000000000000000000000000000000000000000006044820152fd5b90506020813d602011610882575b8161086b60209383610a15565b810103126106745761087c90610b24565b5f610112565b3d915061085e565b96509350505050610140833d8211610929575b816108ab6101409383610a15565b81010312610674576108bc83610b24565b926108c960208201610b24565b906108d660408201610b38565b94600460206108e760608501610b38565b9261091c6101206108fa60808801610b38565b9661090760a08201610b46565b506109156101008201610b46565b5001610b46565b50949792939591506100d2565b3d915061089d565b346106745760406003193601126106745761094a610ab4565b6024356001600160a01b03811681036106745761097161096b602093610aca565b91610aca565b12604051908152f35b34610674575f600319360112610674576105de610995610a54565b604051918291602083526020830190610a8f565b346106745760206003193601126106745760206109cc6109c7610ab4565b610aca565b604051908152f35b34610674575f600319360112610674576020906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b90601f601f19910116810190811067ffffffffffffffff82111761060f57604052565b67ffffffffffffffff811161060f57601f01601f191660200190565b60405190610a63604083610a15565b600182527f53000000000000000000000000000000000000000000000000000000000000006020830152565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b600435906001600160a01b038216820361067457565b6001600160a01b03807f000000000000000000000000000000000000000000000000000000000000000016911614610b00575f90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c90565b51906001600160a01b038216820361067457565b51908160020b820361067457565b51906fffffffffffffffffffffffffffffffff8216820361067457565b519061ffff8216820361067457565b519060ff8216820361067457565b6020818303126106745780519067ffffffffffffffff8211610674570181601f8201121561067457805190610bb482610a38565b92610bc26040519485610a15565b8284526020838301011161067457815f9260208093018386015e8301015290565b610bec81610d56565b90815115610bf8575090565b90506001600160a01b03610c0c6006610a38565b91610c1a6040519384610a15565b60068352601f19610c2b6006610a38565b01366020850137165f5b60038110610c4257505090565b8060130360138111610d29577f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103610d2957829060031b1c9060f0807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08416161660ff8316039160ff8311610d2957600f610cc39160041c16610f7c565b8160011b927f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83168303610d2957610d07915f1a610d018588610f3e565b53610f7c565b9160018101809111610d2957610d226001935f1a9186610f3e565b5301610c35565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8060609260405160208101907f95d89b4100000000000000000000000000000000000000000000000000000000825260048152610d95602482610a15565b51915afa903d15610f3857503d90610dac82610a38565b91610dba6040519384610a15565b82523d5f602084013e5b158015610f2f575b610f2057805160208103610eed575060208180518101031261067457602001519060405191610dfc604084610a15565b602080845236848201375f905f5b60208110610e94575050610e1d81610a38565b90610e2b6040519283610a15565b808252601f19610e3a82610a38565b013660208401375f5b818110610e51575090925050565b807fff00000000000000000000000000000000000000000000000000000000000000610e7f60019388610f3e565b51165f1a610e8d8286610f3e565b5301610e43565b81811a7fff000000000000000000000000000000000000000000000000000000000000008160f81b16610ecb575b50600101610e0a565b610ed88487959395610f3e565b535f198114610d295760018091019290610ec2565b9060408211610f0c575050604051610f06602082610a15565b5f815290565b602080610f1d938301019101610b80565b90565b50604051610f06602082610a15565b50805115610dcc565b90610dc4565b908151811015610f4f570160200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60ff16600a811015610fbb5760300160ff8111610d295760f81b7fff000000000000000000000000000000000000000000000000000000000000001690565b60370160ff8111610d295760f81b7fff00000000000000000000000000000000000000000000000000000000000000169056fea2646970667358221220dab4fcf429bfc2c6c582afa84ca25aa21a8873a2986cb2f3b210a546daae4c6564736f6c634300081c0033000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/QuoterV1.json b/test/foundry/bytecodes/shadow-cl/QuoterV1.json new file mode 100644 index 0000000..5a8b878 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/QuoterV1.json @@ -0,0 +1,3 @@ +{ + "bytecode": "60c03461008857601f610f0338819003918201601f19168301916001600160401b0383118484101761008c57808492604094855283398101031261008857610052602061004b836100a0565b92016100a0565b9060805260a052604051610e4e90816100b58239608051818181610298015281816103420152610941015260a0518161023c0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036100885756fe60806040526004361015610011575f80fd5b5f3560e01c806307e3c77c146100a45780632f80bb1d1461007f5780634aa4a4fc1461007a578063cdca175314610075578063d5f3948814610070578063e864cee31461006b5763fa461e3314610066575f80fd5b6102d8565b6102bc565b610279565b610260565b61021d565b346100a0576020610098610092366101eb565b90610782565b604051908152f35b5f80fd5b346100a05760206100986100b7366100d1565b9392909261062f565b6001600160a01b038116036100a057565b60031960a09101126100a0576004356100e9816100c0565b906024356100f6816100c0565b906044358060020b81036100a0579060643590608435610115816100c0565b90565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6060810190811067ffffffffffffffff82111761016157604052565b610118565b90601f601f19910116810190811067ffffffffffffffff82111761016157604052565b67ffffffffffffffff811161016157601f01601f191660200190565b81601f820112156100a0578035906101bc82610189565b926101ca6040519485610166565b828452602083830101116100a057815f926020809301838601378301015290565b60406003198201126100a0576004359067ffffffffffffffff82116100a057610216916004016101a5565b9060243590565b346100a0575f6003193601126100a05760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100a0576020610098610273366101eb565b906107b5565b346100a0575f6003193601126100a05760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100a05760206100986102cf366100d1565b93929092610892565b346100a05760606003193601126100a05760443560043560243567ffffffffffffffff83116100a0576103406103669161031860209536906004016101a5565b6103355f8613918280156103d8575b61033090610922565b610b04565b959194908686610c1b565b7f0000000000000000000000000000000000000000000000000000000000000000610dfb565b50156103b7576001600160a01b0361037e819261040e565b9493169116105b156103935750604051908152fd5b905f54806103a6575b5050604051908152fd5b6103b09114610922565b5f8061039c565b926001600160a01b036103cd819294939461040e565b949316911610610385565b505f8413610327565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f8000000000000000000000000000000000000000000000000000000000000000811461043a575f0390565b6103e1565b91908260409103126100a0576020825192015190565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b919360a09361011596956001600160a01b0380941685521515602085015260408401521660608201528160808201520190610455565b3d156104da573d906104c182610189565b916104cf6040519384610166565b82523d5f602084013e565b606090565b604091935f945f6001600160a01b0382166001600160a01b0385161083825561058661052c6105276105216105158b888b610929565b6001600160a01b031690565b96610969565b61040e565b93828414610611576105786401000276a4975b89519a8b93602085019192602b936bffffffffffffffffffffffff19809360601b16845260e81b601484015260601b1660178201520190565b03601f198101895288610166565b6105bf8651978896879586947f128acb08000000000000000000000000000000000000000000000000000000008652306004870161047a565b03925af190816105e3575b5061011557506101156105db6104b0565b5f8055610a17565b6106049060403d60401161060a575b6105fc8183610166565b81019061043f565b506105ca565b503d6105f2565b61057873fffd8963efd1fc6a506488495d951d5263988d259761053f565b604091939594955f965f6001600160a01b0387166001600160a01b038516106106d16001600160a01b03841615988961077a575b61067d6105276106776105158c858c610929565b97610969565b948a85146107705750828414610753576105786401000276a45b9789519a8b93602085019192602b936bffffffffffffffffffffffff19809360601b16845260e81b601484015260601b1660178201520190565b61070a8651978896879586947f128acb08000000000000000000000000000000000000000000000000000000008652306004870161047a565b03925af19081610735575b50610732576101159192506107286104b0565b906105db57610a17565b50565b61074d9060403d60401161060a576105fc8183610166565b50610715565b61057873fffd8963efd1fc6a506488495d951d5263988d25610697565b610578909761053f565b858455610663565b61079d6042825110159261079583610b04565b9190916104df565b91156107b1576107ac90610b60565b610782565b5090565b6107cf604282511015926107c883610b04565b90916107e3565b91156107b1576107de90610b60565b6107b5565b92906040915f945f6001600160a01b0384166001600160a01b0383161061081a61052c6108146105158a8988610929565b95610969565b6108538651978896879586947f128acb08000000000000000000000000000000000000000000000000000000008652306004870161047a565b03925af19081610874575b50610115575061011561086f6104b0565b610a17565b61088c9060403d60401161060a576105fc8183610166565b5061085e565b9392604092935f809661081a6001600160a01b0386166001600160a01b03831610916108c56105216105158b8a85610929565b946001600160a01b0381161585146107705750828414610753576105786401000276a49789519a8b93602085019192602b936bffffffffffffffffffffffff19809360601b16845260e81b601484015260601b1660178201520190565b156100a057565b6001600160a01b03926109659261093f92610c1b565b7f0000000000000000000000000000000000000000000000000000000000000000610c73565b1690565b7f80000000000000000000000000000000000000000000000000000000000000008110156100a05790565b6020818303126100a05780519067ffffffffffffffff82116100a0570181601f820112156100a0578051906109c882610189565b926109d66040519485610166565b828452602083830101116100a057815f9260208093018386015e8301015290565b906020610115928181520190610455565b908160209103126100a0575190565b805160208103610a3557508060208061011593518301019101610a08565b604411610a8b57610a55816024806004610a879501518301019101610994565b6040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352600483016109f7565b0390fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f556e6578706563746564206572726f72000000000000000000000000000000006044820152fd5b90601f820180921161043a57565b9190820180921161043a57565b6014815110610b3857602081015160601c916017825110610b3857601782015191602b815110610b38576037015160601c90565b7fb4120f14000000000000000000000000000000000000000000000000000000005f5260045ffd5b805190601782039180831161043a5782610b7981610ae9565b10610bf3578151610b8b846017610af7565b11610b3857601703610ba95750506040515f81526020810160405290565b60405191601f8116916017831560051b80858701019484860193010101905b808410610be05750508252601f01601f191660405290565b9092602080918551815201930190610bc8565b7f35278d12000000000000000000000000000000000000000000000000000000005f5260045ffd5b91906001600160a01b03905f60408051610c3481610145565b828152826020820152015281811682851611610c6d575b8160405194610c5986610145565b16845216602083015260020b604082015290565b92610c4b565b906001600160a01b038151169160208201926001600160a01b038451161115610d9d57610d03610d8e6101159484610d11610cd76040610cce610cc06105159a516001600160a01b031690565b95516001600160a01b031690565b93015160020b90565b604080516001600160a01b0395861660208201908152959094169084015260020b606083015281608081015b03601f198101835282610166565b51902060405192839160208301958690916bffffffffffffffffffffffff196055937fff00000000000000000000000000000000000000000000000000000000000000845260601b16600183015260158201527fc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d60358201520190565b5190206001600160a01b031690565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21546f6b656e4f726465720000000000000000000000000000000000000000006044820152fd5b6001600160a01b0391610e0d91610c73565b16908133036100a05756fea264697066735822122021c0cdfc2a9edfbf189f5e65f63e8d07b68580ce77a25f7f0de21a22b6f1129064736f6c634300081c00330000000000000000000000008bbdc15759a8ecf99a92e004e0c64ea9a5142d59000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/QuoterV2.json b/test/foundry/bytecodes/shadow-cl/QuoterV2.json new file mode 100644 index 0000000..6766b08 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/QuoterV2.json @@ -0,0 +1,3 @@ +{ + "bytecode": "60c03461008757601f61194438819003918201601f19168301916001600160401b0383118484101761008b57808492604094855283398101031261008757610052602061004b8361009f565b920161009f565b9060805260a05260405161189090816100b48239608051818181610395015281816104220152610e3b015260a05181609e0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036100875756fe60806040526004361015610011575f80fd5b5f3560e01c80632f80bb1d146100c65780634aa4a4fc1461007f5780639e7defe61461007a578063cdca175314610075578063d5f3948814610070578063fa461e331461006b5763fa6af90814610066575f80fd5b61058d565b6103b9565b610376565b61035c565b610302565b346100c2575f6003193601126100c25760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b5f80fd5b346100c2576100f06100e06100da366101ae565b90610665565b90604094929451948594856101e0565b0390f35b634e487b7160e01b5f52604160045260245ffd5b6060810190811067ffffffffffffffff82111761012457604052565b6100f4565b90601f601f19910116810190811067ffffffffffffffff82111761012457604052565b67ffffffffffffffff811161012457601f01601f191660200190565b81601f820112156100c25780359061017f8261014c565b9261018d6040519485610129565b828452602083830101116100c257815f926020809301838601378301015290565b60406003198201126100c2576004359067ffffffffffffffff82116100c2576101d991600401610168565b9060243590565b9493929060808601908652608060208701528251809152602060a087019301905f5b818110610251575050508482036040860152602080825193848152019101915f5b81811061023557505060609150930152565b835163ffffffff16835260209384019390920191600101610223565b82516001600160a01b0316855260209485019490920191600101610202565b6001600160a01b038116036100c257565b8060020b036100c257565b60031960a09101126100c2576040519060a0820182811067ffffffffffffffff82111761012457604052816004356102c381610270565b81526024356102d181610270565b602082015260443560408201526064356102ea81610281565b60608201526080608435916102fe83610270565b0152565b346100c25760a06003193601126100c2576100f06103276103223661028c565b61082c565b604080519485526001600160a01b03909316602085015263ffffffff9091169183019190915260608201529081906080820190565b346100c2576100f06100e0610370366101ae565b90610a45565b346100c2575f6003193601126100c25760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100c25760606003193601126100c25760043560243560443567ffffffffffffffff81116100c2576103f0903690600401610168565b9061040e5f841392838015610584575b61040990610aea565b610d0c565b92909193610446610420848688610fe6565b7f000000000000000000000000000000000000000000000000000000000000000061180c565b50156105515761048a61047e60049361046060e094610af1565b956001600160a01b0381166001600160a01b03891610989697610e23565b6001600160a01b031690565b604051928380927f3850c7bd0000000000000000000000000000000000000000000000000000000082525afa91821561054c576060945f925f94610510575b50156104e2575060405192835260208301526040820152fd5b925f54806104ff575b505060405192835260208301526040820152fd5b6105099114610aea565b5f806104eb565b90935061053691925060e03d60e011610545575b61052e8183610129565b810190610b2c565b5050505050919091925f6104c9565b503d610524565b6107e5565b9361048a61047e60049361056660e094610af1565b956001600160a01b0388166001600160a01b03821610989697610e23565b505f8313610400565b346100c25760a06003193601126100c2576100f06103276105ad3661028c565b610b9a565b67ffffffffffffffff81116101245760051b60200190565b906105d4826105b2565b6105e16040519182610129565b828152601f196105f182946105b2565b0190602036910137565b805182101561060f5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b90601f820180921161064557565b610623565b9190820180921161064557565b5f1981146106455760010190565b9190916107065f9261067e61067984610cda565b6105ca565b948561068c61067986610cda565b9461072861072261071b6106e95f965b6106de6001600160a01b036106b088610d0c565b60405195919391929082906106c660a089610129565b168652166020850152604084015260020b6060830152565b5f6080820152610b9a565b93929a90916106f88a8a6105fb565b906001600160a01b03169052565b610710888c6105fb565b9063ffffffff169052565b879961064a565b93610657565b946107368260429051101590565b15610767575090610748859392610d68565b91966107069550909190610728906107229061071b906106e99061069c565b9796509193505050565b91908260409103126100c2576020825192015190565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b919360a0936107e296956001600160a01b0380941685521515602085015260408401521660608201528160808201520190610787565b90565b6040513d5f823e3d90fd5b3d1561081a573d906108018261014c565b9161080f6040519384610129565b82523d5f602084013e565b606090565b9190820391821161064557565b905f915f5f905f9161084584516001600160a01b031690565b926020850194604061085e87516001600160a01b031690565b61088d6001600160a01b0382166001600160a01b03891610976060850192610887845160020b90565b91610e23565b966109925a9961095e6108a286880151610e63565b946108b760808901516001600160a01b031690565b6001600160a01b038116610a3257508415610a0c576109506109046108f66108ee6401000276a45b9b5b516001600160a01b031690565b935160020b90565b94516001600160a01b031690565b8851948593602085019192602b937fffffffffffffffffffffffffffffffffffffffff000000000000000000000000809360601b16845260e81b601484015260601b1660178201520190565b03601f198101835282610129565b845195869485947f128acb0800000000000000000000000000000000000000000000000000000000865230600487016107ac565b03815f6001600160a01b038a165af190816109de575b506109d7575050506109cf9293506109c96109c16107f0565b925a9061081f565b91610e8e565b929391929091565b9250925092565b6109ff9060403d604011610a05575b6109f78183610129565b810190610771565b506109a8565b503d6109ed565b6109506109046108f66108ee73fffd8963efd1fc6a506488495d951d5263988d256108df565b6109046108f66108ee610950939b6108e1565b9190916107065f92610a5961067984610cda565b9485610a6761067986610cda565b94610aab61072261071b6106e95f965b610aa06001600160a01b03610a8b88610d0c565b604051959193919282906106c660a089610129565b5f608082015261082c565b94610ab98260429051101590565b15610767575090610acb859392610d68565b91966107069550909190610aab906107229061071b906106e990610a77565b156100c257565b7f80000000000000000000000000000000000000000000000000000000000000008114610645575f0390565b519061ffff821682036100c257565b908160e09103126100c2578051610b4281610270565b916020820151610b5181610281565b91610b5e60408201610b1d565b91610b6b60608301610b1d565b91610b7860808201610b1d565b9160a082015160ff811681036100c25760c09092015180151581036100c25790565b90610c4b5f925f905f915f92610bb783516001600160a01b031690565b93602084016040610bcf82516001600160a01b031690565b95610bf96001600160a01b0388166001600160a01b038a16109860608301986108878a5160020b90565b9760808201998a926001600160a01b03610c1a85516001600160a01b031690565b1615610cbb575b61095e5a9a6108b7610c3d610c3889860151610e63565b610af1565b96516001600160a01b031690565b03815f6001600160a01b038b165af19081610c9d575b50610c94575050506109cf939450610c8861047e6108f6610c806107f0565b935a9061081f565b610e8e575f8055610e8e565b93509350939050565b610cb59060403d604011610a05576109f78183610129565b50610c61565b848101515f55610c21565b634e487b7160e01b5f52601260045260245ffd5b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec8101908111610645576017900490565b6014815110610d4057602081015160601c916017825110610d4057601782015191602b815110610d40576037015160601c90565b7fb4120f14000000000000000000000000000000000000000000000000000000005f5260045ffd5b80519060178203918083116106455782610d8181610637565b10610dfb578151610d9384601761064a565b11610d4057601703610db15750506040515f81526020810160405290565b60405191601f8116916017831560051b80858701019484860193010101905b808410610de85750508252601f01601f191660405290565b9092602080918551815201930190610dd0565b7f35278d12000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b0392610e5f92610e3992610fe6565b7f000000000000000000000000000000000000000000000000000000000000000061103e565b1690565b7f80000000000000000000000000000000000000000000000000000000000000008110156100c25790565b919092604051927f3850c7bd00000000000000000000000000000000000000000000000000000000845260e0846004816001600160a01b0389165afa93841561054c575f94610fbe575b50805160608103610f0a5750610efa81602080610f0394518301019101611243565b9195909661133b565b9293929190565b604411610f6057610f2a816024806004610f5c95015183010191016111cf565b6040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301611232565b0390fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f556e6578706563746564206572726f72000000000000000000000000000000006044820152fd5b610fd891945060e03d60e0116105455761052e8183610129565b50505050509050925f610ed8565b91906001600160a01b03905f60408051610fff81610108565b828152826020820152015281811682851611611038575b816040519461102486610108565b16845216602083015260020b604082015290565b92611016565b906001600160a01b038151169160208201926001600160a01b038451161115611171576109506111626107e294846110d26110a2604061109961108b61047e9a516001600160a01b031690565b95516001600160a01b031690565b93015160020b90565b604080516001600160a01b0395861660208201908152959094169084015260020b60608301528160808101610950565b51902060405192839160208301958690917fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006055937fff00000000000000000000000000000000000000000000000000000000000000845260601b16600183015260158201527fc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d60358201520190565b5190206001600160a01b031690565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21546f6b656e4f726465720000000000000000000000000000000000000000006044820152fd5b6020818303126100c25780519067ffffffffffffffff82116100c2570181601f820112156100c2578051906112038261014c565b926112116040519485610129565b828452602083830101116100c257815f9260208093018386015e8301015290565b9060206107e2928181520190610787565b908160609103126100c2578051916040602083015161126181610270565b9201516107e281610281565b908160209103126100c257516107e281610281565b60020b9060020b9081156112c0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000081145f19831416610645570590565b610cc6565b9060020b9081156112c05760020b0790565b908160209103126100c2575190565b60ff1660ff039060ff821161064557565b9063ffffffff8091169116019063ffffffff821161064557565b60010b617fff81146106455760010190565b63ffffffff5f199116019063ffffffff821161064557565b90916001600160a01b035f9216936040516334324e9f60e21b8152602081600481895afa801561054c5761137e61138a91611390935f916117ed575b5087611282565b60020b60081d60020b90565b60010b90565b916040516334324e9f60e21b81526020816004818a5afa801561054c576113c66113d1916113d7935f916117ce575b5088611282565b6101009060020b0790565b60ff1690565b946040516334324e9f60e21b81526020816004818b5afa801561054c5761137e61138a9161140d935f916117af575b5085611282565b926040516334324e9f60e21b81526020816004818c5afa801561054c576113c66113d191611443935f91611790575b5086611282565b6040517f5339c296000000000000000000000000000000000000000000000000000000008152600186900b60048201529095906020816024818d5afa90811561054c575f91611771575b50600160ff88161b1615159283611718575b83611707575b6040517f5339c296000000000000000000000000000000000000000000000000000000008152600183900b60048201526020816024818e5afa90811561054c575f916116e8575b50600160ff8b161b161515948561167e575b8561166c575b50508460010b8160010b9080821291821561164c575b5050156116395790969095939493905f1960ff9091161b5b8560010b8760010b81811361160957146115ed575b6040517f5339c296000000000000000000000000000000000000000000000000000000008152600188900b6004820152916020836024818d5afa801561054c576115a46115b1936115ab926115b7965f916115bf575b5016611829565b61ffff1690565b906112f7565b95611311565b945f19611532565b6115e0915060203d81116115e6575b6115d88183610129565b8101906112d7565b5f61159d565b503d6115ce565b6116036115f9866112e6565b60ff5f1991161c90565b16611547565b5050509596509250925050611629575b6116205790565b6107e290611323565b9061163390611323565b90611619565b9096939590945f1960ff9091161b611532565b1490508061165c575b5f8061151a565b5060ff861660ff89161115611655565b600290810b91900b1293505f80611504565b6040516334324e9f60e21b81529095506020816004818e5afa801561054c576116af915f916116b9575b50826112c5565b60020b15946114fe565b6116db915060203d6020116116e1575b6116d38183610129565b81019061126d565b5f6116a8565b503d6116c9565b611701915060203d6020116115e6576115d88183610129565b5f6114ec565b92508360020b8360020b13926114a5565b92506040516334324e9f60e21b81526020816004818d5afa801561054c57611748915f91611752575b50856112c5565b60020b159261149f565b61176b915060203d6020116116e1576116d38183610129565b5f611741565b61178a915060203d6020116115e6576115d88183610129565b5f61148d565b6117a9915060203d6020116116e1576116d38183610129565b5f61143c565b6117c8915060203d6020116116e1576116d38183610129565b5f611406565b6117e7915060203d6020116116e1576116d38183610129565b5f6113bf565b611806915060203d6020116116e1576116d38183610129565b5f611377565b6001600160a01b039161181e9161103e565b16908133036100c257565b805f915b611835575090565b9061ffff1661ffff811461064557600101905f1981019080821161064557168061182d56fea2646970667358221220db838931796195cf33783f1a632839cac41126ea574974045f719eca1c12089b64736f6c634300081c00330000000000000000000000008bbdc15759a8ecf99a92e004e0c64ea9a5142d59000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/RamsesV3Factory.json b/test/foundry/bytecodes/shadow-cl/RamsesV3Factory.json new file mode 100644 index 0000000..9ec776f --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/RamsesV3Factory.json @@ -0,0 +1,3 @@ +{ + "bytecode": "0x6080346101f457601f610edf38819003918201601f19168301916001600160401b038311848410176101f9578084926020946040528339810103126101f457516001600160a01b038116908190036101f45760018060a01b03196005541617600555600160005260016020526040600020606462ffffff198254161790557f7a8f5b6a3fe6312faf94330e829a331301dbd2ce6947e915be63bf67b473ed5f6040805160646001600080516020610ebf833981519152600080a3600560005260016020528160002060fa62ffffff1982541617905560fa6005600080516020610ebf833981519152600080a3600a6000526001602052816000206101f462ffffff198254161790556101f4600a600080516020610ebf833981519152600080a36032600052600160205281600020610bb862ffffff19825416179055610bb86032600080516020610ebf833981519152600080a3606460005260016020528160002061271062ffffff198254161790556127106064600080516020610ebf833981519152600080a360c8600052600160205281600020614e2062ffffff19825416179055614e2060c8600080516020610ebf833981519152600080a36004805460ff19166005908117909155600080546001600160a01b0319163317815582526020820152a1604051610caf90816102108239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c8063232aa5ac1461081957806328af8d0b146107ac5780633cb08b53146106fa57806346c96aac146106d15780634bc2a65714610684578063527eb4bc1461066357806376734e3e1461057a578063890357301461051e578063a42dce8014610491578063b613a141146103fe578063ba364c3d14610332578063bf49a2921461030b578063c415b95c146102de578063c4d66de814610291578063cf3a52a61461025a578063e7589b3914610231578063ebb0d9f7146102025763eee0fdb4146100e357600080fd5b346101ff5760403660031901126101ff576100fc610bb4565b62ffffff610108610bc4565b61011d60018060a01b03600554163314610c0e565b1690620f42408210156101f05760020b828113806101e5575b156101bb57808352600160205262ffffff60408420541661019057808352600160205260408320805462ffffff1916831790557febafae466a4a780a1d87f5fab2f52fad33be9151a7f69d099e8934c8de85b7478380a380f35b606460405162461bcd60e51b81526020600482015260046024820152630545321360e41b6044820152fd5b60405162461bcd60e51b8152602060048201526002602482015261545360f01b6044820152606490fd5b506140008112610136565b6316326a1b60e21b8352600483fd5b80fd5b50346101ff5760203660031901126101ff576020610226610221610b73565b610c40565b60ff60405191168152f35b50346101ff57806003193601126101ff576005546040516001600160a01b039091168152602090f35b50346101ff5760203660031901126101ff5762ffffff604060209261027d610bb4565b60020b815260018452205416604051908152f35b50346101ff5760203660031901126101ff576102ab610b73565b815490336001600160a01b038316036102da576001600160a01b03166001600160a01b03199190911617815580f35b8280fd5b50346101ff57806003193601126101ff5760045460405160089190911c6001600160a01b03168152602090f35b50346101ff57806003193601126101ff57546040516001600160a01b039091168152602090f35b50346101ff5760403660031901126101ff5761034c610b73565b610354610bc4565b9061036a60018060a01b03600554163314610c0e565b6001600160a01b031690813b156102da578262ffffff6040519263755dab1160e11b84521691826004820152818160248183885af180156103f3576103de575b507fe4accbaee82fb833ac207d4c4454c5a04e85f5e1e9a20a9e2c98e54e8706ff2b6040848482519182526020820152a180f35b816103e891610bd6565b6102da5782386103aa565b6040513d84823e3d90fd5b50346101ff5760203660031901126101ff5760043560ff811680910361048d5761043360018060a01b03600554163314610c0e565b6064811161047e5760407f7a8f5b6a3fe6312faf94330e829a331301dbd2ce6947e915be63bf67b473ed5f91600454908060ff1983161760045560ff8351921682526020820152a180f35b6316326a1b60e21b8252600482fd5b5080fd5b50346101ff5760203660031901126101ff576104ab610b73565b6104c060018060a01b03600554163314610c0e565b600454906001600160a01b0380821690600884901c167f649c5e3d0ed183894196148e193af316452b0037e77d2ff0fef23b7dc722bed08580a3610100600160a81b031990911660089190911b610100600160a81b03161760045580f35b50346101ff57806003193601126101ff57600754600854600954604080516001600160a01b03948516815292841660208401529281169282019290925260a082811c62ffffff16606083015260b89290921c60020b6080820152f35b50346101ff5760403660031901126101ff57610594610b73565b9060243560ff811680910361048d576105b860018060a01b03600554163314610c0e565b6064811161047e577fa667945ce175575f1ba112f8598cad43210716077bdcabd4d73f2397a81e59bd6060846105ee8596610c40565b9060018060a01b0316938486526003602052604086208160ff1982541617905560ff604051928684521660208301526040820152a1803b1561066057818091600460405180948193637b7d549d60e01b83525af180156103f35761064f5750f35b8161065991610bd6565b6101ff5780f35b50fd5b50346101ff57806003193601126101ff57602060ff60045416604051908152f35b50346101ff5760203660031901126101ff5761069e610b73565b6106b360018060a01b03600554163314610c0e565b60018060a01b03166001600160601b0360a01b600654161760065580f35b50346101ff57806003193601126101ff576006546040516001600160a01b039091168152602090f35b50346101ff5760203660031901126101ff5780610715610b73565b6006546001600160a01b0316331461075e576001600160a01b0316803b1561066057818091600460405180948193637b7d549d60e01b83525af180156103f35761064f57505080f35b6001600160a01b0316808252600360205260408220805460ff19166064179055803b1561066057818091600460405180948193637b7d549d60e01b83525af180156103f35761064f57505080f35b50346101ff5760603660031901126101ff576107c6610b73565b9060406107d1610b8e565b916107da610ba4565b6001600160a01b0394851682526002602081815293909220938516600090815293835260408085209190920b8452825291829020549151919092168152f35b50346101ff5760803660031901126101ff57610833610b73565b9061083c610b8e565b90610845610ba4565b6064356001600160a01b03811694908590036102da576001600160a01b03848116908216808214610b64571015610b5e575b6001600160a01b0316928315610b4f578160020b938484526001602052604084205462ffffff8116938415610b40578286526002602090815260408088206001600160a01b038781168a529083528189208a8a5290925287205416610b31576040519360a0850185811067ffffffffffffffff821117610b1d57889160809160405230875285602088015260018060a01b0316958660408201528760608201520152306001600160601b0360a01b6007541617600755826001600160601b0360a01b6008541617600855836001600160601b0360a01b60095416176009556009549060b81b62ffffff60b81b169162ffffff60a01b9060a01b169065ffffffffffff60a01b1916171760095583602060018060a01b03825416606460405180948193635f90b0b360e11b83528760048401528860248401528b60448401525af1908115610b12578591610acb575b506007859055600885905560098590558185526002602081815260408088208689528252808820898952825280882080546001600160a01b03959095166001600160a01b03199586168117909155868952928252808820858952825280882089895282528088208054909416831790935582519788528701819052957f783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b71189190a482610a76575b602082604051908152f35b813b156101ff576040519263f637731d60e01b84526004840152808360248183865af1928315610abe57602093610aae575b50610a6b565b81610ab891610bd6565b38610aa8565b50604051903d90823e3d90fd5b90506020813d602011610b0a575b81610ae660209383610bd6565b81010312610b0657516001600160a01b0381168103610b065760406109c5565b8480fd5b3d9150610ad9565b6040513d87823e3d90fd5b634e487b7160e01b88526041600452602488fd5b636d47e01d60e01b8652600486fd5b63f704e89960e01b8652600486fd5b635cc23f7d60e01b8352600483fd5b92610877565b63a8fa826d60e01b8552600485fd5b600435906001600160a01b0382168203610b8957565b600080fd5b602435906001600160a01b0382168203610b8957565b604435908160020b8203610b8957565b600435908160020b8203610b8957565b6024359062ffffff82168203610b8957565b90601f8019910116810190811067ffffffffffffffff821117610bf857604052565b634e487b7160e01b600052604160045260246000fd5b15610c1557565b606460405162461bcd60e51b815260206004820152600460248201526310a3a7ab60e11b6044820152fd5b6001600160a01b031660008181526003602052604090205460ff16610c655750600590565b600052600360205260ff604060002054169056fea2646970667358221220efdcad1a8af661dd8865b49dcd5c67e1dda5628cd5dd1cb6370bdfdf198def2464736f6c634300081a0033ebafae466a4a780a1d87f5fab2f52fad33be9151a7f69d099e8934c8de85b747" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/RamsesV3PoolDeployer.json b/test/foundry/bytecodes/shadow-cl/RamsesV3PoolDeployer.json new file mode 100644 index 0000000..bbb1250 --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/RamsesV3PoolDeployer.json @@ -0,0 +1,3 @@ +{ + "bytecode": "60a034607357601f61605138819003918201601f19168301916001600160401b03831184841017607757808492602094604052833981010312607357516001600160a01b0381168103607357608052604051615fc5908161008c823960805181818160990152818161018201526101ec0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c90816335c8692b146102df5750806389035730146101a65780639f38f740146101635763bf21616614610048575f80fd5b3461015f57606036600319011261015f576004356001600160a01b03811680910361015f576024356001600160a01b03811680910361015f576044358060020b80910361015f576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016330361015f57604051916020830193845260408301526060820152606081526100e360808261033a565b519020604051615c1f80820182811067ffffffffffffffff821117610132578291610371833903905ff58015610127576020906001600160a01b0360405191168152f35b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80fd5b3461015f575f36600319011261015f5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461015f575f36600319011261015f576040517f8903573000000000000000000000000000000000000000000000000000000000815260a0816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa8015610127575f905f5f905f945f93610259575b50936001600160a01b0362ffffff928160a097816040519816885216602087015216604085015216606083015260020b6080820152f35b94505050505060a0813d60a0116102d7575b8161027860a0938361033a565b8101031261015f576102898161035c565b906102966020820161035c565b906102a36040820161035c565b9060608101519062ffffff8216820361015f57608001518060020b810361015f579093929091906001600160a01b03610222565b3d915061026b565b3461015f575f36600319011261015f576040615c1f91610302602084018261033a565b828152602081019261037184398151928391602083525180918160208501528484015e5f828201840152601f01601f19168101030190f35b90601f8019910116810190811067ffffffffffffffff82111761013257604052565b51906001600160a01b038216820361015f5756fe610120806040523461022b57630890357360e41b815260a081600481335afa90811561024a575f905f905f905f905f9561019d575b5062ffffff908560e0521662ffffff195f516020615bff5f395f51905f525416175f516020615bff5f395f51905f525560c05260a05260805260020b80156101895760018162ffffff92620d89e71905818080620d89e805920260020b910260020b0360020b05821601168015610189576001600160801b030461010052604051615995908161026a823960805181818161055301528181610867015281816110cc015261165e015260a051818181610c310152818161115501528181611de6015281816134470152818161399f0152614d99015260c0518181816107e501528181610bdc0152818161118401528181611db6015281816133780152614d14015260e051818181610821015281816123b2015281816124380152818161255001528181612e8a01528181612fb101528181613042015281816130870152614f360152610100518181816116e10152614f630152f35b634e487b7160e01b5f52601260045260245ffd5b94505050505060a03d60a011610243575b601f8101601f191682016001600160401b0381118382101761022f5760a09183916040528101031261022b576101e381610255565b906101f060208201610255565b906101fd60408201610255565b9060608101519062ffffff8216820361022b5760800151938460020b850361022b5792919062ffffff610034565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b503d6101ae565b6040513d5f823e3d90fd5b51906001600160a01b038216820361022b5756fe6080806040526004361015610012575f80fd5b5f905f3560e01c9081630dfe16811461398257508063128acb081461216c5780631a686502146121395780631ad8b03b146120bb578063252c09d71461202d57806332148f6714611f055780633850c7bd14611e835780634614131914611e46578063490e6cbc14611977578063514ea4bf146118f05780635339c296146118915780636847456a1461170557806370cf754a146116c15780637b7d549d146115c75780638221b8c1146112ed57806385b6672914611021578063883bdbfd14610df95780639918fbb614610c7d578063a02f1069146109e8578063a38807f2146108a7578063c2e0f9b21461088b578063c45a015514610847578063d0c93a7c14610809578063d21220a7146107c5578063d340ef8a14610788578063ddca3f4314610746578063e57c0ca914610674578063ea4a1104146105e7578063eabb5622146104a2578063f305839914610465578063f30dba93146103a65763f637731d1461017e575f80fd5b346103a35760203660031901126103a3576101976139c3565b6001600160a01b035f5160206159005f395f51905f52541661037b576040816101e07f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9593614632565b9082516101ec81613af7565b8581526020808201878152858301888152600160608501529251905192519290911b6affffffffffffff000000001663ffffffff919091161760589190911b7effffffffffffffffffffffffffffffffffffffff00000000000000000000001617600160f81b175f5160206159405f395f51905f525561026a613d52565b6001600160a01b0383519161027e83613a8e565b16808252600283900b602080840182905285840188905260016060850181905260808501819052600560a08087019190915260c0909501525f5160206159005f395f51905f5280547901000000000000000000000000000000000000000000000000009690951b62ffffff60a01b167fffffffffff00000000000000000000000000000000000000000000000000000090951666ffffffffffffff60a01b1985161794909417949094177fff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0105000100000000000000000000000000000000000000000000000000000017909255835190815291820152a180f35b6004827f9cc0b7f8000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346103a35760203660031901126103a3576101006103f66103c6613a37565b60020b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280660205260405f2090565b8054906001810154906003600282015491015491604051936001600160801b038116855260801d600f0b6020850152604084015260608301528060060b60808301526001600160a01b038160381c1660a083015263ffffffff8160d81c1660c083015260f81c151560e0820152f35b50346103a357806003193601126103a35760207ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280254604051908152f35b50346103a35760203660031901126103a3576004359062ffffff82168092036103a3575f5160206159005f395f51905f52549160ff8360f01c16156105d85760ff60f01b198293165f5160206159005f395f51905f5255730c2e1dd2960879f9461c1d2f6472b72ba12bd61790813b156105d45782906044604051809481937f4f67424900000000000000000000000000000000000000000000000000000000835260048301526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248301525af480156105c9576105b4575b50600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525580f35b816105be91613b13565b6103a357805f610585565b6040513d84823e3d90fd5b5050fd5b6004826350dfbc4360e11b8152fd5b50346103a35760203660031901126103a357604060809160043581525f5160206158e05f395f51905f526020522060606040519161062483613af7565b5463ffffffff8116928381528160201c60020b908160208201526001600160a01b038360381c60020b9384604084015260501c169384910152604051938452602084015260408301526060820152f35b50346103a35760203660031901126103a35760043567ffffffffffffffff8111610742576106a6903690600401613a5d565b906106b082613d3a565b906106be6040519283613b13565b8282526106ca83613d3a565b6020830190601f1901368237845b848110156106fc576001908060051b840135546106f58287614024565b52016106d8565b5091925050604051928392602084019060208552518091526040840192915b818110610729575050500390f35b825184528594506020938401939092019160010161071b565b5080fd5b50346103a357806003193601126103a357602062ffffff7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb28015416604051908152f35b50346103a357806003193601126103a35760207ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc280954604051908152f35b50346103a357806003193601126103a35760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346103a357806003193601126103a35760206040517f000000000000000000000000000000000000000000000000000000000000000060020b8152f35b50346103a357806003193601126103a35760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346103a357806003193601126103a3576108a4613d52565b80f35b50346103a35760403660031901126103a3576108c1613a37565b906108ca613a07565b6108d4818461523c565b604051927f9b7beb6000000000000000000000000000000000000000000000000000000000845260020b600484015260020b602483015263ffffffff421660448301526060826064817350f6a754f94a6a5ee3d887e6b1f12b55aee0c69c5af49182156109db57818091819461096e575b60608463ffffffff876001600160a01b03876040519460060b8552166020840152166040820152f35b92509250506060813d6060116109d3575b8161098c60609383613b13565b810103126107425780518060060b81036109cf5760406109ae60208401613bab565b9201519263ffffffff841684036103a3575090806001600160a01b03610945565b8280fd5b3d915061097f565b50604051903d90823e3d90fd5b50346103a35760c03660031901126103a357610a026139c3565b90610a0b613a17565b610a13613a27565b92610a1c613a47565b9360a4356001600160801b038116808203610c79575f5160206159005f395f51905f525460ff8160f01c1615610c6a5760ff60f01b19165f5160206159005f395f51905f525560405160208101903360601b825260243560348201528660e81b60548201528460e81b6057820152603a8152610a99605a82613b13565b51902086527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280860205260036040872001918254966001600160801b03881698896001600160801b038216115f14610c64575088975b60801c92839150115f14610c5c5750955b856001600160801b0381169182610c06575b50506001600160801b0387169182610ba8575b506001600160a01b03604051941684526020840152604083015260020b9160020b907f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c060603392a45f5160206159005f395f51905f52805460ff60f01b1916600160f01b179055604080516001600160801b03928316815292909116602083015290f35b80546001600160801b038116608091821c8a900390911b6fffffffffffffffffffffffffffffffff1916179055610c0082857f0000000000000000000000000000000000000000000000000000000000000000614bec565b5f610b24565b83546fffffffffffffffffffffffffffffffff19169190036001600160801b0316178255610c5581857f0000000000000000000000000000000000000000000000000000000000000000614bec565b855f610b11565b905095610aff565b97610aee565b6004876350dfbc4360e11b8152fd5b8580fd5b50346103a35760a03660031901126103a357602435906001600160a01b0382168092036103a357610cac613a27565b916084358060020b8091036109cf576040519360c0850185811067ffffffffffffffff821117610de5579063ffffffff939291604052600435865260208601928352604086016044358152606087019160020b8252608087019283526001600160a01b0360a08801948642168652604051987fd2e6311b000000000000000000000000000000000000000000000000000000008a525160048a0152511660248801525160448701525160020b60648601525160020b6084850152511660a483015260208260c481734bd87e0077d12b9b18b158dbe5ea7944135318e65af4908115610dd95790610da2575b602090604051908152f35b506020813d602011610dd1575b81610dbc60209383613b13565b81010312610dcd5760209051610d97565b5f80fd5b3d9150610daf565b604051903d90823e3d90fd5b602485634e487b7160e01b81526041600452fd5b50346103a35760203660031901126103a35760043567ffffffffffffffff811161074257610e2b903690600401613a5d565b919063ffffffff4216925f5160206159005f395f51905f52548060a01c60020b61ffff8260b81c169061ffff6001600160801b035f5160206158c05f395f51905f5254169360c81c1693610e7e81613d3a565b95610e8c6040519788613b13565b818752602087019160051b81019036821161101d57915b818310610ffc575050508315610fed57845196610ed8610ec289613d3a565b98610ed06040519a8b613b13565b808a52613d3a565b602089019690601f1901368837805196610ef4610ec289613d3a565b602089019190601f1901368337895b8b8451821015610f6457908a610f5882600194816001600160a01b038f8f8f918f918f938f93610f4f9563ffffffff610f3f8a610f4798614024565b51169061497d565b939097614024565b91169052614024565b9060060b905201610f03565b8a90848d8560405194859460408601906040875251809152606086019290845b818110610fd1575050506020908583038287015251918281520192915b818110610faf575050500390f35b82516001600160a01b0316845285945060209384019390920191600101610fa1565b825160060b855288975060209485019490920191600101610f84565b600486636b93000360e11b8152fd5b823563ffffffff8116810361101957815260209283019201610ea3565b8980fd5b8880fd5b50346103a35760603660031901126103a35761103b6139c3565b906024356001600160801b03811680910361074257604435906001600160801b0382168092036109cf575f5160206159005f395f51905f525460ff8160f01c16156112de5760ff60f01b19165f5160206159005f395f51905f52556040517fc415b95c0000000000000000000000000000000000000000000000000000000081526020816004816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156112d3578490611286575b6001600160a01b03915016330361125e576001600160a01b03604051947fb81955c9000000000000000000000000000000000000000000000000000000008652166004850152602484015260448301526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660648301526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016608483015260408260a481730c2e1dd2960879f9461c1d2f6472b72ba12bd6175af49182156109db57818093611213575b50505f5160206159005f395f51905f52805460ff60f01b1916600160f01b179055604080516001600160801b03928316815292909116602083015290f35b915091506040823d604011611256575b8161123060409383613b13565b810103126103a3575061124e602061124783613d26565b9201613d26565b905f806111d5565b3d9150611223565b6004837f3d83866f000000000000000000000000000000000000000000000000000000008152fd5b506020813d6020116112cb575b816112a060209383613b13565b810103126112c757516001600160a01b03811681036112c7576001600160a01b03906110fb565b8380fd5b3d9150611293565b6040513d86823e3d90fd5b6004846350dfbc4360e11b8152fd5b50346103a35760c03660031901126103a3576113076139c3565b61130f613a17565b611317613a27565b91611320613a47565b9260a43567ffffffffffffffff8111610c79576113419036906004016139d9565b9390945f5160206159005f395f51905f525460ff8160f01c16156115b85760ff60f01b19165f5160206159005f395f51905f52556001600160801b0390611386613d52565b169586156103a35786600f0b93878503610dcd576113e1906001600160a01b03604051916113b383613adb565b1693848252602435602083015260020b9485604083015260020b95866060830152600f0b6080820152614e88565b969150968290839189151591826115a8575b8915159485611598575b333b15611594578a8c61143f899360405195869485947fd348799700000000000000000000000000000000000000000000000000000000865260048601613c8e565b038183335af18015611589578b9291879161156a575b505082611550575b50506115285786908261150e575b50506114e657507f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde608060409788519033825260208201528789820152866060820152a4600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525582519182526020820152f35b807f20e5672e0000000000000000000000000000000000000000000000000000000060049252fd5b6115189250613be3565b611520614cf1565b10855f61146b565b6004837f748800af000000000000000000000000000000000000000000000000000000008152fd5b61155a9250613be3565b611562614d76565b10885f61145d565b819293509061157891613b13565b611585578990855f611455565b8480fd5b6040513d88823e3d90fd5b8680fd5b93506115a2614cf1565b936113fd565b90506115b2614d76565b906113f3565b6004886350dfbc4360e11b8152fd5b50346103a357806003193601126103a3575f5160206159005f395f51905f525460ff8160f01c16156105d85760ff60f01b19165f5160206159005f395f51905f525580730c2e1dd2960879f9461c1d2f6472b72ba12bd617803b156116be5781602491604051928380927f425fb0030000000000000000000000000000000000000000000000000000000082526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048301525af480156105c9576105b45750600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525580f35b50fd5b50346103a357806003193601126103a35760206040516001600160801b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346103a35760803660031901126103a35761171f613a07565b90611728613a17565b606435906001600160801b0382168092036109cf575f5160206159005f395f51905f525460ff8160f01c16156112de5760ff60f01b19165f5160206159005f395f51905f5255611776613d52565b81600f0b90828203610dcd576117c160409586519061179482613adb565b338252600435602083015260020b92838883015260020b938460608301528603600f0b6080820152614e88565b818703968190039592911580159190611887575b50611849575b50855190815284602082015283868201527f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c60603392a4600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525582519182526020820152f35b60030180546001600160801b038781168183160181166fffffffffffffffffffffffffffffffff19918816608093841c0190921b161790555f6117db565b905015155f6117d5565b50346103a35760203660031901126103a357600435908160010b82036103a35760206118e78360010b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280760205260405f2090565b54604051908152f35b50346103a35760203660031901126103a357604060a09160043581527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2808602052206001600160801b03815416906001810154906003600282015491015491604051938452602084015260408301526001600160801b038116606083015260801c6080820152f35b50346103a35760803660031901126103a3576119916139c3565b906024356044359260643567ffffffffffffffff81116112c7576119b99036906004016139d9565b90945f5160206159005f395f51905f525460ff8160f01c1615611e375760ff60f01b19165f5160206159005f395f51905f52556001600160801b035f5160206158c05f395f51905f525416908115611e0f5762ffffff7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2801541691611a47611a408488614e42565b9383614e42565b90611a50614d76565b94611a59614cf1565b9988611ddf575b84611daf575b333b1561101957611aa9918a9160405193849283927fe9cbafb0000000000000000000000000000000000000000000000000000000008452888b60048601613c8e565b038183335af18015611da457908991611d8b575b5050611ac7614d76565b9182611adb611ad4614cf1565b9688613be3565b11611d6357611aeb85918b613be3565b11611d3b576001600160a01b03969798858303948181039660ff5f5160206159005f395f51905f525460e81c169403611c66575b03611b92575b505060405195865260208601526040850152606084015216907fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca63360803392a3600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525580f35b611bb69180611c5b5750885b6001600160801b03811680611c02575b508503614453565b7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280354017ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2803555f80611b25565b6001600160801b03611c55915f5160206159205f395f51905f525460801c01166001600160801b035f5160206159205f395f51905f52549181199060801b169116175f5160206159205f395f51905f5255565b5f611bae565b606490860204611b9e565b83611d2c57611c89838c5b6001600160801b03811680611cd3575b508803614453565b7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280254017ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280255611b1f565b6001600160801b03611d2691815f5160206159205f395f51905f52541601166001600160801b03166001600160801b03195f5160206159205f395f51905f525416175f5160206159205f395f51905f5255565b5f611c81565b611c8983606486890204611c71565b6004887fe90c3493000000000000000000000000000000000000000000000000000000008152fd5b6004897ff704e899000000000000000000000000000000000000000000000000000000008152fd5b81611d9591613b13565b611da057875f611abd565b8780fd5b6040513d8b823e3d90fd5b611dda85897f0000000000000000000000000000000000000000000000000000000000000000614bec565b611a66565b611e0a89897f0000000000000000000000000000000000000000000000000000000000000000614bec565b611a60565b6004867f9f13f76d000000000000000000000000000000000000000000000000000000008152fd5b6004866350dfbc4360e11b8152fd5b50346103a357806003193601126103a35760207ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280354604051908152f35b50346103a357806003193601126103a35760e0611e9e613b35565b6001600160a01b0381511690602081015160020b9061ffff60408201511661ffff60608301511661ffff6080840151169160c060ff60a086015116940151151594604051968752602087015260408601526060850152608084015260a083015260c0820152f35b50346103a35760203660031901126103a35760043561ffff81168103610742575f5160206159005f395f51905f525460ff8160f01c161561201e57907fff00ff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffff7cffff000000000000000000000000000000000000000000000000000000611fae61ffff8560ff60f01b19600160f01b97165f5160206159005f395f51905f525560d81c169384614dcc565b5f5160206159005f395f51905f52549361ffff8216808203611fe7575b505060d81b16911617175f5160206159005f395f51905f525580f35b7fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a9160409182519182526020820152a15f80611fcb565b6004836350dfbc4360e11b8152fd5b50346103a35760203660031901126103a35760043561ffff8110156120a75760809150612068905f5160206159405f395f51905f5201613ce3565b63ffffffff81511690602081015160060b9060606001600160a01b03604083015116910151151591604051938452602084015260408301526060820152f35b602482634e487b7160e01b81526032600452fd5b50346103a357806003193601126103a3576040516040810181811067ffffffffffffffff8211176121255760409081525f5160206159205f395f51905f52546001600160801b03811680845260809190911c60209384018190528251918252928101929092529150f35b602483634e487b7160e01b81526041600452fd5b50346103a357806003193601126103a35760206001600160801b035f5160206158c05f395f51905f525416604051908152f35b5034610dcd5760a0366003190112610dcd576121866139c3565b90602435151560243503610dcd57606435906001600160a01b0382168203610dcd5760843567ffffffffffffffff8111610dcd576121c89036906004016139d9565b909263ffffffff42169462093a808604946121e1613b35565b937ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2809548063ffffffff8916036136fe575b50604435156136d65760c0850151156136c75760243515613685576001600160a01b038551166001600160a01b038516108061366e575b156136465760409760ff60f01b195f5160206159005f395f51905f5254165f5160206159005f395f51905f52556001600160801b035f5160206158c05f395f51905f5254169760ff60a0880151169863ffffffff82165f525f5160206158e05f395f51905f5260205263ffffffff8b5f205416928b519a6122c98c613a8e565b8b528160208c01528b8b01525f60608b01525f60808b01525f60a08b01528260c08b01526001600160a01b0388511692602089015160020b6024355f1461361e577ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280254915b5f525f5160206158e05f395f51905f5260205263ffffffff6001600160a01b038e5f205460501c1694165f525f5160206158e05f395f51905f526020528c5f205460201c60020b948d519d8e61238381613abe565b60443581525f6020820152015260608d015260808c01525f60a08c015260c08b015260e08a01526101008901527f000000000000000000000000000000000000000000000000000000000000000060020b15955b88511515806135fe575b156130b6576040516123f281613a8e565b5f81525f60208201525f60408201525f60608201525f60808201525f60a08201525f60c08201526001600160a01b0360408b015116815260608a015160020b88612daf577f000000000000000000000000000000000000000000000000000000000000000060020b8105905f81129081613080575b50613075575b60243515612ebb5761248f8160020b906101008260081d60010b920760ff1690565b909160ff8216926124d46001851b5f19908001019160010b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280760205260405f2090565b5416801580159481612e845750815f91610dcd5782600160801b60ff941015612e75575b5080680100000000000000006002921015612e67575b640100000000811015612e59575b62010000811015612e4b575b610100811015612e3d575b6010811015612e2f575b6004811015612e22575b1015612e18575b7f000000000000000000000000000000000000000000000000000000000000000093031660020b900360020b0260020b5b905b1515604083015260020b60208201819052620d89e719811215612dfb5750620d89e71960208201525b6001600160a01b036125c2602083015160020b614042565b168060608301526001600160a01b0360408c015116906024355f14612dea576001600160a01b03881681105b15612de4575086905b60c08c01518c517ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2801545f808312936001600160a01b03871680871015949362ffffff16928615926001600160801b03168188612cee575061266262ffffff86620f42400316876143de565b998715612cdd57612674828b83615343565b9a5b8b8110612c525750985b6001600160a01b038a169a848c149815612bfc578880612bf5575b15612be4575b998a9880612bdd575b15612bce575050505b955b80612bc3575b612bb8575b81612bad575b5015612b8f5750035b60c085015260a0840152608083015260408b01525f6044351315612b3557608081015160c082015101600160ff1b811015610dcd578a51038a5260a0810151600160ff1b811015610dcd5760208b01515f8282039212818312811691831390151617612b215760208b01525b60ff89511680612aed575b506001600160801b0360c08b01511680612ace575b506001600160a01b0360408b0151166001600160a01b0360608301511681145f14612a9f575060408101516127bb575b602435156127af5760205f1991015160020b0160020b5b60020b60608a01526123d7565b6020015160020b6127a2565b60a089015115612a3e575b60243515612a08576001600160801b038a60808101517ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280354905b8c602086015160020b6001600160a01b0360808301511663ffffffff6040606085015160060b940151169160e08701519261010088015160020b9461286f8360020b5f527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280660205260405f2090565b9763ffffffff62093a808404169760018a01908154900390556002890190815490039055600388019166ffffffffffffff8354927effffffff0000000000000000000000000000000000000000000000000000007affffffffffffffffffffffffffffffffffffffff000000000000006001600160a01b038660381c16890360381b1691827fffffffffff0000000000000000000000000000000000000000ffffffffffffff87161760060b90039363ffffffff858516847fffffffffff0000000000000000000000000000000000000000000000000000008916171760d81c16900360d81b169360ff60f81b16179116171790556004865460801d960193855f528460205260405f205491131580612a00575b156129f7575003915b5f5260205260405f2055806024356129ea575b505f81600f0b125f146129d2576129bf8360c06129c79401511691613c1a565b831690613c3a565b1660c08b015261278b565b8260c06129e59301511690831690613bfa565b6129c7565b90505f03600f0b5f61299f565b9150039161298c565b508015612983565b6001600160801b038a7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280254608082015190612800565b6001600160a01b03612a8263ffffffff60408c015116898c602082015160020b61ffff60606001600160801b03602083604088015116950151169401511693614912565b9190911660808b015260060b60608a0152600160a08a01526127c6565b90516001600160a01b03168103612ab7575b506123d7565b612ac090614632565b60020b60608a01525f612ab1565b612adc9060c0830151614453565b60808b01510160808b01525f61275b565b6001600160801b036064819260c085015102048060c08501510360c0850152168160a08d015116011660a08b01525f612746565b634e487b7160e01b5f52601160045260245ffd5b60a0810151600160ff1b811015610dcd578a51018a52612b5e608082015160c083015190613be3565b600160ff1b811015610dcd5760208b01515f8282019283129112908015821691151617612b215760208b015261273b565b9050612ba8915062ffffff81620f424003169084614e6c565b6126cf565b90508614155f6126c6565b9450825f03946126c0565b50835f0386116126bb565b612bd893506153b1565b6126b3565b50896126aa565b50612bf082828c615343565b6126a1565b508561269b565b9099908880612c4b575b15612c3a575b998a9880612c33575b15612c24575050505b956126b5565b612c2e93506152d9565b612c1e565b5089612c15565b50612c4682828c6153e2565b612c0c565b5085612c06565b90508915610dcd578115610dcd578715612c7757612c7190828b6157c9565b98612680565b612caf906001600160a01b038111612cc457612ca0906001600160801b0384169060601b613bf0565b6001600160a01b038b16613be3565b6001600160a01b038116908114612c71575f80fd5b612cd8906001600160801b0384169061452d565b612ca0565b612ce882828c6153e2565b9a612676565b9991508615612dd357612d02818a846153b1565b915b5f879003838110612d16575098612680565b90508915610dcd578115610dcd578715612dc3576001600160a01b038111612d725760601b6001600160801b03821680820615159104015b6001600160a01b038a169080821115610dcd576001600160a01b0391031698612680565b6001600160801b038216612d8b81600160601b846145ad565b918115612daf57600160601b900915612d4e575f19811015610dcd57600101612d4e565b634e487b7160e01b5f52601260045260245ffd5b612dce90828b615756565b612c71565b612dde81838b6152d9565b91612d04565b906125f7565b6001600160a01b03881681116125ee565b620d89e8809113612e0d575b506125aa565b60208201525f612e07565b600101811661254e565b918101831691811c612547565b60049283018416921c61253d565b60089283018416921c612533565b60109283018416921c612528565b60209283018416921c61251c565b60409283018416921c61250e565b60809250821c905060026124f8565b935050507f00000000000000000000000000000000000000000000000000000000000000009160020b900360020b0260020b61257f565b600190810160020b600881901d820b5f9081527ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb280760205260409020545f1960ff61010084071693841b01191680158015939092918361303b578093610dcd5760ff906001600160801b03811615613031575050607f5b67ffffffffffffffff84161561302757603f190160ff165b63ffffffff84161561301d57601f190160ff165b61ffff84161561301357600f190160ff165b60ff841615613009576007190160ff165b600f841615612fff576003190160ff165b6003841615612ff3576001190160ff16926001905b16612fe5575b60ff907f000000000000000000000000000000000000000000000000000000000000000093031660020b0160020b0260020b5b90612581565b5f1990920160ff1691612fac565b9260019060021c612fa6565b9260041c92612f91565b9260081c92612f80565b9260101c92612f6f565b9260201c92612f5d565b9260401c92612f49565b60801c9350612f31565b50915060ff7f00000000000000000000000000000000000000000000000000000000000000009281031660020b0160020b0260020b612fdf565b5f190160020b61246d565b9950505f987f000000000000000000000000000000000000000000000000000000000000000060020b900760020b15155f612467565b88906001600160801b0360208a89606086015160020b8382015160020b809114155f146135b3578161ffff6040613114940151169163ffffffff604086015116908787870151169161ffff6080816060870151169501511694614ab8565b6001600160a01b036040880151169161ffff60b81b73ffffffffffffffffffffffffffffffffffffffff1960608a01519366ffffffffffffff60a01b1961ffff60c81b5f5160206159005f395f51905f52549260c81b16911617169160b81b16179060a01b62ffffff60a01b1617175f5160206159005f395f51905f52555b0151166001600160801b0360c084015116809103613575575b50602435156134db5760808201517ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2802556001600160801b0360a08301511680613482575b505b60243515155f604435130361347057815160443503936020830151935b602435156133a15782851261336f575b613227614d76565b91333b156112c757613252918491604051938492839263fa461e3360e01b84528a8c60048601613c8e565b038183335af18015613364578691849161334b575b505061327291613be3565b61327a614d76565b1061332357506001600160a01b036040945b8186840151169260606001600160801b0360c08301511691015160020b90875194878652866020870152888601526060850152608084015216907fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca6760a03392a3600160f01b60ff60f01b195f5160206159005f395f51905f525416175f5160206159005f395f51905f525582519182526020820152f35b807fba0b951e0000000000000000000000000000000000000000000000000000000060049252fd5b8192509061335891613b13565b61074257848288613267565b6040513d85823e3d90fd5b61339c858403887f0000000000000000000000000000000000000000000000000000000000000000614bec565b61321f565b5f869392931261343e575b6133b4614cf1565b92333b15610dcd576133df915f91604051938492839263fa461e3360e01b84528a8c60048601613c8e565b038183335af190811561343357859161341c575b506133fe9192613be3565b613406614cf1565b1061332357506001600160a01b0360409461328c565b61342992505f9150613b13565b5f836133fe6133f3565b6040513d5f823e3d90fd5b61346b865f03887f0000000000000000000000000000000000000000000000000000000000000000614bec565b6133ac565b6020820151938251604435039361320f565b6001600160801b036134d591815f5160206159205f395f51905f52541601166001600160801b03166001600160801b03195f5160206159205f395f51905f525416175f5160206159205f395f51905f5255565b856131f0565b60808201517ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2803556001600160801b0360a0830151168061351c575b506131f2565b6001600160801b0361356f915f5160206159205f395f51905f525460801c01166001600160801b035f5160206159205f395f51905f52549181199060801b169116175f5160206159205f395f51905f5255565b85613516565b6135ad906001600160801b03166001600160801b03195f5160206158c05f395f51905f525416175f5160206158c05f395f51905f5255565b856131ac565b50506001600160a01b0360408601511673ffffffffffffffffffffffffffffffffffffffff195f5160206159005f395f51905f525416175f5160206159005f395f51905f5255613193565b506001600160a01b0385166001600160a01b0360408b01511614156123e1565b7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2803549161232e565b7ffcdf4aa7000000000000000000000000000000000000000000000000000000005f5260045ffd5b506401000276a36001600160a01b03851611612249565b6001600160a01b038551166001600160a01b038516118015612249575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b03851610612249565b6350dfbc4360e11b5f5260045ffd5b7f03fff018000000000000000000000000000000000000000000000000000000005f5260045ffd5b63ffffffff88167ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc280981905560408781015190516318a230bb60e31b81525f5160206159405f395f51905f52600482015261ffff90911660248201526044810191909152906020826064817350f6a754f94a6a5ee3d887e6b1f12b55aee0c69c5af4918215613433575f92613939575b506001600160a01b0360606139339361384960208b01916137e2835160020b875f525f5160206158e05f395f51905f5260205260405f209081549060381b62ffffff60381b169062ffffff60381b1916179055565b855f525f5160206158e05f395f51905f5260205260405f20907fffff0000000000000000000000000000000000000000ffffffffffffffffffff7dffffffffffffffffffffffffffffffffffffffff0000000000000000000083549260501b169116179055565b63ffffffff613856613bbf565b941684525160020b926020810193845263ffffffff8c165f525f5160206158e05f395f51905f5260205260405f209363ffffffff808351161663ffffffff198654161785555184549060201b66ffffff00000000169066ffffff0000000019161784556138e3604082015160020b859081549060381b62ffffff60381b169062ffffff60381b1916179055565b015182547fffff0000000000000000000000000000000000000000ffffffffffffffffffff16911660501b7dffffffffffffffffffffffffffffffffffffffff0000000000000000000016179055565b5f612212565b91506020823d60201161397a575b8161395460209383613b13565b81010312610dcd576001600160a01b03606061397261393394613bab565b93505061378d565b3d9150613947565b34610dcd575f366003190112610dcd576020906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b600435906001600160a01b0382168203610dcd57565b9181601f84011215610dcd5782359167ffffffffffffffff8311610dcd5760208381860195010111610dcd57565b602435908160020b8203610dcd57565b604435908160020b8203610dcd57565b606435908160020b8203610dcd57565b600435908160020b8203610dcd57565b608435906001600160801b0382168203610dcd57565b9181601f84011215610dcd5782359167ffffffffffffffff8311610dcd576020808501948460051b010111610dcd57565b60e0810190811067ffffffffffffffff821117613aaa57604052565b634e487b7160e01b5f52604160045260245ffd5b610120810190811067ffffffffffffffff821117613aaa57604052565b60a0810190811067ffffffffffffffff821117613aaa57604052565b6080810190811067ffffffffffffffff821117613aaa57604052565b90601f8019910116810190811067ffffffffffffffff821117613aaa57604052565b60405190613b4282613a8e565b8160c060ff5f5160206159005f395f51905f52546001600160a01b03811684528060a01c60020b602085015261ffff8160b81c16604085015261ffff8160c81c16606085015261ffff8160d81c166080850152818160e81c1660a085015260f01c161515910152565b51906001600160a01b0382168203610dcd57565b60405190613bcc82613af7565b5f6060838281528260208201528260408201520152565b91908201809211612b2157565b8115612daf570490565b906001600160801b03809116911601906001600160801b038211612b2157565b600f0b6f7fffffffffffffffffffffffffffffff198114612b21575f0390565b906001600160801b03809116911603906001600160801b038211612b2157565b6001600160801b03166001600160801b03195f5160206158c05f395f51905f525416175f5160206158c05f395f51905f5255565b6060908593602096938252868201528160408201520192818452848401375f828201840152601f01601f1916010190565b61ffff821015613ccf5701905f90565b634e487b7160e01b5f52603260045260245ffd5b90604051613cf081613af7565b606081935463ffffffff811683528060201c60060b60208401526001600160a01b038160581c16604084015260f81c1515910152565b51906001600160801b0382168203610dcd57565b67ffffffffffffffff8111613aaa5760051b60200190565b7ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc28095462093a8063ffffffff4216049063ffffffff821691818303613d9557505050565b508015614003575b7350f6a754f94a6a5ee3d887e6b1f12b55aee0c69c905b828110613dec5750505f198101908111612b21577ff047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc280955565b613df4613b35565b9061ffff6040830151166001820192838311612b21576040516318a230bb60e31b81525f5160206159405f395f51905f52600482015261ffff92909216602483015260448201849052602082606481885af4918215613433575f92613fad575b50926001600160a01b036060613fa793613f1360206001980191613eac835160020b895f525f5160206158e05f395f51905f5260205260405f209081549060381b62ffffff60381b169062ffffff60381b1916179055565b875f525f5160206158e05f395f51905f5260205260405f20907fffff0000000000000000000000000000000000000000ffffffffffffffffffff7dffffffffffffffffffffffffffffffffffffffff0000000000000000000083549260501b169116179055565b613f1b613bbf565b9063ffffffff871682525160020b93602082019485525f525f5160206158e05f395f51905f5260205260405f209363ffffffff808351161663ffffffff198654161785555184549060201b66ffffff00000000169066ffffff0000000019161784556138e3604082015160020b859081549060381b62ffffff60381b169062ffffff60381b1916179055565b01613db4565b9150926020823d8211613ffb575b81613fc860209383613b13565b81010312610dcd576001600160a01b036060600195613f136020613fee613fa797613bab565b9650505092955050613e54565b3d9150613fbb565b505f19810181811115613d9d57634e487b7160e01b5f52601160045260245ffd5b8051821015613ccf5760209160051b010190565b8115612daf570690565b60020b5f8112156143d857805f03905b620d89e882116143b05760018216156143945770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad37aa2d162d1a5940015b169160028116614378575b6004811661435c575b60088116614340575b60108116614324575b60208116614308575b604081166142ec575b608081166142d0575b61010081166142b4575b6102008116614298575b610400811661427c575b6108008116614260575b6110008116614244575b6120008116614228575b614000811661420c575b61800081166141f0575b6201000081166141d4575b6202000081166141b9575b62040000811661419e575b6208000016614185575b5f12614177575b6001600160a01b039063ffffffff811661416e5760ff5f5b169060201c011690565b60ff6001614164565b8015612daf575f190461414c565b6b048a170391f7dc42444e8fa290910260801c90614145565b6d2216e584f5fa1ea926041bedfe9890920260801c9161413b565b916e5d6af8dedb81196699c329225ee6040260801c91614130565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c91614125565b916f31be135f97d08fd981231505542fcfa60260801c9161411a565b916f70d869a156d2a1b890bb3df62baf32f70260801c91614110565b916fa9f746462d870fdf8a65dc1f90e061e50260801c91614106565b916fd097f3bdfd2022b8845ad8f792aa58250260801c916140fc565b916fe7159475a2c29b7443b29c7fa6e889d90260801c916140f2565b916ff3392b0822b70005940c7a398e4b70f30260801c916140e8565b916ff987a7253ac413176f2b074cf7815e540260801c916140de565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c916140d4565b916ffe5dee046a99a2a811c461f1969c30530260801c916140ca565b916fff2ea16466c96a3843ec78b326b528610260801c916140c1565b916fff973b41fa98c081472e6896dfb254c00260801c916140b8565b916fffcb9843d60f6159c9db58835c9266440260801c916140af565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c916140a6565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c9161409d565b916ffff97272373d413259a46990580e213a0260801c91614094565b70ffffffffffffffffffffffffffffffffff600160801b614089565b7f2bc80f3a000000000000000000000000000000000000000000000000000000005f5260045ffd5b80614052565b9091905f905f1984820990848102928380841093039280840393146144455782620f424011156103a357507fde8f6cefed634549b62c77574f722e1ac57e23f24d8fd5cb790fb65668c261399394620f4240910990828211900360fa1b910360061c170290565b505050620f42409192500490565b5f19600160801b8209918160801b918280851094039380850394146144d35783821115610dcd57600160801b82910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b5080925015610dcd570490565b5f915f1981830991818102938480851094039380850394146145235783600160601b11156103a3575090600160601b910990828211900360a01b910360601c1790565b5050505060601c90565b5f19600160601b8209918160601b918280851094039380850394146144d35783821115610dcd57600160601b82910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b915f1982840992828102928380861095039480860395146146245784831115610dcd5782910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b505080925015610dcd570490565b6001600160a01b038116906401000276a3821015806148f5575b156148cd5777ffffffffffffffffffffffffffffffffffffffff000000009060201b16806001600160801b03811160071b90811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c9060ff821160031b91821c92600f841160021b93841c94600160038711811b96871c1196171717171717179060808210155f146148c357607e1982011c5b800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c80029081607f1c8260ff1c1c80029283607f1c8460ff1c1c80029485607f1c8660ff1c1c80029687607f1c8860ff1c1c80029889607f1c8a60ff1c1c80029a8b607f1c8c60ff1c1c80029c8d80607f1c9060ff1c1c800260cd1c6604000000000000169d60cc1c6608000000000000169c60cb1c6610000000000000169b60ca1c6620000000000000169a60c91c6640000000000000169960c81c6680000000000000169860c71c670100000000000000169760c61c670200000000000000169660c51c670400000000000000169560c41c670800000000000000169460c31c671000000000000000169360c21c672000000000000000169260c11c674000000000000000169160c01c6780000000000000001690607f190160401b1717171717171717171717171717693627a301d71055774c85026f028f6481ab7f045a5af012a19d003aa919810160801d60020b906fdb2df09e81959a81455e260799a0632f0160801d60020b918282145f146148a3575090505b90565b6001600160a01b036148b484614042565b16116148be575090565b905090565b81607f031b6146e7565b7f4980e1be000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073fffd8963efd1fc6a506488495d951d5263988d26821061464c565b9493509061ffff811015613ccf57614938905f5160206159405f395f51905f5201613ce3565b9363ffffffff85511663ffffffff82160361496a575b5050506001600160a01b036040602084015160060b9301511690565b6149749394615433565b905f808061494e565b95949290939163ffffffff851615614a7d5763ffffffff6149b09588031680975f5160206159405f395f51905f526154fb565b909263ffffffff8451168082145f146149df575050506001600160a01b036040602084015160060b9301511690565b63ffffffff8395935116908183145f14614a1057505050506001600160a01b036040602084015160060b9301511690565b63ffffffff818193031692031693602083015160060b9283602083015160060b0360060b928060060b928315612daf57614a68604092896001600160a01b038096948180888198015116978892015116031602613bf0565b1601169460060b91050260060b0160060b9190565b925090925061ffff811015613ccf57614938905f5160206159405f395f51905f5201613ce3565b9061ffff16908115612daf5761ffff160690565b90919293959461ffff821015613ccf57614ae0825f5160206159405f395f51905f5201613ce3565b9663ffffffff88511663ffffffff851614614be157614b2b949261ffff6001989795938382614b2595168383161180614bd1575b15614bc757509889925b0116614aa4565b96615433565b61ffff841015613ccf57805160208083015160408401516060909401517fff0000000000000000000000000000000000000000000000000000000000000090151560f81b167effffffffffffffffffffffffffffffffffffffff000000000000000000000060589590951b9490941663ffffffff909316911b6affffffffffffff00000000161717175f5160206159405f395f51905f52840155565b9050988992614b1e565b508383165f198201841614614b14565b965050925050509190565b5f9291838093604051906001600160a01b0360208301947fa9059cbb000000000000000000000000000000000000000000000000000000008652166024830152604482015260448152614c40606482613b13565b51925af13d15614cea573d67ffffffffffffffff8111613aaa5760405190614c72601f8201601f191660200183613b13565b81523d5f602083013e5b81614cb2575b5015614c8a57565b7f8b986265000000000000000000000000000000000000000000000000000000005f5260045ffd5b8051801592508215614cc7575b50505f614c82565b8192509060209181010312610dcd57602001518015158103610dcd575f80614cbf565b6060614c7c565b6040516370a0823160e01b81523060048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613433575f91614d47575090565b90506020813d602011614d6e575b81614d6260209383613b13565b81010312610dcd575190565b3d9150614d55565b6040516370a0823160e01b81523060048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115613433575f91614d47575090565b61ffff8116908115614e335761ffff831691821115614e2d575f5160206159405f395f51905f52905b8261ffff821610614e065750505090565b61ffff811015613ccf5760018161ffff9284018263ffffffff198254161790550116614df5565b91505090565b636b93000360e11b5f5260045ffd5b9190620f424090614e548282866145ad565b9309614e5c57565b905f19811015610dcd5760010190565b929190614e7a8282866145ad565b938215612daf5709614e5c57565b905f905f9060408401805160020b90614eaa6060870192835160020b9061523c565b614eb2613b35565b906001600160a01b03875116602088015192825160020b916001600160801b036080875160020b9b01958651600f0b9463ffffffff602086019d8e5160020b8242169860405197614f0289613abe565b88526020880195865260408801948552606088019283526080880190815260a0880191825260c08801928a845260e08901957f000000000000000000000000000000000000000000000000000000000000000060020b87526101008a0197897f00000000000000000000000000000000000000000000000000000000000000001689526001600160a01b036040519b7ffc322879000000000000000000000000000000000000000000000000000000008d52511660048c01525160248b01525160020b60448a01525160020b606489015251600f0b60848801525160020b60a4870152511660c48501525160020b60e4840152511661010482015260208161012481734bd87e0077d12b9b18b158dbe5ea7944135318e65af4908115613433575f9161520a575b50988451600f0b61503d575b505050505050565b90919293949597815160020b855160020b908181125f14615095575050505050509061507d61507361508894935160020b614042565b925160020b614042565b9051600f0b91615721565b915b5f8080808080615035565b90919293959997809599505160020b135f146151df575050916001600160a01b0361518961517f615197946151096151c698976001600160801b035f5160206158c05f395f51905f5254169b8c61ffff60408a015116925160020b61ffff60608b0151169261ffff60808c01511694614ab8565b907fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff61ffff60c81b61ffff60b81b5f5160206159005f395f51905f52549360b81b169360c81b16911617175f5160206159005f395f51905f525561517484865116915160020b614042565b8751600f0b91615721565b985160020b614042565b9151168351600f0b916156cc565b9381515f81600f0b125f146151cb57506151b7613c5a9251600f0b613c1a565b6001600160801b031690613c3a565b61508a565b613c5a92506001600160801b031690613bfa565b9097506152049596506151f9929493506150739150614042565b9051600f0b916156cc565b9061508a565b90506020813d602011615234575b8161522560209383613b13565b81010312610dcd57515f615029565b3d9150615218565b9060020b9060020b818112156152b157620d89e7191361528957620d89e81261526157565b7fd7b54ab1000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f9ad612e8000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f2fe0284f000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b0382166001600160a01b0382161161533d575b6001600160a01b038116918215610dcd576148a0936fffffffffffffffffffffffffffffffff60601b6001600160a01b03615338948185169403169160601b166145ad565b613bf0565b906152f3565b906001600160a01b0381166001600160a01b038316116153ab575b6001600160a01b038216928315610dcd576fffffffffffffffffffffffffffffffff60601b6001600160a01b0361539f948185169403169160601b16614e6c565b90808206151591040190565b9061535e565b6001600160a01b036001600160801b03916148a09493828116838316116153dc575b031691166144e0565b906153d3565b6001600160a01b036001600160801b0391600160601b938281168383161161542d575b03169216916154158282856145ad565b920961541e5790565b5f19811015610dcd5760010190565b90615405565b9192909261543f613bbf565b5063ffffffff8351168403906001600160a01b036040602086015160060b95015116926001600160801b03811615155f146154eb576001600160801b03905b16918215612daf576001600160a01b039473ffffffff000000000000000000000000000000009263ffffffff604051986154b78a613af7565b16885263ffffffff831660060b9060020b0260060b0160060b602087015260801b1604011660408201526001606082015290565b506001600160801b03600161547e565b969294909493919361550b613bbf565b50615514613bbf565b91615528615522858b613cbf565b50613ce3565b9163ffffffff83511661553c88828b615841565b6156a1575050505050600161ffff91011661556361552261555d8784614aa4565b88613cbf565b83606082015115615686575b63ffffffff61558092511686615841565b1561565e5761ffff6155a5868293615596613bbf565b5061559f613bbf565b50614aa4565b169416935f19858201015b80820160011c906155cd6155226155c78985614038565b8a613cbf565b6060810151156156535760018301906155f26155226155ec8b85614038565b8c613cbf565b6156048863ffffffff8451168b615841565b91828061563b575b61562c5750506156235750505f1901905b906155b0565b9150915061561d565b9a509850949650505050505050565b5061564e63ffffffff8351168a8c615841565b61560c565b50915060010161561d565b7f27e8e875000000000000000000000000000000000000000000000000000000005f5260045ffd5b615580915063ffffffff61569989613ce3565b92505061556f565b93995094975090955093915063ffffffff8216036156c0575050509190565b836148a0949650615433565b905f83600f0b125f146156ff576156ee925f036001600160801b0316916153b1565b600160ff1b811015610dcd575f0390565b615712926001600160801b0316916153e2565b600160ff1b811015610dcd5790565b905f83600f0b125f14615743576156ee925f036001600160801b0316916152d9565b615712926001600160801b031691615343565b9082156157c3576fffffffffffffffffffffffffffffffff60601b6001600160a01b039160601b1691168061578e8185029485613bf0565b14806157ba575b15610dcd576157a692820391614e6c565b6001600160a01b038116908103610dcd5790565b50828211615795565b50905090565b909180156157c3576001600160a01b036fffffffffffffffffffffffffffffffff60601b819460601b169216808202816158038483613bf0565b14615829575b509061581861581d9284613bf0565b613be3565b80820615159104011690565b830183811061580957915061583d92614e6c565b1690565b63ffffffff9182169291168083118015806158af575b6158a2579063ffffffff64ffffffffff939484935f1461589357945b1690811115615885575b169116111590565b64010000000001811661587d565b64010000000001831694615873565b505063ffffffff16101590565b508163ffffffff8416111561585756fef047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2805f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccc2808f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2800f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2804f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2809a2646970667358221220b64492fd2aa111d61f9982d0c39b8bc03e0ea09d4752f86e4449ff579d2b054964736f6c634300081c0033f047b0c59244a0faf8e48cb6b6fde518e6717176152b6dd953628cd9dccb2801a2646970667358221220e7cfe14b2879e38918f93b4905a9a12e000bf6811f0a462d4624245b480805c564736f6c634300081c0033000000000000000000000000cd2d0637c94fe77c2896bbcbb174ceffb08de6d7" +} \ No newline at end of file diff --git a/test/foundry/bytecodes/shadow-cl/SwapRouter.json b/test/foundry/bytecodes/shadow-cl/SwapRouter.json new file mode 100644 index 0000000..467bc0b --- /dev/null +++ b/test/foundry/bytecodes/shadow-cl/SwapRouter.json @@ -0,0 +1,3 @@ +{ + "bytecode": "60c0346100a857601f61237638819003918201601f19168301916001600160401b038311848410176100ac5780849260409485528339810103126100a857610052602061004b836100c0565b92016100c0565b9060805260a0525f195f556040516122a190816100d58239608051818181610b7b015281816114220152611f56015260a0518181816101fa0152818161031a01528181610397015281816115000152611ded0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036100a85756fe60806040526004361015610022575b3615610018575f80fd5b6100206114f6565b005b5f3560e01c806312210e8a146101315780634659a4941461012c57806349404b7c146101275780634aa4a4fc146101225780639b2c0a371461011d578063a026383e14610118578063a4a78f0c14610113578063ac9650d81461010e578063c04b8d5914610109578063c2e3140a14610104578063c714e838146100ff578063d5f39488146100fa578063df2ab5bb146100f5578063e0e189a0146100f0578063f28c0498146100eb578063f3995c67146100e65763fa461e330361000e57610df4565b610ddc565b610d2f565b610c3c565b610b9f565b610b5c565b610a6e565b6109dc565b610940565b610715565b6105e0565b6104d1565b61033e565b6102fb565b6101c2565b6101aa565b610144565b5f91031261014057565b5f80fd5b5f600319360112610140574761015657005b610020473361156c565b6001600160a01b0381160361014057565b60031960c09101126101405760043561018981610160565b90602435906044359060643560ff8116810361014057906084359060a43590565b6100206101b636610171565b94939093929192610e61565b6040600319360112610140576024356004356101dd82610160565b6040516370a0823160e01b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016929091602083602481875afa9283156102c1575f936102c6575b5061024190831015610f05565b8161024857005b823b15610140575f60405180947f2e1a7d4d00000000000000000000000000000000000000000000000000000000825281838161028d88600483019190602083019252565b03925af19283156102c157610020936102a7575b5061156c565b806102b55f6102bb9361089c565b80610136565b5f6102a1565b610e56565b6102419193506102ed9060203d6020116102f4575b6102e5818361089c565b810190610ef6565b9290610234565b503d6102db565b34610140575f6003193601126101405760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b60806003193601126101405760043560243561035981610160565b60443560643561036881610160565b811515806104b4575b61037a90610f50565b6040516370a0823160e01b81523060048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694602082602481895afa9182156102c1575f9261048f575b506103dc90821015610f05565b806103e357005b843b15610140575f60405180967f2e1a7d4d00000000000000000000000000000000000000000000000000000000825281838161042887600483019190602083019252565b03925af19485156102c15761044e61046594610456926100209861047b575b5083610f84565b612710900490565b91828061046b575b5050610f9c565b9061156c565b6104749161156c565b5f8261045e565b806102b55f6104899361089c565b5f610447565b6103dc9192506104ad9060203d6020116102f4576102e5818361089c565b91906103cf565b506064821115610371565b60031961010091011261014057600490565b610100600319360112610140576104e7366104bf565b608081013542116105b8576105b4906105a460c061059960a0840135606085013561051181610160565b60e08601359061052082610160565b86359261052c84610160565b6bffffffffffffffffffffffff1961054660408a01610fa9565b60208a01359061055582610160565b826040519760601b16602088015260e81b603487015260601b166037850152602b8452610583604b8561089c565b61058b6108bf565b9384523360208501526117da565b920135821015610fb7565b6040519081529081906020820190565b0390f35b7fb8e3f2bf000000000000000000000000000000000000000000000000000000005f5260045ffd5b6105e936610171565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529094919391906020816044816001600160a01b038b165afa9081156102c1575f91610654575b505f191161064b57005b61002095610e61565b61066d915060203d6020116102f4576102e5818361089c565b5f610641565b90601f19601f602080948051918291828752018686015e5f8582860101520116010190565b602081016020825282518091526040820191602060408360051b8301019401925f915b8383106106ca57505050505090565b9091929394602080610706837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528951610673565b970193019301919392906106bb565b60206003193601126101405760043567ffffffffffffffff811161014057366023820112156101405780600401359067ffffffffffffffff8211610140576024810190602436918460051b010111610140576107708261101a565b915f5b81811061078857604051806105b48682610698565b5f806107958385876110e0565b906107a560405180938193611100565b0390305af46107b261110d565b90156107d857906001916107c682876111b0565b526107d181866111b0565b5001610773565b6044815110610140576107fa816024806004610812950151830101910161113c565b60405191829162461bcd60e51b83526004830161119f565b0390fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60a0810190811067ffffffffffffffff82111761085f57604052565b610816565b6040810190811067ffffffffffffffff82111761085f57604052565b6060810190811067ffffffffffffffff82111761085f57604052565b90601f601f19910116810190811067ffffffffffffffff82111761085f57604052565b604051906108ce60408361089c565b565b67ffffffffffffffff811161085f57601f01601f191660200190565b9291926108f8826108d0565b91610906604051938461089c565b829481845281830111610140578281602093845f960137010152565b9080601f830112156101405781602061093d933591016108ec565b90565b60206003193601126101405760043567ffffffffffffffff81116101405760a06003198236030112610140576040519061097982610843565b80600401359167ffffffffffffffff83116101405760846105a4926109a76105b49560043691840101610922565b835260248101356109b781610160565b60208401526044810135604084015260648101356060840152013560808201526111c4565b6109e536610171565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529094919391906020816044816001600160a01b038b165afa80156102c15782915f91610a4f575b5010610a4657005b610020956112f9565b610a68915060203d6020116102f4576102e5818361089c565b5f610a3e565b61010060031936011261014057610a84366104bf565b608081013542116105b8576105b490610b5360c0610b4860a08401356060850135610aae81610160565b60e086013590610abd82610160565b602087013592610acc84610160565b610b32883594610adb86610160565b610b24610aea60408c01610fa9565b60405197889360208501916bffffffffffffffffffffffff199081602b959360601b16845260601b16601483015260e81b60288201520190565b03601f19810186528561089c565b610b3a6108bf565b938452336020850152611b64565b920135821115611263565b5f195f556105a4565b34610140575f6003193601126101405760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b606060031936011261014057600435610bb781610160565b602435604435610bc681610160565b604051916370a0823160e01b83523060048401526020836024816001600160a01b0388165afa9283156102c1575f93610c17575b50610c07908310156112ae565b81610c0e57005b61002092611cc8565b610c07919350610c359060203d6020116102f4576102e5818361089c565b9290610bfa565b60a060031936011261014057600435610c5481610160565b60243590604435610c6481610160565b606435608435610c7381610160565b81151580610d24575b610c8590610f50565b6040516370a0823160e01b8152306004820152946020866024816001600160a01b0389165afa9586156102c1575f96610cff575b50610cc6908610156112ae565b84610ccd57005b84610ce161044e610cef9461002098610f84565b918280610cf5575050610f9c565b91611cc8565b6104749187611cc8565b610cc6919650610d1d9060203d6020116102f4576102e5818361089c565b9590610cb9565b506064821115610c7c565b60206003193601126101405760043567ffffffffffffffff811161014057806004019060a0600319823603011261014057604481013542116105b857610db5610da86105b4936064840135610d92602486013592610d8c84610160565b8061108f565b939060405194610da186610864565b36916108ec565b8352336020840152611a1f565b50610dc860845f54920135821115611263565b5f195f556040519081529081906020820190565b610020610de836610171565b949390939291926112f9565b346101405760606003193601126101405760443560243560043567ffffffffffffffff831161014057366023840112156101405782600401359167ffffffffffffffff83116101405736602484860101116101405760246100209401916113e1565b6040513d5f823e3d90fd5b6001600160a01b0390959293951693843b15610140575f9461010493869260ff604051998a9889977f8fcbaf0c0000000000000000000000000000000000000000000000000000000089523360048a01523060248a015260448901526064880152600160848801521660a486015260c485015260e48401525af180156102c157610ee85750565b806102b55f6108ce9361089c565b90816020910312610140575190565b15610f0c57565b606460405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420574554483900000000000000000000000000006044820152fd5b1561014057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810292918115918404141715610f9757565b610f57565b91908203918211610f9757565b358060020b81036101405790565b15610fbe57565b606460405162461bcd60e51b815260206004820152601360248201527f546f6f206c6974746c65207265636569766564000000000000000000000000006044820152fd5b67ffffffffffffffff811161085f5760051b60200190565b9061102482611002565b611031604051918261089c565b828152601f196110418294611002565b01905f5b82811061105157505050565b806060602080938501015201611045565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610140570180359067ffffffffffffffff82116101405760200191813603831361014057565b908210156110fb576110f79160051b81019061108f565b9091565b611062565b908092918237015f815290565b3d15611137573d9061111e826108d0565b9161112c604051938461089c565b82523d5f602084013e565b606090565b6020818303126101405780519067ffffffffffffffff8211610140570181601f8201121561014057805190611170826108d0565b9261117e604051948561089c565b8284526020838301011161014057815f9260208093018386015e8301015290565b90602061093d928181520190610673565b80518210156110fb5760209160051b010190565b604081015142116105b85760608101335b6112206111e58451516042111590565b918351835f1461124f5730905b61121b6111ff88516118ba565b936112086108bf565b9485526001600160a01b03166020850152565b61168a565b808352901561123c575030611235835161198b565b83526111d5565b61093d9150608090920151821015610fb7565b60208601516001600160a01b0316906111f2565b1561126a57565b606460405162461bcd60e51b815260206004820152601260248201527f546f6f206d7563682072657175657374656400000000000000000000000000006044820152fd5b156112b557565b606460405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420746f6b656e00000000000000000000000000006044820152fd5b6001600160a01b0390959293951693843b15610140575f9460e493869260ff604051998a9889977fd505accf0000000000000000000000000000000000000000000000000000000089523360048a01523060248a01526044890152606488015216608486015260a485015260c48401525af180156102c157610ee85750565b6020818303126101405780359067ffffffffffffffff821161014057019060408282031261014057604051916113ad83610864565b803567ffffffffffffffff8111610140576020926113cc918301610922565b835201356113d981610160565b602082015290565b916114209161140a611446925f8613968780156114ed575b61140290610f50565b810190611378565b946114158651611dac565b949195908587611fa9565b7f0000000000000000000000000000000000000000000000000000000000000000612001565b50156114d157506001600160a01b0381166001600160a01b038316105b15611487575061148060206108ce9401516001600160a01b031690565b3391611de0565b90506114968351516042111590565b156114b75750906114b4916114ab825161198b565b82523390611a1f565b50565b61148060206108ce94845f5501516001600160a01b031690565b92506001600160a01b0382166001600160a01b03821610611463565b505f84136113f9565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016330361152857565b606460405162461bcd60e51b815260206004820152600960248201527f4e6f7420574554483900000000000000000000000000000000000000000000006044820152fd5b5f919082916040519061158060208361089c565b83825260208201915f36843751925af161159861110d565b50156115a057565b606460405162461bcd60e51b815260206004820152600360248201527f53544500000000000000000000000000000000000000000000000000000000006044820152fd5b6020815260406001600160a01b036020611608855184838701526060860190610673565b9401511691015290565b9190826040910312610140576020825192015190565b919360a09361093d96956001600160a01b0380941685521515602085015260408401521660608201528160808201520190610673565b7f80000000000000000000000000000000000000000000000000000000000000008114610f97575f0390565b6116e092916040916001600160a01b038216156117d2575b6116d45f6116e66116b38751611dac565b999194906001600160a01b038b166001600160a01b038716109a8b96611f3e565b6001600160a01b031690565b93611f7e565b938282146117ae5761175061170d61171b6401000276a4995b8951928391602083016115e4565b03601f19810183528261089c565b8751988997889687957f128acb0800000000000000000000000000000000000000000000000000000000875260048701611628565b03925af19081156102c15761093d925f915f9361177b575b5015611774575061165e565b905061165e565b9092506117a0915060403d6040116117a7575b611798818361089c565b810190611612565b915f611768565b503d61178e565b61175061170d61171b73fffd8963efd1fc6a506488495d951d5263988d25996116ff565b3091506116a2565b9161182693926040926001600160a01b03811615611898575b5f6116d49161182c6118058851611dac565b9a9195906001600160a01b038c166001600160a01b038816109b8c97611f3e565b94611f7e565b946001600160a01b03811615831461188857508282146118655761175061170d61171b6401000276a45b998951928391602083016115e4565b61175061170d61171b73fffd8963efd1fc6a506488495d951d5263988d25611856565b61170d61171b61175092996116ff565b50306117f3565b90601f8201809211610f9757565b91908201809211610f9757565b602b90816118c78161189f565b106119635780516118d8835f6118ad565b1161193b57816118f45750506040515f81526020810160405290565b60405191601f811691821560051b808486010193838501920101905b8084106119285750508252601f01601f191660405290565b9092602080918551815201930190611910565b7fb4120f14000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f35278d12000000000000000000000000000000000000000000000000000000005f5260045ffd5b80516016198101818111610f9757806119a38161189f565b106119635782516119b58260176118ad565b1161193b57806119d2575050506040515f81526020810160405290565b604051926017601f8316801560051b9060161982828901019687010193010101905b808410611a0c5750508252601f01601f191660405290565b90926020809185518152019301906119f4565b909291926001600160a01b03811615611b5d575b60406116d491611a63611a468751611dac565b95916001600160a01b0381166001600160a01b0388161096611f3e565b835f611a76611a7188611f7e565b61165e565b93828214611b3957611ad161170d611a9c6401000276a49c8951928391602083016115e4565b87519b8c97889687957f128acb0800000000000000000000000000000000000000000000000000000000875260048701611628565b03925af19081156102c1575f945f92611b15575b5015611b015790611af86108ce9261165e565b935b9314610f50565b9290611b0f6108ce9261165e565b93611afa565b909450611b31915060403d6040116117a757611798818361089c565b90935f611ae5565b611ad161170d611a9c73fffd8963efd1fc6a506488495d951d5263988d259c6116ff565b5030611a33565b90939291936001600160a01b03811615611ca9575b60406116d491611b8c611a468651611dac565b835f611b9a611a7188611f7e565b936001600160a01b038b16159a8b8314611c995750828214611c7657611c0a61170d611bd56401000276a45b9b8951928391602083016115e4565b87519a8b97889687957f128acb0800000000000000000000000000000000000000000000000000000000875260048701611628565b03925af19081156102c1575f935f92611c52575b5015611c4257611c2d9061165e565b915b93611c38575050565b6108ce9114610f50565b91611c4c9061165e565b91611c2f565b909350611c6e915060403d6040116117a757611798818361089c565b90925f611c1e565b611c0a61170d611bd573fffd8963efd1fc6a506488495d951d5263988d25611bc6565b61170d611bd5611c0a929b6116ff565b5030611b79565b90816020910312610140575180151581036101405790565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082019081526001600160a01b03909316602482015260448101939093525f928392908390611d1f816064810161170d565b51925af1611d2b61110d565b81611d7d575b5015611d3957565b606460405162461bcd60e51b815260206004820152600260248201527f53540000000000000000000000000000000000000000000000000000000000006044820152fd5b8051801592508215611d92575b50505f611d31565b611da59250602080918301019101611cb0565b5f80611d8a565b601481511061193b57602081015160601c91601782511061193b57601782015191602b81511061193b576037015160601c90565b9290926001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693846001600160a01b0383161480611f34575b15611f0b575050823b1561014057604051927fd0e30db00000000000000000000000000000000000000000000000000000000084525f8460048185855af19283156102c157611ebe94602094611ef7575b505f6040518096819582947fa9059cbb00000000000000000000000000000000000000000000000000000000845260048401602090939291936001600160a01b0360408201951681520152565b03925af180156102c157611ecf5750565b6114b49060203d602011611ef0575b611ee8818361089c565b810190611cb0565b503d611ede565b806102b55f611f059361089c565b5f611e71565b9093509091906001600160a01b0381163003611f2b57506108ce92611cc8565b6108ce9361201e565b5082471015611e20565b6001600160a01b0392611f7a92611f5492611fa9565b7f0000000000000000000000000000000000000000000000000000000000000000612107565b1690565b7f80000000000000000000000000000000000000000000000000000000000000008110156101405790565b91906001600160a01b03905f60408051611fc281610880565b828152826020820152015281811682851611611ffb575b8160405194611fe786610880565b16845216602083015260020b604082015290565b92611fd9565b6001600160a01b039161201391612107565b169081330361014057565b905f80949381946001600160a01b03604051928160208501967f23b872dd00000000000000000000000000000000000000000000000000000000885216602485015216604483015260648201526064815261207a60848261089c565b51925af161208661110d565b816120d8575b501561209457565b606460405162461bcd60e51b815260206004820152600360248201527f53544600000000000000000000000000000000000000000000000000000000006044820152fd5b80518015925082156120ed575b50505f61208c565b6121009250602080918301019101611cb0565b5f806120e5565b906001600160a01b038151169160208201926001600160a01b0384511611156122275761170d61221861093d948461219b61216b60406121626121546116d49a516001600160a01b031690565b95516001600160a01b031690565b93015160020b90565b604080516001600160a01b0395861660208201908152959094169084015260020b6060830152816080810161170d565b51902060405192839160208301958690916bffffffffffffffffffffffff196055937fff00000000000000000000000000000000000000000000000000000000000000845260601b16600183015260158201527fc701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d60358201520190565b5190206001600160a01b031690565b606460405162461bcd60e51b815260206004820152600b60248201527f21546f6b656e4f726465720000000000000000000000000000000000000000006044820152fdfea2646970667358221220e15de371b0b5a7682e4da58ca24f2b347a20e25d8c92fec9ddd114555f4e5f6064736f6c634300081c00330000000000000000000000008bbdc15759a8ecf99a92e004e0c64ea9a5142d59000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38" +} \ No newline at end of file diff --git a/test/foundry/fixtures/TestBed.sol b/test/foundry/fixtures/TestBed.sol index 3acacfd..67695bf 100644 --- a/test/foundry/fixtures/TestBed.sol +++ b/test/foundry/fixtures/TestBed.sol @@ -58,6 +58,7 @@ contract TestBed is UniswapSetup { initDeltaSwap(owner); initAerodrome(owner); initAerodromeCL(owner,aeroVoter); + initShadowCL(owner); router = new TestUniversalRouter(address(weth)); } diff --git a/test/foundry/fixtures/UniswapSetup.sol b/test/foundry/fixtures/UniswapSetup.sol index 3cd2a70..49b3e58 100644 --- a/test/foundry/fixtures/UniswapSetup.sol +++ b/test/foundry/fixtures/UniswapSetup.sol @@ -11,6 +11,8 @@ import '@gammaswap/v1-deltaswap/contracts/interfaces/IDeltaSwapPair.sol'; import '@gammaswap/v1-deltaswap/contracts/interfaces/IDeltaSwapRouter02.sol'; import '@gammaswap/v1-core/contracts/GammaPoolFactory.sol'; +import '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol'; + import '../../../contracts/interfaces/external/IAeroCLPool.sol'; import '../../../contracts/interfaces/external/IAeroCLPoolFactory.sol'; import '../../../contracts/interfaces/external/IAeroPoolFactory.sol'; @@ -21,6 +23,13 @@ import '../../../contracts/test/IAeroRouter.sol'; import '../../../contracts/test/IAeroToken.sol'; import '../../../contracts/test/ICLGaugeFactory.sol'; import '../../../contracts/test/IPositionManagerMintable.sol'; +import '../../../contracts/test/IShadowCLPositionManagerMintable.sol'; + +import '../../../contracts/interfaces/external/IRamsesV3Factory.sol'; +import '../../../contracts/interfaces/external/IRamsesV3Pool.sol'; +import '../../../contracts/interfaces/external/shadow-cl/IRamsesV3PoolDeployer.sol'; +import '../../../contracts/libraries/ShadowPoolAddress.sol'; +import '../../../contracts/interfaces/external/shadow-cl/periphery/IShadowCLNonfungiblePositionManager.sol'; import './TokensSetup.sol'; contract UniswapSetup is TokensSetup { @@ -125,6 +134,21 @@ contract UniswapSetup is TokensSetup { IAeroCLPool public aeroCLDaiUsdcPool; IAeroCLPool public aeroCLDaiUsdtPool; + IRamsesV3Factory public shadowCLFactory; + IRamsesV3PoolDeployer public shadowCLPoolDeployer; + address public shadowCLPositionManager; + int24 public shadowCLTickSpacing = 100; + IRamsesV3Pool public shadowCLWethUsdcPool; + IRamsesV3Pool public shadowCLWethUsdtPool; + IRamsesV3Pool public shadowCLWethDaiPool; + IRamsesV3Pool public shadowCLWbtcWethPool; + IRamsesV3Pool public shadowCLWbtcUsdcPool; + IRamsesV3Pool public shadowCLWbtcUsdtPool; + IRamsesV3Pool public shadowCLWbtcDaiPool; + IRamsesV3Pool public shadowCLUsdtUsdcPool; + IRamsesV3Pool public shadowCLDaiUsdcPool; + IRamsesV3Pool public shadowCLDaiUsdtPool; + function initUniswapV3(address owner) public { bytes memory factoryBytecode = abi.encodePacked(vm.getCode("./node_modules/@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json")); assembly { @@ -634,6 +658,225 @@ contract UniswapSetup is TokensSetup { vm.stopPrank(); } + function initShadowCL(address owner) public { + console.log("Starting ShadowCL initialization with owner:", owner); + console.log("msg.sender"); + console.logAddress(msg.sender); + address accessHub = address(0x1); + + bytes memory factoryArgs = abi.encode(accessHub); + vm.prank(owner); + bytes memory factoryBytecode = abi.encodePacked( + vm.getCode("./test/foundry/bytecodes/shadow-cl/RamsesV3Factory.json"), + factoryArgs + ); + + address factoryAddress; + assembly { + factoryAddress := create(0, add(factoryBytecode, 0x20), mload(factoryBytecode)) + } + shadowCLFactory = IRamsesV3Factory(factoryAddress); + console.log('shadowCLFactory: ', address(shadowCLFactory)); + + bytes memory poolDeployerBytecode = vm.getCode("./test/foundry/bytecodes/shadow-cl/RamsesV3PoolDeployer.json"); + + bytes memory modifiedPoolDeployerBytecode = replaceAddressAtEnd( + poolDeployerBytecode, + factoryAddress + ); + + console.log("modified pooldeployer bytecode"); + console.logBytes(modifiedPoolDeployerBytecode); + + address poolDeployerAddress; + console.logAddress(msg.sender); + assembly { + poolDeployerAddress := create(0, add(modifiedPoolDeployerBytecode, 0x20), mload(modifiedPoolDeployerBytecode)) + } + + shadowCLPoolDeployer = IRamsesV3PoolDeployer(poolDeployerAddress); + console.log("PoolDeployer deployed at:", address(shadowCLPoolDeployer)); + + // Initialize the factory with the pool deployer address + vm.prank(owner); + try shadowCLFactory.initialize(address(shadowCLPoolDeployer)) { + console.log("Factory initialized successfully"); + } catch { + console.log("Factory initialization failed - might already be initialized"); + } + + try shadowCLFactory.ramsesV3PoolDeployer() returns (address poolDeployerFromFactory) { + console.log('poolDeployerFromFactory: ', poolDeployerFromFactory); + require(poolDeployerFromFactory == address(shadowCLPoolDeployer), "pool deployer mismatch"); + } catch { + console.log("Could not get pool deployer from factory - function might not exist"); + } + + address factoryFromPoolDeployer = shadowCLPoolDeployer.RamsesV3Factory(); + console.log('factoryFromPoolDeployer (recheck): ', factoryFromPoolDeployer); + require(factoryFromPoolDeployer == address(shadowCLFactory), "factory mismatch"); + + bytes memory descriptorBytecode = vm.getCode("./test/foundry/bytecodes/shadow-cl/NonfungibleTokenPositionDescriptor.json"); + bytes memory modifiedDescriptorBytecode = replaceAddressAtEnd( + descriptorBytecode, + address(weth) + ); + + address shadowCLNFTDescriptor; + assembly { + shadowCLNFTDescriptor := create(0, add(modifiedDescriptorBytecode, 0x20), mload(modifiedDescriptorBytecode)) + } + console.log("shadowCLNFTDescriptor", shadowCLNFTDescriptor); + + bytes memory positionManagerBytecode = vm.getCode("./test/foundry/bytecodes/shadow-cl/NonfungiblePositionManager.json"); + + + address[] memory replacementAddresses = new address[](4); + replacementAddresses[0] = address(shadowCLPoolDeployer); + replacementAddresses[1] = address(weth); + replacementAddresses[2] = shadowCLNFTDescriptor; + replacementAddresses[3] = accessHub; + + bytes memory modifiedPositionManagerBytecode = replaceImmutableAddresses( + positionManagerBytecode, + replacementAddresses + ); + console.log("modified bytecode for position manager"); + console.logBytes(modifiedPositionManagerBytecode); + + address positionManager; + assembly { + positionManager := create(0, add(modifiedPositionManagerBytecode, 0x20), mload(modifiedPositionManagerBytecode)) + } + + shadowCLPositionManager = positionManager; + console.log('shadowCLPositionManager: ', shadowCLPositionManager); + + + console.log("weth", address(weth)); + console.log("usdc", address(usdc)); + console.log("shadowCLTickSpacing"); + console.logInt(shadowCLTickSpacing); + console.log("wethUsdcSqrtPriceX96"); + console.logUint(wethUsdcSqrtPriceX96); + uint24 fee = shadowCLFactory.tickSpacingInitialFee(shadowCLTickSpacing); + console.log("fee"); + console.logUint(fee); + address factory = shadowCLPoolDeployer.RamsesV3Factory(); + console.log("poolAddress", factory); + require(factory == address(shadowCLFactory), "FT"); + + shadowCLWethUsdcPool = IRamsesV3Pool(shadowCLFactory.createPool( + address(weth), address(usdc), shadowCLTickSpacing, wethUsdcSqrtPriceX96 + )); + console.log('shadowCLWethUsdcPool deployed at: ', address(shadowCLWethUsdcPool)); + // shadowCLWethUsdtPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(weth), address(usdt), shadowCLTickSpacing, wethUsdcSqrtPriceX96 + // )); + // shadowCLWethDaiPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(weth), address(dai), shadowCLTickSpacing, wethDaiSqrtPriceX96 + // )); + // shadowCLWbtcWethPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(wbtc), address(weth), shadowCLTickSpacing, wbtcWethSqrtPriceX96 + // )); + // shadowCLWbtcUsdcPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(wbtc), address(usdc), shadowCLTickSpacing, wbtcUsdcSqrtPriceX96 + // )); + // shadowCLWbtcUsdtPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(wbtc), address(usdt), shadowCLTickSpacing, wbtcUsdcSqrtPriceX96 + // )); + // shadowCLWbtcDaiPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(wbtc), address(dai), shadowCLTickSpacing, wbtcDaiSqrtPriceX96 + // )); + // shadowCLUsdtUsdcPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(usdt), address(usdc), shadowCLTickSpacing, usdtUsdcSqrtPriceX96 + // )); + // shadowCLDaiUsdcPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(dai), address(usdc), shadowCLTickSpacing, daiUsdcSqrtPriceX96 + // )); + // shadowCLDaiUsdtPool = IRamsesV3Pool(shadowCLFactory.createPool( + // address(dai), address(usdt), shadowCLTickSpacing, daiUsdcSqrtPriceX96 + // )); + + weth.mint(owner, 120); + usdc.mint(owner, 350_000); + // weth.mint(owner, 890); + // usdt.mint(owner, 2_700_000); + // weth.mint(owner, 120); + // dai.mint(owner, 350_000); + // weth.mint(owner, 220); + // wbtc.mint(owner, 11); + // wbtc.mint(owner, 11); + // usdc.mint(owner, 660_000); + // wbtc.mint(owner, 11); + // usdt.mint(owner, 660_000); + // wbtc.mint(owner, 11); + // dai.mint(owner, 660_000); + // usdc.mint(owner, 660_000); + // usdt.mint(owner, 660_000); + // usdc.mint(owner, 660_000); + // dai.mint(owner, 660_000); + // usdt.mint(owner, 660_000); + // dai.mint(owner, 660_000); + + vm.startPrank(owner); + + weth.approve(shadowCLPositionManager, type(uint256).max); + console.log("approved weth"); + usdc.approve(shadowCLPositionManager, type(uint256).max); + console.log("approved usdc"); + // usdt.approve(shadowCLPositionManager, type(uint256).max); + // wbtc.approve(shadowCLPositionManager, type(uint256).max); + // dai.approve(shadowCLPositionManager, type(uint256).max); + + address poolAddress = ShadowPoolAddress.computeAddress( + address(shadowCLPoolDeployer), + ShadowPoolAddress.PoolKey({ + token0: address(weth) < address(usdc) ? address(weth) : address(usdc), + token1: address(weth) < address(usdc) ? address(usdc) : address(weth), + tickSpacing: shadowCLTickSpacing + }) + ); + console.log("Pool address:", poolAddress); + console.log("Is this the expected pool address?", poolAddress == address(shadowCLWethUsdcPool)); + + console.log("Pool fee:"); + uint24 poolFee = shadowCLWethUsdcPool.fee(); + console.logUint(poolFee); + + address deployerFromManager = IShadowCLNonfungiblePositionManager(shadowCLPositionManager).deployer(); + console.log("Deployer from position manager:", deployerFromManager); + console.log("Shadow CL pool deployer:", address(shadowCLPoolDeployer)); + console.log("Match?", deployerFromManager == address(shadowCLPoolDeployer)); + address wethFromManager = IShadowCLNonfungiblePositionManager(shadowCLPositionManager).WETH9(); + console.log("WETH9 from position manager:", wethFromManager); + console.log("WETH9 from pool deployer:", address(weth)); + console.log("Match?", wethFromManager == address(weth)); + + + (uint256 tokenId,,,) = addLiquidityShadowCL(shadowCLPositionManager, address(weth), address(usdc), shadowCLTickSpacing, 115594502247137145239, 345648123455); + console.log("added liquidity"); + console.logUint(tokenId); + try IRamsesV3Pool(poolAddress).liquidity() returns (uint128 currentLiquidity) { + console.log("Pool has liquidity:"); + console.logUint(currentLiquidity); + } catch { + console.log("Failed to query pool liquidity"); + } + + // addLiquidityShadowCL(shadowCLPositionManager, address(weth), address(usdt), shadowCLTickSpacing, 887209737429288199534, 2680657431182); + // addLiquidityShadowCL(shadowCLPositionManager, address(weth), address(dai), shadowCLTickSpacing, 115594502247137145239, 345648123455000000000000); + // addLiquidityShadowCL(shadowCLPositionManager, address(wbtc), address(weth), shadowCLTickSpacing, 1012393293, 217378372286812000000); + // addLiquidityShadowCL(shadowCLPositionManager, address(wbtc), address(usdc), shadowCLTickSpacing, 1012393293, 658055640487); + // addLiquidityShadowCL(shadowCLPositionManager, address(wbtc), address(usdt), shadowCLTickSpacing, 1013393293, 659055640487); + // addLiquidityShadowCL(shadowCLPositionManager, address(wbtc), address(dai), shadowCLTickSpacing, 1011393293, 657055640487000000000000); + // addLiquidityShadowCL(shadowCLPositionManager, address(usdt), address(usdc), shadowCLTickSpacing, 658055640487, 659055640487); + // addLiquidityShadowCL(shadowCLPositionManager, address(dai), address(usdc), shadowCLTickSpacing, 657055640487000000000000, 658055640487); + // addLiquidityShadowCL(shadowCLPositionManager, address(dai), address(usdt), shadowCLTickSpacing, 657055640487000000000000, 656055640487); + + vm.stopPrank(); + } + function addLiquidity(address token0, address token1, uint256 amount0, uint256 amount1, address to) public returns (uint256 amountA, uint256 amountB, uint256 liquidity) { (amountA, amountB, liquidity) = uniRouter.addLiquidity(token0, token1, amount0, amount1, 0, 0, to, type(uint256).max); } @@ -688,4 +931,106 @@ contract UniswapSetup is TokensSetup { }); IAeroPositionManagerMintable(nftPositionManager).mint(mintParams); } -} \ No newline at end of file + + function addLiquidityShadowCL( + address nftPositionManager, + address token0, + address token1, + int24 tickSpacing, + uint256 amount0, + uint256 amount1 + ) internal returns (uint256 tokenId, uint128 liquidity, uint256 amount0Used, uint256 amount1Used) { + console.log('msg.sender: '); + console.logAddress(msg.sender); + (address token0, address token1) = token0 < token1 + ? (token0, token1) + : (token1, token0); + + (uint256 amount0, uint256 amount1) = token0 < token1 + ? (amount0, amount1) + : (amount1, amount0); + + IShadowCLNonfungiblePositionManager.MintParams memory params = IShadowCLNonfungiblePositionManager.MintParams({ + token0: token0, + token1: token1, + tickSpacing: tickSpacing, + tickLower: -887200, + tickUpper: 887200, + amount0Desired: amount0, + amount1Desired: amount1, + amount0Min: 0, + amount1Min: 0, + recipient: msg.sender, + deadline: type(uint256).max + }); + // return IShadowCLPositionManagerMintable(nftPositionManager).mint(params); + try IShadowCLNonfungiblePositionManager(shadowCLPositionManager).mint(params) returns ( + uint256 tokenId, + uint128 liquidity, + uint256 amount0, + uint256 amount1 + ) { + console.log("Mint successful!"); + console.log("Token ID:", tokenId); + console.log("Liquidity:", uint256(liquidity)); + console.log("Amount0 used:", amount0); + console.log("Amount1 used:", amount1); + return (tokenId, liquidity, amount0, amount1); + } catch Error(string memory reason) { + console.log("Mint failed with reason:", reason); + return (0, 0, 0, 0); + } catch { + console.log("Mint failed with unknown error"); + return (0, 0, 0, 0); + } + } + + function replaceAddressAtEnd(bytes memory bytecode, address newAddress) internal pure returns (bytes memory) { + // Create a copy of the original bytecode + bytes memory result = new bytes(bytecode.length); + for (uint i = 0; i < bytecode.length; i++) { + result[i] = bytecode[i]; + } + + // Replace the last 20 bytes (address size) with the new address + // Note: This assumes the address is at the very end and not encoded with additional padding + + bytes memory addressBytes = abi.encodePacked(newAddress); + for (uint i = 0; i < 20; i++) { + result[result.length - 20 + i] = addressBytes[i]; + } + + return result; + } + + function replaceImmutableAddresses( + bytes memory bytecode, + address[] memory replacementAddresses + ) internal pure returns (bytes memory) { + // Create a copy of the original bytecode + bytes memory result = new bytes(bytecode.length); + for (uint i = 0; i < bytecode.length; i++) { + result[i] = bytecode[i]; + } + + // For immutables, we know they're at the end of the bytecode + // Each address is 20 bytes, packed in 32-byte slots at the end + uint256 startPos = result.length - (replacementAddresses.length * 32); + + // Replace each address in reverse order (starting from the last one) + for (uint i = 0; i < replacementAddresses.length; i++) { + address replacement = replacementAddresses[i]; + bytes memory replacementBytes = abi.encodePacked(replacement); + + // Calculate position for this immutable (20 bytes at the end of a 32-byte slot) + uint256 position = startPos + (i * 32) + 12; // 32 bytes slot - 20 bytes address = 12 bytes offset + + // Replace the address (20 bytes) + for (uint j = 0; j < 20; j++) { + result[position + j] = replacementBytes[j]; + } + } + + return result; + } +} diff --git a/test/foundry/routes/ShadowCLTest.t.sol b/test/foundry/routes/ShadowCLTest.t.sol new file mode 100644 index 0000000..1af6aeb --- /dev/null +++ b/test/foundry/routes/ShadowCLTest.t.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +import '../fixtures/TestBed.sol'; +import '../../../contracts/test/TestUniversalRouter.sol'; +import '../../../contracts/test/routes/TestShadowCL.sol'; + +contract ShadowCLTest is TestBed { + address owner; + TestShadowCL route; + + function setUp() public { + owner = vm.addr(1); + initSetup(owner); + + route = new TestShadowCL(8, address(shadowCLPoolDeployer), address(weth)); + } + + function testConstants() public { + assertEq(route.protocolId(), 8); + assertEq(route.factory(), address(shadowCLFactory)); + assertEq(route.WETH(), address(weth)); + } + + function testPairFor() public { + address pair = route.getPairFor(address(usdc), address(weth), shadowCLTickSpacing); + assertEq(pair, address(shadowCLWethUsdcPool)); + + pair = route.getPairFor(address(weth), address(usdc), shadowCLTickSpacing); + assertEq(pair, address(shadowCLWethUsdcPool)); + } + + function testDecodePrice() public { + (uint256 sqrtPriceX96,,,,,,) = shadowCLWethUsdcPool.slot0(); + uint8 decimals = GammaSwapLibrary.decimals(shadowCLWethUsdcPool.token0()); + uint256 price = route.getDecodedPrice(sqrtPriceX96, 10**decimals); + assertApproxEqRel(price, 2999999999, 1e14); + } + + function testQuote() public { + uint256 amountIn = 1e18; + uint256 amountOut = route.quote(amountIn, address(weth), address(usdc), uint24(shadowCLTickSpacing)); + assertGt(amountOut, 0); + } + + function testGetOrigin() public { + (address pair, address origin) = route.getOrigin(address(weth), address(usdc), uint24(shadowCLTickSpacing)); + assertEq(pair, address(shadowCLWethUsdcPool)); + assertEq(origin, address(route)); + } + + function testGetAmountOut() public { + uint256 amountIn = 1e18; + (uint256 amountOut, address pair, uint24 swapFee) = route.getAmountOut(amountIn, address(weth), address(usdc), uint24(shadowCLTickSpacing)); + assertEq(pair, address(shadowCLWethUsdcPool)); + assertEq(swapFee, uint24(shadowCLTickSpacing)); + assertGt(amountOut, 0); + } + + function testGetAmountIn() public { + uint256 amountOut = 1e6; + (uint256 amountIn, address pair, uint24 swapFee) = route.getAmountIn(amountOut, address(usdc), address(weth), uint24(shadowCLTickSpacing)); + assertEq(pair, address(shadowCLWethUsdcPool)); + assertEq(swapFee, uint24(shadowCLTickSpacing)); + assertGt(amountIn, 0); + } + + function testSwap() public { + uint256 amountIn = 1e18; + deal(address(weth), address(route), amountIn); + uint256 balanceBefore = usdc.balanceOf(owner); + + vm.startPrank(owner); + route.swap(address(weth), address(usdc), uint24(shadowCLTickSpacing), owner); + vm.stopPrank(); + + uint256 balanceAfter = usdc.balanceOf(owner); + assertGt(balanceAfter, balanceBefore); + } +}