Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Quoter
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 1000000
- EVM Version
- default
- Verified at
- 2024-03-11T10:38:50.309867Z
Constructor Arguments
0x000000000000000000000000d8676fbdfa5b56bb2298d452c9768f51e80e34ae0000000000000000000000003fb787101dc6be47cfe18aeee15404dcc842e6af0000000000000000000000005822a45b05d08028baa3d19626870076d26bc460
Arg [0] (address) : 0xd8676fbdfa5b56bb2298d452c9768f51e80e34ae
Arg [1] (address) : 0x3fb787101dc6be47cfe18aeee15404dcc842e6af
Arg [2] (address) : 0x5822a45b05d08028baa3d19626870076d26bc460
contracts/lens/Quoter.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; pragma abicoder v2; import '@cryptoalgebra/core/contracts/libraries/SafeCast.sol'; import '@cryptoalgebra/core/contracts/libraries/TickMath.sol'; import '@cryptoalgebra/core/contracts/libraries/FullMath.sol'; import '@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/core/contracts/interfaces/callback/IAlgebraSwapCallback.sol'; import '../interfaces/IQuoter.sol'; import '../base/PeripheryImmutableState.sol'; import '../libraries/Path.sol'; import '../libraries/PoolAddress.sol'; import '../libraries/CallbackValidation.sol'; /// @title Provides quotes for swaps /// @notice Allows getting the expected amount out or amount in for a given swap without executing the swap /// @dev These functions are not gas efficient and should _not_ be called on chain. Instead, optimistically execute /// the swap and check the amounts in the callback. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery contract Quoter is IQuoter, IAlgebraSwapCallback, PeripheryImmutableState { using Path for bytes; using SafeCast for uint256; /// @dev Transient storage variable used to check a safety condition in exact output swaps. uint256 private amountOutCached; constructor( address _factory, address _WNativeToken, address _poolDeployer ) PeripheryImmutableState(_factory, _WNativeToken, _poolDeployer) {} function getPool(address tokenA, address tokenB) private view returns (IAlgebraPool) { return IAlgebraPool(PoolAddress.computeAddress(poolDeployer, PoolAddress.getPoolKey(tokenA, tokenB))); } /// @inheritdoc IAlgebraSwapCallback function algebraSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes memory path ) external view override { require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported (address tokenIn, address tokenOut) = path.decodeFirstPool(); CallbackValidation.verifyCallback(poolDeployer, tokenIn, tokenOut); (bool isExactInput, uint256 amountToPay, uint256 amountReceived) = amount0Delta > 0 ? (tokenIn < tokenOut, uint256(amount0Delta), uint256(-amount1Delta)) : (tokenOut < tokenIn, uint256(amount1Delta), uint256(-amount0Delta)); IAlgebraPool pool = getPool(tokenIn, tokenOut); uint16 fee; (, , uint16 feeZto, uint16 feeOtz, , , , ) = pool.globalState(); fee = tokenIn < tokenOut ? feeZto : feeOtz; if (isExactInput) { assembly { let ptr := mload(0x40) mstore(ptr, amountReceived) mstore(add(ptr, 0x20), fee) revert(ptr, 64) } } else { // if the cache has been populated, ensure that the full output amount has been received if (amountOutCached != 0) require(amountReceived == amountOutCached); assembly { let ptr := mload(0x40) mstore(ptr, amountToPay) mstore(add(ptr, 0x20), fee) revert(ptr, 64) } } } /// @dev Parses a revert reason that should contain the numeric quote function parseRevertReason(bytes memory reason) private pure returns (uint256, uint16) { if (reason.length != 64) { if (reason.length < 68) revert('Unexpected error'); assembly { reason := add(reason, 0x04) } revert(abi.decode(reason, (string))); } return abi.decode(reason, (uint256, uint16)); } /// @inheritdoc IQuoter function quoteExactInputSingle( address tokenIn, address tokenOut, uint256 amountIn, uint160 limitSqrtPrice ) public override returns (uint256 amountOut, uint16 fee) { bool zeroToOne = tokenIn < tokenOut; try getPool(tokenIn, tokenOut).swap( address(this), // address(0) might cause issues with some tokens zeroToOne, amountIn.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encodePacked(tokenIn, tokenOut) ) {} catch (bytes memory reason) { (amountOut, fee) = parseRevertReason(reason); } } /// @inheritdoc IQuoter function quoteExactInput(bytes memory path, uint256 amountIn) external override returns (uint256 amountOut, uint16[] memory fees) { fees = new uint16[](path.numPools()); uint256 i = 0; while (true) { bool hasMultiplePools = path.hasMultiplePools(); (address tokenIn, address tokenOut) = path.decodeFirstPool(); // the outputs of prior swaps become the inputs to subsequent ones (amountIn, fees[i]) = quoteExactInputSingle(tokenIn, tokenOut, amountIn, 0); // decide whether to continue or terminate if (hasMultiplePools) { path = path.skipToken(); } else { return (amountIn, fees); } i++; } } /// @inheritdoc IQuoter function quoteExactOutputSingle( address tokenIn, address tokenOut, uint256 amountOut, uint160 limitSqrtPrice ) public override returns (uint256 amountIn, uint16 fee) { bool zeroToOne = tokenIn < tokenOut; // if no price limit has been specified, cache the output amount for comparison in the swap callback if (limitSqrtPrice == 0) amountOutCached = amountOut; try getPool(tokenIn, tokenOut).swap( address(this), // address(0) might cause issues with some tokens zeroToOne, -amountOut.toInt256(), limitSqrtPrice == 0 ? (zeroToOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtPrice, abi.encodePacked(tokenOut, tokenIn) ) {} catch (bytes memory reason) { if (limitSqrtPrice == 0) delete amountOutCached; // clear cache (amountIn, fee) = parseRevertReason(reason); } } /// @inheritdoc IQuoter function quoteExactOutput(bytes memory path, uint256 amountOut) external override returns (uint256 amountIn, uint16[] memory fees) { fees = new uint16[](path.numPools()); uint256 i = 0; while (true) { bool hasMultiplePools = path.hasMultiplePools(); (address tokenOut, address tokenIn) = path.decodeFirstPool(); // the inputs of prior swaps become the outputs of subsequent ones (amountOut, fees[i]) = quoteExactOutputSingle(tokenIn, tokenOut, amountOut, 0); // decide whether to continue or terminate if (hasMultiplePools) { path = path.skipToken(); } else { return (amountOut, fees); } i++; } } }
contracts/base/PeripheryImmutableState.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; import '../interfaces/IPeripheryImmutableState.sol'; /// @title Immutable state /// @notice Immutable state used by periphery contracts /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery abstract contract PeripheryImmutableState is IPeripheryImmutableState { /// @inheritdoc IPeripheryImmutableState address public immutable override factory; /// @inheritdoc IPeripheryImmutableState address public immutable override poolDeployer; /// @inheritdoc IPeripheryImmutableState address public immutable override WNativeToken; constructor( address _factory, address _WNativeToken, address _poolDeployer ) { factory = _factory; poolDeployer = _poolDeployer; WNativeToken = _WNativeToken; } }
@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import './pool/IAlgebraPoolImmutables.sol'; import './pool/IAlgebraPoolState.sol'; import './pool/IAlgebraPoolDerivedState.sol'; import './pool/IAlgebraPoolActions.sol'; import './pool/IAlgebraPoolPermissionedActions.sol'; import './pool/IAlgebraPoolEvents.sol'; /** * @title The interface for a Algebra Pool * @dev The pool interface is broken up into many smaller pieces. * Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPool is IAlgebraPoolImmutables, IAlgebraPoolState, IAlgebraPoolDerivedState, IAlgebraPoolActions, IAlgebraPoolPermissionedActions, IAlgebraPoolEvents { // used only for combining interfaces }
@cryptoalgebra/core/contracts/interfaces/IDataStorageOperator.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; pragma abicoder v2; import '../libraries/AdaptiveFee.sol'; interface IDataStorageOperator { event FeeConfiguration(bool zto, AdaptiveFee.Configuration feeConfig); /** * @notice Returns data belonging to a certain timepoint * @param index The index of timepoint in the array * @dev There is more convenient function to fetch a timepoint: getTimepoints(). Which requires not an index but seconds * @return initialized Whether the timepoint has been initialized and the values are safe to use, * blockTimestamp The timestamp of the observation, * tickCumulative The tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp, * secondsPerLiquidityCumulative The seconds per in range liquidity for the life of the pool as of the timepoint timestamp, * volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp, * averageTick Time-weighted average tick, * volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp */ function timepoints(uint256 index) external view returns ( bool initialized, uint32 blockTimestamp, int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint88 volatilityCumulative, int24 averageTick, uint144 volumePerLiquidityCumulative ); /// @notice Initialize the dataStorage array by writing the first slot. Called once for the lifecycle of the timepoints array /// @param time The time of the dataStorage initialization, via block.timestamp truncated to uint32 /// @param tick Initial tick function initialize(uint32 time, int24 tick) external; /// @dev Reverts if an timepoint at or before the desired timepoint timestamp does not exist. /// 0 may be passed as `secondsAgo' to return the current cumulative values. /// If called with a timestamp falling between two timepoints, returns the counterfactual accumulator values /// at exactly the timestamp between the two timepoints. /// @param time The current block timestamp /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an timepoint /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return tickCumulative The cumulative tick since the pool was first initialized, as of `secondsAgo` /// @return secondsPerLiquidityCumulative The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of `secondsAgo` /// @return volatilityCumulative The cumulative volatility value since the pool was first initialized, as of `secondsAgo` /// @return volumePerAvgLiquidity The cumulative volume per liquidity value since the pool was first initialized, as of `secondsAgo` function getSingleTimepoint( uint32 time, uint32 secondsAgo, int24 tick, uint16 index, uint128 liquidity ) external view returns ( int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint112 volatilityCumulative, uint256 volumePerAvgLiquidity ); /// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos` /// @dev Reverts if `secondsAgos` > oldest timepoint /// @param time The current block.timestamp /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an timepoint /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return tickCumulatives The cumulative tick since the pool was first initialized, as of each `secondsAgo` /// @return secondsPerLiquidityCumulatives The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of each `secondsAgo` /// @return volatilityCumulatives The cumulative volatility values since the pool was first initialized, as of each `secondsAgo` /// @return volumePerAvgLiquiditys The cumulative volume per liquidity values since the pool was first initialized, as of each `secondsAgo` function getTimepoints( uint32 time, uint32[] memory secondsAgos, int24 tick, uint16 index, uint128 liquidity ) external view returns ( int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulatives, uint112[] memory volatilityCumulatives, uint256[] memory volumePerAvgLiquiditys ); /// @notice Returns average volatility in the range from time-WINDOW to time /// @param time The current block.timestamp /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return TWVolatilityAverage The average volatility in the recent range /// @return TWVolumePerLiqAverage The average volume per liquidity in the recent range function getAverages( uint32 time, int24 tick, uint16 index, uint128 liquidity ) external view returns (uint112 TWVolatilityAverage, uint256 TWVolumePerLiqAverage); /// @notice Writes an dataStorage timepoint to the array /// @dev Writable at most once per block. Index represents the most recently written element. index must be tracked externally. /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param blockTimestamp The timestamp of the new timepoint /// @param tick The active tick at the time of the new timepoint /// @param liquidity The total in-range liquidity at the time of the new timepoint /// @param volumePerLiquidity The gmean(volumes)/liquidity at the time of the new timepoint /// @return indexUpdated The new index of the most recently written element in the dataStorage array function write( uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint128 volumePerLiquidity ) external returns (uint16 indexUpdated); /// @notice Changes fee configuration for the pool function changeFeeConfiguration(bool zto, AdaptiveFee.Configuration calldata feeConfig) external; /// @notice Calculates gmean(volume/liquidity) for block /// @param liquidity The current in-range pool liquidity /// @param amount0 Total amount of swapped token0 /// @param amount1 Total amount of swapped token1 /// @return volumePerLiquidity gmean(volume/liquidity) capped by 100000 << 64 function calculateVolumePerLiquidity( uint128 liquidity, int256 amount0, int256 amount1 ) external pure returns (uint128 volumePerLiquidity); /// @return windowLength Length of window used to calculate averages function window() external view returns (uint32 windowLength); /// @notice Calculates fee based on combination of sigmoids /// @param time The current block.timestamp /// @param tick The current tick /// @param index The index of the timepoint that was most recently written to the timepoints array /// @param liquidity The current in-range pool liquidity /// @return feeZto The fee for ZtO swaps in hundredths of a bip, i.e. 1e-6 /// @return feeOtz The fee for OtZ swaps in hundredths of a bip, i.e. 1e-6 function getFees( uint32 time, int24 tick, uint16 index, uint128 liquidity ) external view returns (uint16 feeZto, uint16 feeOtz); }
@cryptoalgebra/core/contracts/interfaces/callback/IAlgebraSwapCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IAlgebraPoolActions#swap /// @notice Any contract that calls IAlgebraPoolActions#swap must implement this interface /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraSwapCallback { /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call function algebraSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolActions.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissionless pool actions /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolActions { /** * @notice Sets the initial price for the pool * @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value * @param price the initial sqrt price of the pool as a Q64.96 */ function initialize(uint160 price) external; /** * @notice Adds liquidity for the given recipient/bottomTick/topTick position * @dev The caller of this method receives a callback in the form of IAlgebraMintCallback# AlgebraMintCallback * in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends * on bottomTick, topTick, the amount of liquidity, and the current price. * @param sender The address which will receive potential surplus of paid tokens * @param recipient The address for which the liquidity will be created * @param bottomTick The lower tick of the position in which to add liquidity * @param topTick The upper tick of the position in which to add liquidity * @param amount The desired amount of liquidity to mint * @param data Any data that should be passed through to the callback * @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback * @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback * @return liquidityActual The actual minted amount of liquidity */ function mint( address sender, address recipient, int24 bottomTick, int24 topTick, uint128 amount, bytes calldata data ) external returns ( uint256 amount0, uint256 amount1, uint128 liquidityActual ); /** * @notice Collects tokens owed to a position * @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. * Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or * amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the * actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. * @param recipient The address which should receive the fees collected * @param bottomTick The lower tick of the position for which to collect fees * @param topTick The upper tick of the position for which to collect fees * @param amount0Requested How much token0 should be withdrawn from the fees owed * @param amount1Requested How much token1 should be withdrawn from the fees owed * @return amount0 The amount of fees collected in token0 * @return amount1 The amount of fees collected in token1 */ function collect( address recipient, int24 bottomTick, int24 topTick, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); /** * @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position * @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 * @dev Fees must be collected separately via a call to #collect * @param bottomTick The lower tick of the position for which to burn liquidity * @param topTick The upper tick of the position for which to burn liquidity * @param amount How much liquidity to burn * @return amount0 The amount of token0 sent to the recipient * @return amount1 The amount of token1 sent to the recipient */ function burn( int24 bottomTick, int24 topTick, uint128 amount ) external returns (uint256 amount0, uint256 amount1); /** * @notice Swap token0 for token1, or token1 for token0 * @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback# AlgebraSwapCallback * @param recipient The address to receive the output of the swap * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this * value after the swap. If one for zero, the price cannot be greater than this value after the swap * @param data Any data to be passed through to the callback. If using the Router it should contain * SwapRouter#SwapCallbackData * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive */ function swap( address recipient, bool zeroToOne, int256 amountSpecified, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /** * @notice Swap token0 for token1, or token1 for token0 (tokens that have fee on transfer) * @dev The caller of this method receives a callback in the form of I AlgebraSwapCallback# AlgebraSwapCallback * @param sender The address called this function (Comes from the Router) * @param recipient The address to receive the output of the swap * @param zeroToOne The direction of the swap, true for token0 to token1, false for token1 to token0 * @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) * @param limitSqrtPrice The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this * value after the swap. If one for zero, the price cannot be greater than this value after the swap * @param data Any data to be passed through to the callback. If using the Router it should contain * SwapRouter#SwapCallbackData * @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive * @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive */ function swapSupportingFeeOnInputTokens( address sender, address recipient, bool zeroToOne, int256 amountSpecified, uint160 limitSqrtPrice, bytes calldata data ) external returns (int256 amount0, int256 amount1); /** * @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback * @dev The caller of this method receives a callback in the form of IAlgebraFlashCallback# AlgebraFlashCallback * @dev All excess tokens paid in the callback are distributed to liquidity providers as an additional fee. So this method can be used * to donate underlying tokens to currently in-range liquidity providers by calling with 0 amount{0,1} and sending * the donation amount(s) from the callback * @param recipient The address which will receive the token0 and token1 amounts * @param amount0 The amount of token0 to send * @param amount1 The amount of token1 to send * @param data Any data to be passed through to the callback */ function flash( address recipient, uint256 amount0, uint256 amount1, bytes calldata data ) external; }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolDerivedState.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title Pool state that is not stored * @notice Contains view functions to provide information about the pool that is computed rather than stored on the * blockchain. The functions here may have variable gas costs. * @dev Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPoolDerivedState { /** * @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp * @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing * the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, * you must call it with secondsAgos = [3600, 0]. * @dev The time weighted average tick represents the geometric time weighted average price of the pool, in * log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. * @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned * @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp * @return secondsPerLiquidityCumulatives Cumulative seconds per liquidity-in-range value as of each `secondsAgos` * from the current block timestamp * @return volatilityCumulatives Cumulative standard deviation as of each `secondsAgos` * @return volumePerAvgLiquiditys Cumulative swap volume per liquidity as of each `secondsAgos` */ function getTimepoints(uint32[] calldata secondsAgos) external view returns ( int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulatives, uint112[] memory volatilityCumulatives, uint256[] memory volumePerAvgLiquiditys ); /** * @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range * @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed. * I.e., snapshots cannot be compared if a position is not held for the entire period between when the first * snapshot is taken and the second snapshot is taken. * @param bottomTick The lower tick of the range * @param topTick The upper tick of the range * @return innerTickCumulative The snapshot of the tick accumulator for the range * @return innerSecondsSpentPerLiquidity The snapshot of seconds per liquidity for the range * @return innerSecondsSpent The snapshot of the number of seconds during which the price was in this range */ function getInnerCumulatives(int24 bottomTick, int24 topTick) external view returns ( int56 innerTickCumulative, uint160 innerSecondsSpentPerLiquidity, uint32 innerSecondsSpent ); }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolEvents.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Events emitted by a pool /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolEvents { /** * @notice Emitted exactly once by a pool when #initialize is first called on the pool * @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize * @param price The initial sqrt price of the pool, as a Q64.96 * @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool */ event Initialize(uint160 price, int24 tick); /** * @notice Emitted when liquidity is minted for a given position * @param sender The address that minted the liquidity * @param owner The owner of the position and recipient of any minted liquidity * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param liquidityAmount The amount of liquidity minted to the position range * @param amount0 How much token0 was required for the minted liquidity * @param amount1 How much token1 was required for the minted liquidity */ event Mint( address sender, address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1 ); /** * @notice Emitted when fees are collected by the owner of a position * @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees * @param owner The owner of the position for which fees are collected * @param recipient The address that received fees * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param amount0 The amount of token0 fees collected * @param amount1 The amount of token1 fees collected */ event Collect(address indexed owner, address recipient, int24 indexed bottomTick, int24 indexed topTick, uint128 amount0, uint128 amount1); /** * @notice Emitted when a position's liquidity is removed * @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect * @param owner The owner of the position for which liquidity is removed * @param bottomTick The lower tick of the position * @param topTick The upper tick of the position * @param liquidityAmount The amount of liquidity to remove * @param amount0 The amount of token0 withdrawn * @param amount1 The amount of token1 withdrawn */ event Burn(address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1); /** * @notice Emitted by the pool for any swaps between token0 and token1 * @param sender The address that initiated the swap call, and that received the callback * @param recipient The address that received the output of the swap * @param amount0 The delta of the token0 balance of the pool * @param amount1 The delta of the token1 balance of the pool * @param price The sqrt(price) of the pool after the swap, as a Q64.96 * @param liquidity The liquidity of the pool after the swap * @param tick The log base 1.0001 of price of the pool after the swap */ event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 price, uint128 liquidity, int24 tick); /** * @notice Emitted by the pool for any flashes of token0/token1 * @param sender The address that initiated the swap call, and that received the callback * @param recipient The address that received the tokens from flash * @param amount0 The amount of token0 that was flashed * @param amount1 The amount of token1 that was flashed * @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee * @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee */ event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1); /** * @notice Emitted when the community fee is changed by the pool * @param communityFee0New The updated value of the token0 community fee percent * @param communityFee1New The updated value of the token1 community fee percent */ event CommunityFee(uint8 communityFee0New, uint8 communityFee1New); /** * @notice Emitted when the tick spacing changes * @param newTickSpacing The updated value of the new tick spacing */ event TickSpacing(int24 newTickSpacing); /** * @notice Emitted when new activeIncentive is set * @param virtualPoolAddress The address of a virtual pool associated with the current active incentive */ event Incentive(address indexed virtualPoolAddress); /** * @notice Emitted when the fee changes * @param feeZto The value of the token fee for zto swaps * @param feeOtz The value of the token fee for otz swaps */ event Fee(uint16 feeZto, uint16 feeOtz); /** * @notice Emitted when the LiquidityCooldown changes * @param liquidityCooldown The value of locktime for added liquidity */ event LiquidityCooldown(uint32 liquidityCooldown); }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolImmutables.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import '../IDataStorageOperator.sol'; /// @title Pool state that never changes /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolImmutables { /** * @notice The contract that stores all the timepoints and can perform actions with them * @return The operator address */ function dataStorageOperator() external view returns (address); /** * @notice The contract that deployed the pool, which must adhere to the IAlgebraFactory interface * @return The contract address */ function factory() external view returns (address); /** * @notice The first of the two tokens of the pool, sorted by address * @return The token contract address */ function token0() external view returns (address); /** * @notice The second of the two tokens of the pool, sorted by address * @return The token contract address */ function token1() external view returns (address); /** * @notice The 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); }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolPermissionedActions.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /** * @title Permissioned pool actions * @notice Contains pool methods that may only be called by the factory owner or tokenomics * @dev Credit to Uniswap Labs under GPL-2.0-or-later license: * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces */ interface IAlgebraPoolPermissionedActions { /** * @notice Set the community's % share of the fees. Cannot exceed 25% (250) * @param communityFee0 new community fee percent for token0 of the pool in thousandths (1e-3) * @param communityFee1 new community fee percent for token1 of the pool in thousandths (1e-3) */ function setCommunityFee(uint8 communityFee0, uint8 communityFee1) external; /// @notice Set the new tick spacing values. Only factory owner /// @param newTickSpacing The new tick spacing value function setTickSpacing(int24 newTickSpacing) external; /** * @notice Sets an active incentive * @param virtualPoolAddress The address of a virtual pool associated with the incentive */ function setIncentive(address virtualPoolAddress) external; /** * @notice Sets new lock time for added liquidity * @param newLiquidityCooldown The time in seconds */ function setLiquidityCooldown(uint32 newLiquidityCooldown) external; }
@cryptoalgebra/core/contracts/interfaces/pool/IAlgebraPoolState.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that can change /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces interface IAlgebraPoolState { /** * @notice The globalState structure in the pool stores many values but requires only one slot * and is exposed as a single method to save gas when accessed externally. * @return price The current price of the pool as a sqrt(token1/token0) Q64.96 value; * Returns tick The current tick of the pool, i.e. according to the last tick transition that was run; * Returns This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick * boundary; * Returns feeZto The last pool fee value for ZtO swaps in hundredths of a bip, i.e. 1e-6; * Returns feeOtz The last pool fee value for OtZ swaps in hundredths of a bip, i.e. 1e-6; * Returns timepointIndex The index of the last written timepoint; * Returns communityFeeToken0 The community fee percentage of the swap fee in thousandths (1e-3) for token0; * Returns communityFeeToken1 The community fee percentage of the swap fee in thousandths (1e-3) for token1; * Returns unlocked Whether the pool is currently locked to reentrancy; */ function globalState() external view returns ( uint160 price, int24 tick, uint16 feeZto, uint16 feeOtz, uint16 timepointIndex, uint8 communityFeeToken0, uint8 communityFeeToken1, bool unlocked ); /** * @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool * @dev This value can overflow the uint256 */ function totalFeeGrowth0Token() external view returns (uint256); /** * @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool * @dev This value can overflow the uint256 */ function totalFeeGrowth1Token() external view returns (uint256); /** * @notice The currently in range liquidity available to the pool * @dev This value has no relationship to the total liquidity across all ticks. * Returned value cannot exceed type(uint128).max */ function liquidity() external view returns (uint128); /** * @notice Look up information about a specific tick in the pool * @dev This is a public structure, so the `return` natspec tags are omitted. * @param tick The tick to look up * @return liquidityTotal the total amount of position liquidity that uses the pool either as tick lower or * tick upper; * Returns liquidityDelta how much liquidity changes when the pool price crosses the tick; * Returns outerFeeGrowth0Token the fee growth on the other side of the tick from the current tick in token0; * Returns outerFeeGrowth1Token the fee growth on the other side of the tick from the current tick in token1; * Returns outerTickCumulative the cumulative tick value on the other side of the tick from the current tick; * Returns outerSecondsPerLiquidity the seconds spent per liquidity on the other side of the tick from the current tick; * Returns outerSecondsSpent the seconds spent on the other side of the tick from the current tick; * Returns initialized Set to true if the tick is initialized, i.e. liquidityTotal is greater than 0 * otherwise equal to false. Outside values can only be used if the tick is initialized. * In addition, these values are only relative and must be used only in comparison to previous snapshots for * a specific position. */ function ticks(int24 tick) external view returns ( uint128 liquidityTotal, int128 liquidityDelta, uint256 outerFeeGrowth0Token, uint256 outerFeeGrowth1Token, int56 outerTickCumulative, uint160 outerSecondsPerLiquidity, uint32 outerSecondsSpent, bool initialized ); /** @notice Returns 256 packed tick initialized boolean values. See TickTable for more information */ function tickTable(int16 wordPosition) external view returns (uint256); /** * @notice Returns the information about a position by the position's key * @dev This is a public mapping of structures, so the `return` natspec tags are omitted. * @param key The position's key is a hash of a preimage composed by the owner, bottomTick and topTick * @return liquidityAmount The amount of liquidity in the position; * Returns lastLiquidityAddTimestamp Timestamp of last adding of liquidity; * Returns innerFeeGrowth0Token Fee growth of token0 inside the tick range as of the last mint/burn/poke; * Returns innerFeeGrowth1Token Fee growth of token1 inside the tick range as of the last mint/burn/poke; * Returns fees0 The computed amount of token0 owed to the position as of the last mint/burn/poke; * Returns fees1 The computed amount of token1 owed to the position as of the last mint/burn/poke */ function positions(bytes32 key) external view returns ( uint128 liquidityAmount, uint32 lastLiquidityAddTimestamp, uint256 innerFeeGrowth0Token, uint256 innerFeeGrowth1Token, uint128 fees0, uint128 fees1 ); /** * @notice Returns data about a specific timepoint index * @param index The element of the timepoints array to fetch * @dev You most likely want to use #getTimepoints() instead of this method to get an timepoint as of some amount of time * ago, rather than at a specific index in the array. * This is a public mapping of structures, so the `return` natspec tags are omitted. * @return initialized whether the timepoint has been initialized and the values are safe to use; * Returns blockTimestamp The timestamp of the timepoint; * Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp; * Returns secondsPerLiquidityCumulative the seconds per in range liquidity for the life of the pool as of the timepoint timestamp; * Returns volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp; * Returns averageTick Time-weighted average tick; * Returns volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp; */ function timepoints(uint256 index) external view returns ( bool initialized, uint32 blockTimestamp, int56 tickCumulative, uint160 secondsPerLiquidityCumulative, uint88 volatilityCumulative, int24 averageTick, uint144 volumePerLiquidityCumulative ); /** * @notice Returns the information about active incentive * @dev if there is no active incentive at the moment, virtualPool,endTimestamp,startTimestamp would be equal to 0 * @return virtualPool The address of a virtual pool associated with the current active incentive */ function activeIncentive() external view returns (address virtualPool); /** * @notice Returns the lock time for added liquidity */ function liquidityCooldown() external view returns (uint32 cooldownInSeconds); /** * @notice The pool tick spacing * @dev Ticks can only be used at multiples of this value * e.g.: a tickSpacing of 60 means ticks can be initialized every 60th tick, i.e., ..., -120, -60, 0, 60, 120, ... * This value is an int24 to avoid casting even though it is always positive. * @return The tick spacing */ function tickSpacing() external view returns (int24); }
@cryptoalgebra/core/contracts/libraries/AdaptiveFee.sol
// SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.7.6; import './Constants.sol'; /// @title AdaptiveFee /// @notice Calculates fee based on combination of sigmoids library AdaptiveFee { // alpha1 + alpha2 + baseFee must be <= type(uint16).max struct Configuration { uint16 alpha1; // max value of the first sigmoid uint16 alpha2; // max value of the second sigmoid uint32 beta1; // shift along the x-axis for the first sigmoid uint32 beta2; // shift along the x-axis for the second sigmoid uint16 gamma1; // horizontal stretch factor for the first sigmoid uint16 gamma2; // horizontal stretch factor for the second sigmoid uint32 volumeBeta; // shift along the x-axis for the outer volume-sigmoid uint16 volumeGamma; // horizontal stretch factor the outer volume-sigmoid uint16 baseFee; // minimum possible fee } /// @notice Calculates fee based on formula: /// baseFee + sigmoidVolume(sigmoid1(volatility, volumePerLiquidity) + sigmoid2(volatility, volumePerLiquidity)) /// maximum value capped by baseFee + alpha1 + alpha2 function getFee( uint88 volatility, uint256 volumePerLiquidity, Configuration memory config ) internal pure returns (uint16 fee) { uint256 sumOfSigmoids = sigmoid(volatility, config.gamma1, config.alpha1, config.beta1) + sigmoid(volatility, config.gamma2, config.alpha2, config.beta2); if (sumOfSigmoids > type(uint16).max) { // should be impossible, just in case sumOfSigmoids = type(uint16).max; } return uint16(config.baseFee + sigmoid(volumePerLiquidity, config.volumeGamma, uint16(sumOfSigmoids), config.volumeBeta)); // safe since alpha1 + alpha2 + baseFee _must_ be <= type(uint16).max } /// @notice calculates α / (1 + e^( (β-x) / γ)) /// that is a sigmoid with a maximum value of α, x-shifted by β, and stretched by γ /// @dev returns uint256 for fuzzy testing. Guaranteed that the result is not greater than alpha function sigmoid( uint256 x, uint16 g, uint16 alpha, uint256 beta ) internal pure returns (uint256 res) { if (x > beta) { x = x - beta; if (x >= 6 * uint256(g)) return alpha; // so x < 19 bits uint256 g8 = uint256(g)**8; // < 128 bits (8*16) uint256 ex = exp(x, g, g8); // < 155 bits res = (alpha * ex) / (g8 + ex); // in worst case: (16 + 155 bits) / 155 bits // so res <= alpha } else { x = beta - x; if (x >= 6 * uint256(g)) return 0; // so x < 19 bits uint256 g8 = uint256(g)**8; // < 128 bits (8*16) uint256 ex = g8 + exp(x, g, g8); // < 156 bits res = (alpha * g8) / ex; // in worst case: (16 + 128 bits) / 156 bits // g8 <= ex, so res <= alpha } } /// @notice calculates e^(x/g) * g^8 in a series, since (around zero): /// e^x = 1 + x + x^2/2 + ... + x^n/n! + ... /// e^(x/g) = 1 + x/g + x^2/(2*g^2) + ... + x^(n)/(g^n * n!) + ... function exp( uint256 x, uint16 g, uint256 gHighestDegree ) internal pure returns (uint256 res) { // calculating: // g**8 + x * g**7 + (x**2 * g**6) / 2 + (x**3 * g**5) / 6 + (x**4 * g**4) / 24 + (x**5 * g**3) / 120 + (x**6 * g^2) / 720 + x**7 * g / 5040 + x**8 / 40320 // x**8 < 152 bits (19*8) and g**8 < 128 bits (8*16) // so each summand < 152 bits and res < 155 bits uint256 xLowestDegree = x; res = gHighestDegree; // g**8 gHighestDegree /= g; // g**7 res += xLowestDegree * gHighestDegree; gHighestDegree /= g; // g**6 xLowestDegree *= x; // x**2 res += (xLowestDegree * gHighestDegree) / 2; gHighestDegree /= g; // g**5 xLowestDegree *= x; // x**3 res += (xLowestDegree * gHighestDegree) / 6; gHighestDegree /= g; // g**4 xLowestDegree *= x; // x**4 res += (xLowestDegree * gHighestDegree) / 24; gHighestDegree /= g; // g**3 xLowestDegree *= x; // x**5 res += (xLowestDegree * gHighestDegree) / 120; gHighestDegree /= g; // g**2 xLowestDegree *= x; // x**6 res += (xLowestDegree * gHighestDegree) / 720; xLowestDegree *= x; // x**7 res += (xLowestDegree * g) / 5040 + (xLowestDegree * x) / (40320); } }
@cryptoalgebra/core/contracts/libraries/Constants.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; library Constants { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; uint256 internal constant Q128 = 0x100000000000000000000000000000000; // fee value in hundredths of a bip, i.e. 1e-6 uint16 internal constant BASE_FEE = 100; int24 internal constant MAX_TICK_SPACING = 500; // max(uint128) / (MAX_TICK - MIN_TICK) uint128 internal constant MAX_LIQUIDITY_PER_TICK = 191757638537527648490752896198553; uint32 internal constant MAX_LIQUIDITY_COOLDOWN = 1 days; uint8 internal constant MAX_COMMUNITY_FEE = 250; uint256 internal constant COMMUNITY_FEE_DENOMINATOR = 1000; }
@cryptoalgebra/core/contracts/libraries/FullMath.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0 = a * b; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { assembly { result := div(prod0, denominator) } return result; } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod // Subtract 256 bit remainder from 512 bit number assembly { let remainder := mulmod(a, b, denominator) prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = -denominator & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the preconditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { if (a == 0 || ((result = a * b) / a == b)) { require(denominator > 0); assembly { result := add(div(result, denominator), gt(mod(result, denominator), 0)) } } else { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } /// @notice Returns ceil(x / y) /// @dev division by 0 has unspecified behavior, and must be checked externally /// @param x The dividend /// @param y The divisor /// @return z The quotient, ceil(x / y) function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := add(div(x, y), gt(mod(x, y), 0)) } } }
@cryptoalgebra/core/contracts/libraries/SafeCast.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library SafeCast { /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { require((z = uint160(y)) == y); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { require((z = int128(y)) == y); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { require(y < 2**255); z = int256(y); } }
@cryptoalgebra/core/contracts/libraries/TickMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return price A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) /// at the given tick function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 price) { // get abs value int24 mask = tick >> (24 - 1); uint256 absTick = uint256((tick ^ mask) - mask); require(absTick <= uint256(MAX_TICK), 'T'); uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; if (tick > 0) ratio = type(uint256).max / ratio; // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtRatio of the output price is always consistent price = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case price < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param price The sqrt ratio for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio function getTickAtSqrtRatio(uint160 price) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(price >= MIN_SQRT_RATIO && price < MAX_SQRT_RATIO, 'R'); uint256 ratio = uint256(price) << 32; uint256 r = ratio; uint256 msb = 0; assembly { let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(5, gt(r, 0xFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(4, gt(r, 0xFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(3, gt(r, 0xFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(2, gt(r, 0xF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(1, gt(r, 0x3)) msb := or(msb, f) r := shr(f, r) } assembly { let f := gt(r, 0x1) msb := or(msb, f) } if (msb >= 128) r = ratio >> (msb - 127); else r = ratio << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= price ? tickHi : tickLow; } }
contracts/interfaces/IPeripheryImmutableState.sol
// 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 /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IPeripheryImmutableState { /// @return Returns the address of the Algebra factory function factory() external view returns (address); /// @return Returns the address of the pool Deployer function poolDeployer() external view returns (address); /// @return Returns the address of WNativeToken function WNativeToken() external view returns (address); }
contracts/interfaces/IQuoter.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Quoter Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. /// Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery interface IQuoter { /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair /// @param amountIn The amount of the first token to swap /// @return amountOut The amount of the last token that would be received function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut, uint16[] memory fees); /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param tokenIn The token being swapped in /// @param tokenOut The token being swapped out /// @param amountIn The desired input amount /// @param limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received function quoteExactInputSingle( address tokenIn, address tokenOut, uint256 amountIn, uint160 limitSqrtPrice ) external returns (uint256 amountOut, uint16 fee); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair. Path must be provided in reverse order /// @param amountOut The amount of the last token to receive /// @return amountIn The amount of first token required to be paid function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn, uint16[] memory fees); /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param tokenIn The token being swapped in /// @param tokenOut The token being swapped out /// @param amountOut The desired output amount /// @param limitSqrtPrice The price limit of the pool that cannot be exceeded by the swap /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` function quoteExactOutputSingle( address tokenIn, address tokenOut, uint256 amountOut, uint160 limitSqrtPrice ) external returns (uint256 amountIn, uint16 fee); }
contracts/libraries/BytesLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later /** * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.5.0 <0.8.0; library BytesLib { function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { require(_length + 31 >= _length, 'slice_overflow'); require(_start + _length >= _start, 'slice_overflow'); require(_bytes.length >= _start + _length, 'slice_outOfBounds'); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_start + 20 >= _start, 'toAddress_overflow'); require(_bytes.length >= _start + 20, 'toAddress_outOfBounds'); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { require(_start + 3 >= _start, 'toUint24_overflow'); require(_bytes.length >= _start + 3, 'toUint24_outOfBounds'); uint24 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x3), _start)) } return tempUint; } }
contracts/libraries/CallbackValidation.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.7.6; import '@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol'; import './PoolAddress.sol'; /// @notice Provides validation for callbacks from Algebra Pools /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library CallbackValidation { /// @notice Returns the address of a valid Algebra Pool /// @param poolDeployer The contract address of the Algebra pool deployer /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @return pool The V3 pool contract address function verifyCallback( address poolDeployer, address tokenA, address tokenB ) internal view returns (IAlgebraPool pool) { return verifyCallback(poolDeployer, PoolAddress.getPoolKey(tokenA, tokenB)); } /// @notice Returns the address of a valid Algebra Pool /// @param poolDeployer The contract address of the Algebra pool deployer /// @param poolKey The identifying key of the V3 pool /// @return pool The V3 pool contract address function verifyCallback(address poolDeployer, PoolAddress.PoolKey memory poolKey) internal view returns (IAlgebraPool pool) { pool = IAlgebraPool(PoolAddress.computeAddress(poolDeployer, poolKey)); require(msg.sender == address(pool)); } }
contracts/libraries/Path.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import './BytesLib.sol'; /// @title Functions for manipulating path data for multihop swaps /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library Path { using BytesLib for bytes; /// @dev The length of the bytes encoded address uint256 private constant ADDR_SIZE = 20; /// @dev The length of the bytes encoded fee uint256 private constant FEE_SIZE = 3; /// @dev The offset of a single token address and pool fee uint256 private constant NEXT_OFFSET = ADDR_SIZE; /// @dev The offset of an encoded pool key uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE; /// @dev The minimum length of an encoding that contains 2 or more pools uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET; /// @notice Returns true iff the path contains two or more pools /// @param path The encoded swap path /// @return True if path contains two or more pools, otherwise false function hasMultiplePools(bytes memory path) internal pure returns (bool) { return path.length >= MULTIPLE_POOLS_MIN_LENGTH; } /// @notice Returns the number of pools in the path /// @param path The encoded swap path /// @return The number of pools in the path function numPools(bytes memory path) internal pure returns (uint256) { // Ignore the first token address. From then on every fee and token offset indicates a pool. return ((path.length - ADDR_SIZE) / NEXT_OFFSET); } /// @notice Decodes the first pool in path /// @param path The bytes encoded swap path /// @return tokenA The first token of the given pool /// @return tokenB The second token of the given pool function decodeFirstPool(bytes memory path) internal pure returns (address tokenA, address tokenB) { tokenA = path.toAddress(0); tokenB = path.toAddress(NEXT_OFFSET); } /// @notice Gets the segment corresponding to the first pool in the path /// @param path The bytes encoded swap path /// @return The segment containing all data necessary to target the first pool in the path function getFirstPool(bytes memory path) internal pure returns (bytes memory) { return path.slice(0, POP_OFFSET); } /// @notice Skips a token + fee element from the buffer and returns the remainder /// @param path The swap path /// @return The remaining token + fee elements in the path function skipToken(bytes memory path) internal pure returns (bytes memory) { return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET); } }
contracts/libraries/PoolAddress.sol
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Provides functions for deriving a pool address from the factory, tokens, and the fee /// @dev Credit to Uniswap Labs under GPL-2.0-or-later license: /// https://github.com/Uniswap/v3-periphery library PoolAddress { bytes32 internal constant POOL_INIT_CODE_HASH = 0x6c1bebd370ba84753516bc1393c0d0a6c645856da55f5393ac8ab3d6dbc861d3; /// @notice The identifying key of the pool struct PoolKey { address token0; address token1; } /// @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 /// @return Poolkey The pool details with ordered token0 and token1 assignments function getPoolKey(address tokenA, address tokenB) internal pure returns (PoolKey memory) { if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); return PoolKey({token0: tokenA, token1: tokenB}); } /// @notice Deterministically computes the pool address given the factory and PoolKey /// @param factory The Algebra factory contract address /// @param key The PoolKey /// @return pool The contract address of the V3 pool function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) { require(key.token0 < key.token1); pool = address( uint256( keccak256( abi.encodePacked( hex'ff', factory, keccak256(abi.encode(key.token0, key.token1)), POOL_INIT_CODE_HASH ) ) ) ); } }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":1000000,"enabled":true},"metadata":{"bytecodeHash":"none"},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_WNativeToken","internalType":"address"},{"type":"address","name":"_poolDeployer","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WNativeToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[],"name":"algebraSwapCallback","inputs":[{"type":"int256","name":"amount0Delta","internalType":"int256"},{"type":"int256","name":"amount1Delta","internalType":"int256"},{"type":"bytes","name":"path","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"poolDeployer","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint16[]","name":"fees","internalType":"uint16[]"}],"name":"quoteExactInput","inputs":[{"type":"bytes","name":"path","internalType":"bytes"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint16","name":"fee","internalType":"uint16"}],"name":"quoteExactInputSingle","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint160","name":"limitSqrtPrice","internalType":"uint160"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint16[]","name":"fees","internalType":"uint16[]"}],"name":"quoteExactOutput","inputs":[{"type":"bytes","name":"path","internalType":"bytes"},{"type":"uint256","name":"amountOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint16","name":"fee","internalType":"uint16"}],"name":"quoteExactOutputSingle","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint160","name":"limitSqrtPrice","internalType":"uint160"}]}]
Contract Creation Code
0x60e06040523480156200001157600080fd5b50604051620014f9380380620014f9833981016040819052620000349162000078565b6001600160601b0319606093841b811660805290831b811660a052911b1660c052620000c1565b80516001600160a01b03811681146200007357600080fd5b919050565b6000806000606084860312156200008d578283fd5b62000098846200005b565b9250620000a8602085016200005b565b9150620000b8604085016200005b565b90509250925092565b60805160601c60a05160601c60c05160601c6113f862000101600039806105b4525080610165528061059052806108a952508061078552506113f86000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638af3ac851161005b5780638af3ac85146101025780639e73c81d1461010a578063c45a01551461011d578063cdca17531461012557610088565b80632c8958f61461008d5780632d9ebd1d146100a25780632f80bb1d146100cc5780633119049a146100ed575b600080fd5b6100a061009b366004610ff9565b610138565b005b6100b56100b0366004610f41565b610323565b6040516100c3929190611320565b60405180910390f35b6100df6100da366004610f93565b6104b9565b6040516100c39291906112cf565b6100f561058e565b6040516100c39190611212565b6100f56105b2565b6100b5610118366004610f41565b6105d6565b6100f5610783565b6100df610133366004610f93565b6107a7565b60008313806101475750600082135b61015057600080fd5b60008061015c83610864565b9150915061018b7f00000000000000000000000000000000000000000000000000000000000000008383610885565b5060008060008088136101d1578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16108789600003610206565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161088886000035b925092509250600061021886866108a2565b905060008060008373ffffffffffffffffffffffffffffffffffffffff1663e76c01e46040518163ffffffff1660e01b81526004016101006040518083038186803b15801561026657600080fd5b505afa15801561027a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029e91906110ba565b505050509350935050508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16106102e157806102e3565b815b925086156102fc57604051858152836020820152604081fd5b6000541561031257600054851461031257600080fd5b604051868152836020820152604081fd5b60008073ffffffffffffffffffffffffffffffffffffffff8086169087161061034c87876108a2565b73ffffffffffffffffffffffffffffffffffffffff1663128acb083083610372896108e0565b73ffffffffffffffffffffffffffffffffffffffff89161561039457886103ba565b856103b35773fffd8963efd1fc6a506488495d951d5263988d256103ba565b6401000276a45b8c8c6040516020016103cd9291906111d8565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016103fc959493929190611233565b6040805180830381600087803b15801561041557600080fd5b505af1925050508015610463575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261046091810190610fd6565b60015b6104ac573d808015610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b506104a081610912565b90945092506104af9050565b50505b5094509492505050565b600060606104c6846109cd565b67ffffffffffffffff811180156104dc57600080fd5b50604051908082528060200260200182016040528015610506578160200160208202803683370190505b50905060005b6000610517866109e5565b905060008061052588610864565b9150915061053681838960006105d6565b86868151811061054257fe5b602002602001018161ffff1661ffff168152508198505050821561057057610569886109ed565b975061057c565b86955050505050610587565b50505060010161050c565b9250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008073ffffffffffffffffffffffffffffffffffffffff808616878216109084166106025760008590555b61060c87876108a2565b73ffffffffffffffffffffffffffffffffffffffff1663128acb083083610632896108e0565b60000373ffffffffffffffffffffffffffffffffffffffff891615610657578861067d565b856106765773fffd8963efd1fc6a506488495d951d5263988d2561067d565b6401000276a45b8b8d6040516020016106909291906111d8565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106bf959493929190611233565b6040805180830381600087803b1580156106d857600080fd5b505af1925050508015610726575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261072391810190610fd6565b60015b6104ac573d808015610754576040519150601f19603f3d011682016040523d82523d6000602084013e610759565b606091505b5073ffffffffffffffffffffffffffffffffffffffff851661077a57600080555b6104a081610912565b7f000000000000000000000000000000000000000000000000000000000000000081565b600060606107b4846109cd565b67ffffffffffffffff811180156107ca57600080fd5b506040519080825280602002602001820160405280156107f4578160200160208202803683370190505b50905060005b6000610805866109e5565b905060008061081388610864565b915091506108248282896000610323565b86868151811061083057fe5b602002602001018161ffff1661ffff168152508198505050821561057057610857886109ed565b97505050506001016107fa565b6000806108718382610a08565b915061087e836014610a08565b9050915091565b600061089a846108958585610b08565b610b77565b949350505050565b60006108d77f00000000000000000000000000000000000000000000000000000000000000006108d28585610b08565b610ba7565b90505b92915050565b60007f8000000000000000000000000000000000000000000000000000000000000000821061090e57600080fd5b5090565b60008082516040146109b057604483511015610963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095a90611298565b60405180910390fd5b6004830192508280602001905181019061097d9190611047565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095a9190611285565b828060200190518101906109c49190611163565b91509150915091565b6000601480835103816109dc57fe5b0490505b919050565b51603c111590565b60606108da60148084510384610ccf9092919063ffffffff16565b600081826014011015610a7c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610aef57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b610b10610eb6565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161115610b48579091905b506040805180820190915273ffffffffffffffffffffffffffffffffffffffff92831681529116602082015290565b6000610b838383610ba7565b90503373ffffffffffffffffffffffffffffffffffffffff8216146108da57600080fd5b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff1610610be957600080fd5b5080516020918201516040805173ffffffffffffffffffffffffffffffffffffffff938416818601529290911682820152805180830382018152606080840183528151918501919091207fff00000000000000000000000000000000000000000000000000000000000000608085015294901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608183015260958201939093527f6c1bebd370ba84753516bc1393c0d0a6c645856da55f5393ac8ab3d6dbc861d360b5808301919091528351808303909101815260d5909101909252815191012090565b60608182601f011015610d4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610db457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b81830184511015610e2657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b606082158015610e455760405191506000825260208201604052610ead565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610e7e578051835260209283019201610e66565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015290565b600082601f830112610edd578081fd5b8135610ef0610eeb82611356565b611332565b818152846020838601011115610f04578283fd5b816020850160208301379081016020019190915292915050565b805161ffff811681146109e057600080fd5b805160ff811681146109e057600080fd5b60008060008060808587031215610f56578384fd5b8435610f61816113c6565b93506020850135610f71816113c6565b9250604085013591506060850135610f88816113c6565b939692955090935050565b60008060408385031215610fa5578182fd5b823567ffffffffffffffff811115610fbb578283fd5b610fc785828601610ecd565b95602094909401359450505050565b60008060408385031215610fe8578182fd5b505080516020909101519092909150565b60008060006060848603121561100d578283fd5b8335925060208401359150604084013567ffffffffffffffff811115611031578182fd5b61103d86828701610ecd565b9150509250925092565b600060208284031215611058578081fd5b815167ffffffffffffffff81111561106e578182fd5b8201601f8101841361107e578182fd5b805161108c610eeb82611356565b8181528560208385010111156110a0578384fd5b6110b1826020830160208601611396565b95945050505050565b600080600080600080600080610100898b0312156110d6578384fd5b88516110e1816113c6565b8098505060208901518060020b81146110f8578485fd5b965061110660408a01610f1e565b955061111460608a01610f1e565b945061112260808a01610f1e565b935061113060a08a01610f30565b925061113e60c08a01610f30565b915060e08901518015158114611152578182fd5b809150509295985092959890939650565b60008060408385031215611175578182fd5b8251915061118560208401610f1e565b90509250929050565b600081518084526111a6816020860160208601611396565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606093841b811682529190921b16601482015260280190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261127a60a083018461118e565b979650505050505050565b6000602082526108d7602083018461118e565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b60006040820184835260206040818501528185518084526060860191508287019350845b8181101561131357845161ffff16835293830193918301916001016112f3565b5090979650505050505050565b91825261ffff16602082015260400190565b60405181810167ffffffffffffffff8111828210171561134e57fe5b604052919050565b600067ffffffffffffffff82111561136a57fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110156113b1578181015183820152602001611399565b838111156113c0576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113e857600080fd5b5056fea164736f6c6343000706000a000000000000000000000000d8676fbdfa5b56bb2298d452c9768f51e80e34ae0000000000000000000000003fb787101dc6be47cfe18aeee15404dcc842e6af0000000000000000000000005822a45b05d08028baa3d19626870076d26bc460
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638af3ac851161005b5780638af3ac85146101025780639e73c81d1461010a578063c45a01551461011d578063cdca17531461012557610088565b80632c8958f61461008d5780632d9ebd1d146100a25780632f80bb1d146100cc5780633119049a146100ed575b600080fd5b6100a061009b366004610ff9565b610138565b005b6100b56100b0366004610f41565b610323565b6040516100c3929190611320565b60405180910390f35b6100df6100da366004610f93565b6104b9565b6040516100c39291906112cf565b6100f561058e565b6040516100c39190611212565b6100f56105b2565b6100b5610118366004610f41565b6105d6565b6100f5610783565b6100df610133366004610f93565b6107a7565b60008313806101475750600082135b61015057600080fd5b60008061015c83610864565b9150915061018b7f0000000000000000000000005822a45b05d08028baa3d19626870076d26bc4608383610885565b5060008060008088136101d1578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16108789600003610206565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161088886000035b925092509250600061021886866108a2565b905060008060008373ffffffffffffffffffffffffffffffffffffffff1663e76c01e46040518163ffffffff1660e01b81526004016101006040518083038186803b15801561026657600080fd5b505afa15801561027a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029e91906110ba565b505050509350935050508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16106102e157806102e3565b815b925086156102fc57604051858152836020820152604081fd5b6000541561031257600054851461031257600080fd5b604051868152836020820152604081fd5b60008073ffffffffffffffffffffffffffffffffffffffff8086169087161061034c87876108a2565b73ffffffffffffffffffffffffffffffffffffffff1663128acb083083610372896108e0565b73ffffffffffffffffffffffffffffffffffffffff89161561039457886103ba565b856103b35773fffd8963efd1fc6a506488495d951d5263988d256103ba565b6401000276a45b8c8c6040516020016103cd9291906111d8565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016103fc959493929190611233565b6040805180830381600087803b15801561041557600080fd5b505af1925050508015610463575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261046091810190610fd6565b60015b6104ac573d808015610491576040519150601f19603f3d011682016040523d82523d6000602084013e610496565b606091505b506104a081610912565b90945092506104af9050565b50505b5094509492505050565b600060606104c6846109cd565b67ffffffffffffffff811180156104dc57600080fd5b50604051908082528060200260200182016040528015610506578160200160208202803683370190505b50905060005b6000610517866109e5565b905060008061052588610864565b9150915061053681838960006105d6565b86868151811061054257fe5b602002602001018161ffff1661ffff168152508198505050821561057057610569886109ed565b975061057c565b86955050505050610587565b50505060010161050c565b9250929050565b7f0000000000000000000000005822a45b05d08028baa3d19626870076d26bc46081565b7f0000000000000000000000003fb787101dc6be47cfe18aeee15404dcc842e6af81565b60008073ffffffffffffffffffffffffffffffffffffffff808616878216109084166106025760008590555b61060c87876108a2565b73ffffffffffffffffffffffffffffffffffffffff1663128acb083083610632896108e0565b60000373ffffffffffffffffffffffffffffffffffffffff891615610657578861067d565b856106765773fffd8963efd1fc6a506488495d951d5263988d2561067d565b6401000276a45b8b8d6040516020016106909291906111d8565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106bf959493929190611233565b6040805180830381600087803b1580156106d857600080fd5b505af1925050508015610726575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261072391810190610fd6565b60015b6104ac573d808015610754576040519150601f19603f3d011682016040523d82523d6000602084013e610759565b606091505b5073ffffffffffffffffffffffffffffffffffffffff851661077a57600080555b6104a081610912565b7f000000000000000000000000d8676fbdfa5b56bb2298d452c9768f51e80e34ae81565b600060606107b4846109cd565b67ffffffffffffffff811180156107ca57600080fd5b506040519080825280602002602001820160405280156107f4578160200160208202803683370190505b50905060005b6000610805866109e5565b905060008061081388610864565b915091506108248282896000610323565b86868151811061083057fe5b602002602001018161ffff1661ffff168152508198505050821561057057610857886109ed565b97505050506001016107fa565b6000806108718382610a08565b915061087e836014610a08565b9050915091565b600061089a846108958585610b08565b610b77565b949350505050565b60006108d77f0000000000000000000000005822a45b05d08028baa3d19626870076d26bc4606108d28585610b08565b610ba7565b90505b92915050565b60007f8000000000000000000000000000000000000000000000000000000000000000821061090e57600080fd5b5090565b60008082516040146109b057604483511015610963576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095a90611298565b60405180910390fd5b6004830192508280602001905181019061097d9190611047565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095a9190611285565b828060200190518101906109c49190611163565b91509150915091565b6000601480835103816109dc57fe5b0490505b919050565b51603c111590565b60606108da60148084510384610ccf9092919063ffffffff16565b600081826014011015610a7c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610aef57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b610b10610eb6565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161115610b48579091905b506040805180820190915273ffffffffffffffffffffffffffffffffffffffff92831681529116602082015290565b6000610b838383610ba7565b90503373ffffffffffffffffffffffffffffffffffffffff8216146108da57600080fd5b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff1610610be957600080fd5b5080516020918201516040805173ffffffffffffffffffffffffffffffffffffffff938416818601529290911682820152805180830382018152606080840183528151918501919091207fff00000000000000000000000000000000000000000000000000000000000000608085015294901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608183015260958201939093527f6c1bebd370ba84753516bc1393c0d0a6c645856da55f5393ac8ab3d6dbc861d360b5808301919091528351808303909101815260d5909101909252815191012090565b60608182601f011015610d4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610db457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b81830184511015610e2657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b606082158015610e455760405191506000825260208201604052610ead565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610e7e578051835260209283019201610e66565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015290565b600082601f830112610edd578081fd5b8135610ef0610eeb82611356565b611332565b818152846020838601011115610f04578283fd5b816020850160208301379081016020019190915292915050565b805161ffff811681146109e057600080fd5b805160ff811681146109e057600080fd5b60008060008060808587031215610f56578384fd5b8435610f61816113c6565b93506020850135610f71816113c6565b9250604085013591506060850135610f88816113c6565b939692955090935050565b60008060408385031215610fa5578182fd5b823567ffffffffffffffff811115610fbb578283fd5b610fc785828601610ecd565b95602094909401359450505050565b60008060408385031215610fe8578182fd5b505080516020909101519092909150565b60008060006060848603121561100d578283fd5b8335925060208401359150604084013567ffffffffffffffff811115611031578182fd5b61103d86828701610ecd565b9150509250925092565b600060208284031215611058578081fd5b815167ffffffffffffffff81111561106e578182fd5b8201601f8101841361107e578182fd5b805161108c610eeb82611356565b8181528560208385010111156110a0578384fd5b6110b1826020830160208601611396565b95945050505050565b600080600080600080600080610100898b0312156110d6578384fd5b88516110e1816113c6565b8098505060208901518060020b81146110f8578485fd5b965061110660408a01610f1e565b955061111460608a01610f1e565b945061112260808a01610f1e565b935061113060a08a01610f30565b925061113e60c08a01610f30565b915060e08901518015158114611152578182fd5b809150509295985092959890939650565b60008060408385031215611175578182fd5b8251915061118560208401610f1e565b90509250929050565b600081518084526111a6816020860160208601611396565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606093841b811682529190921b16601482015260280190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261127a60a083018461118e565b979650505050505050565b6000602082526108d7602083018461118e565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b60006040820184835260206040818501528185518084526060860191508287019350845b8181101561131357845161ffff16835293830193918301916001016112f3565b5090979650505050505050565b91825261ffff16602082015260400190565b60405181810167ffffffffffffffff8111828210171561134e57fe5b604052919050565b600067ffffffffffffffff82111561136a57fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110156113b1578181015183820152602001611399565b838111156113c0576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113e857600080fd5b5056fea164736f6c6343000706000a