My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xae87f24a452914309f58d8e8e29a4257223a59d0db97224d9439a426f4a27aef | 0x60e06040 | 8393014 | 19 days 3 hrs ago | 0xf60f3a45c7d4476019262fc1ff6756fc15042f13 | IN | Create: Router | 0 CRO | 12.6943776 |
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Router
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; pragma abicoder v2; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {TickMath} from '../libraries/TickMath.sol'; import {SafeCast} from '../libraries/SafeCast.sol'; import {PathHelper} from './libraries/PathHelper.sol'; import {PoolAddress} from './libraries/PoolAddress.sol'; import {IPool} from '../interfaces/IPool.sol'; import {IFactory} from '../interfaces/IFactory.sol'; import {IRouter} from '../interfaces/periphery/IRouter.sol'; import {IWETH} from '../interfaces/IWETH.sol'; import {DeadlineValidation} from './base/DeadlineValidation.sol'; import {Multicall} from './base/Multicall.sol'; import {RouterTokenHelperWithFee} from './base/RouterTokenHelperWithFee.sol'; /// @title KyberSwap V2 Swap Router contract Router is IRouter, RouterTokenHelperWithFee, Multicall, DeadlineValidation { using PathHelper for bytes; using SafeCast for uint256; /// @dev Use as the placeholder value for amountInCached uint256 private constant DEFAULT_AMOUNT_IN_CACHED = type(uint256).max; /// @dev Use to cache the computed amount in for an exact output swap. uint256 private amountInCached = DEFAULT_AMOUNT_IN_CACHED; constructor(address _factory, address _WETH) RouterTokenHelperWithFee(_factory, _WETH) {} struct SwapCallbackData { bytes path; address source; } function swapCallback( int256 deltaQty0, int256 deltaQty1, bytes calldata data ) external override { require(deltaQty0 > 0 || deltaQty1 > 0, 'Router: invalid delta qties'); SwapCallbackData memory swapData = abi.decode(data, (SwapCallbackData)); (address tokenIn, address tokenOut, uint24 fee) = swapData.path.decodeFirstPool(); require( msg.sender == address(_getPool(tokenIn, tokenOut, fee)), 'Router: invalid callback sender' ); (bool isExactInput, uint256 amountToTransfer) = deltaQty0 > 0 ? (tokenIn < tokenOut, uint256(deltaQty0)) : (tokenOut < tokenIn, uint256(deltaQty1)); if (isExactInput) { // transfer token from source to the pool which is the msg.sender // wrap eth -> weth and transfer if needed _transferTokens(tokenIn, swapData.source, msg.sender, amountToTransfer); } else { if (swapData.path.hasMultiplePools()) { swapData.path = swapData.path.skipToken(); _swapExactOutputInternal(amountToTransfer, msg.sender, 0, swapData); } else { amountInCached = amountToTransfer; // transfer tokenOut to the pool (it's the original tokenIn) // wrap eth -> weth and transfer if user uses passes eth with the swap _transferTokens(tokenOut, swapData.source, msg.sender, amountToTransfer); } } } function swapExactInputSingle(ExactInputSingleParams calldata params) external payable override onlyNotExpired(params.deadline) returns (uint256 amountOut) { amountOut = _swapExactInputInternal( params.amountIn, params.recipient, params.limitSqrtP, SwapCallbackData({ path: abi.encodePacked(params.tokenIn, params.fee, params.tokenOut), source: msg.sender }) ); require(amountOut >= params.minAmountOut, 'Router: insufficient amountOut'); } function swapExactInput(ExactInputParams memory params) external payable override onlyNotExpired(params.deadline) returns (uint256 amountOut) { address source = msg.sender; // msg.sender is the source of tokenIn for the first swap while (true) { bool hasMultiplePools = params.path.hasMultiplePools(); params.amountIn = _swapExactInputInternal( params.amountIn, hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies 0, SwapCallbackData({path: params.path.getFirstPool(), source: source}) ); if (hasMultiplePools) { source = address(this); params.path = params.path.skipToken(); } else { amountOut = params.amountIn; break; } } require(amountOut >= params.minAmountOut, 'Router: insufficient amountOut'); } function swapExactOutputSingle(ExactOutputSingleParams calldata params) external payable override onlyNotExpired(params.deadline) returns (uint256 amountIn) { amountIn = _swapExactOutputInternal( params.amountOut, params.recipient, params.limitSqrtP, SwapCallbackData({ path: abi.encodePacked(params.tokenOut, params.fee, params.tokenIn), source: msg.sender }) ); require(amountIn <= params.maxAmountIn, 'Router: amountIn is too high'); // has to be reset even though we don't use it in the single hop case amountInCached = DEFAULT_AMOUNT_IN_CACHED; } function swapExactOutput(ExactOutputParams calldata params) external payable override onlyNotExpired(params.deadline) returns (uint256 amountIn) { _swapExactOutputInternal( params.amountOut, params.recipient, 0, SwapCallbackData({path: params.path, source: msg.sender}) ); amountIn = amountInCached; require(amountIn <= params.maxAmountIn, 'Router: amountIn is too high'); amountInCached = DEFAULT_AMOUNT_IN_CACHED; } /// @dev Performs a single exact input swap function _swapExactInputInternal( uint256 amountIn, address recipient, uint160 limitSqrtP, SwapCallbackData memory data ) private returns (uint256 amountOut) { // allow swapping to the router address with address 0 if (recipient == address(0)) recipient = address(this); (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool(); bool isFromToken0 = tokenIn < tokenOut; (int256 amount0, int256 amount1) = _getPool(tokenIn, tokenOut, fee).swap( recipient, amountIn.toInt256(), isFromToken0, limitSqrtP == 0 ? (isFromToken0 ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1) : limitSqrtP, abi.encode(data) ); return uint256(-(isFromToken0 ? amount1 : amount0)); } /// @dev Perform a swap exact amount out using callback function _swapExactOutputInternal( uint256 amountOut, address recipient, uint160 limitSqrtP, SwapCallbackData memory data ) private returns (uint256 amountIn) { // consider address 0 as the router address if (recipient == address(0)) recipient = address(this); (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool(); bool isFromToken0 = tokenOut < tokenIn; (int256 amount0Delta, int256 amount1Delta) = _getPool(tokenIn, tokenOut, fee).swap( recipient, -amountOut.toInt256(), isFromToken0, limitSqrtP == 0 ? (isFromToken0 ? TickMath.MAX_SQRT_RATIO - 1 : TickMath.MIN_SQRT_RATIO + 1) : limitSqrtP, abi.encode(data) ); uint256 receivedAmountOut; (amountIn, receivedAmountOut) = isFromToken0 ? (uint256(amount1Delta), uint256(-amount0Delta)) : (uint256(amount0Delta), uint256(-amount1Delta)); // if no price limit has been specified, receivedAmountOut should be equals to amountOut assert(limitSqrtP != 0 || receivedAmountOut == amountOut); } /// @dev Returns the pool address for the requested token pair swap fee /// Because the function calculates it instead of fetching the address from the factory, /// the returned pool address may not be in existence yet function _getPool( address tokenA, address tokenB, uint24 fee ) private view returns (IPool) { return IPool(PoolAddress.computeAddress(factory, tokenA, tokenB, fee, poolInitHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtP 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 sqrtP) { unchecked { uint256 absTick = uint256(tick < 0 ? -int256(tick) : int256(tick)); require(absTick <= uint256(int256(MAX_TICK)), 'T'); // do bitwise comparison, if i-th bit is turned on, // multiply ratio by hardcoded values of sqrt(1.0001^-(2^i)) * 2^128 // where 0 <= i <= 19 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; // take reciprocal for positive tick values 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 sqrtP = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtP < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtP 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 sqrtP) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(sqrtP >= MIN_SQRT_RATIO && sqrtP < MAX_SQRT_RATIO, 'R'); uint256 ratio = uint256(sqrtP) << 32; uint256 r = ratio; uint256 msb = 0; unchecked { 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) <= sqrtP ? tickHi : tickLow; } } function getMaxNumberTicks(int24 _tickDistance) internal pure returns (uint24 numTicks) { return uint24(TickMath.MAX_TICK / _tickDistance) * 2; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to uint32, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint32 function toUint32(uint256 y) internal pure returns (uint32 z) { require((z = uint32(y)) == y); } /// @notice Cast a uint128 to a int128, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt128(uint128 y) internal pure returns (int128 z) { require(y < 2**127); z = int128(y); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y the uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint128(uint256 y) internal pure returns (uint128 z) { require((z = uint128(y)) == y); } /// @notice Cast a int128 to a uint128 and reverses the sign. /// @param y The int128 to be casted /// @return z = -y, now type uint128 function revToUint128(int128 y) internal pure returns (uint128 z) { unchecked { return type(uint128).max - uint128(y) + 1; } } /// @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 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); } /// @notice Cast a uint256 to a int256 and reverses the sign, revert on overflow /// @param y The uint256 to be casted /// @return z = -y, now type int256 function revToInt256(uint256 y) internal pure returns (int256 z) { require(y < 2**255); z = -int256(y); } /// @notice Cast a int256 to a uint256 and reverses the sign. /// @param y The int256 to be casted /// @return z = -y, now type uint256 function revToUint256(int256 y) internal pure returns (uint256 z) { unchecked { return type(uint256).max - uint256(y) + 1; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import './BytesLib.sol'; /// @title Functions for manipulating path data for multihop swaps library PathHelper { 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 TOKEN_AND_POOL_OFFSET = ADDR_SIZE + FEE_SIZE; /// @dev The offset of an encoded pool data uint256 private constant POOL_DATA_OFFSET = TOKEN_AND_POOL_OFFSET + ADDR_SIZE; /// @dev The minimum length of an encoding that contains 2 or more pools uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POOL_DATA_OFFSET + TOKEN_AND_POOL_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) / TOKEN_AND_POOL_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 /// @return fee The fee level of the pool function decodeFirstPool(bytes memory path) internal pure returns ( address tokenA, address tokenB, uint24 fee ) { tokenA = path.toAddress(0); fee = path.toUint24(ADDR_SIZE); tokenB = path.toAddress(TOKEN_AND_POOL_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, POOL_DATA_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(TOKEN_AND_POOL_OFFSET, path.length - TOKEN_AND_POOL_OFFSET); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; /// @title Provides a function for deriving a pool address from the factory, tokens, and swap fee library PoolAddress { /// @notice Deterministically computes the pool address from the given data /// @param factory the factory address /// @param token0 One of the tokens constituting the token pair, regardless of order /// @param token1 The other token constituting the token pair, regardless of order /// @param swapFee Fee to be collected upon every swap in the pool, in fee units /// @param poolInitHash The keccak256 hash of the Pool creation code /// @return pool the pool address function computeAddress( address factory, address token0, address token1, uint24 swapFee, bytes32 poolInitHash ) internal pure returns (address pool) { (token0, token1) = token0 < token1 ? (token0, token1) : (token1, token0); bytes32 hashed = keccak256( abi.encodePacked( hex'ff', factory, keccak256(abi.encode(token0, token1, swapFee)), poolInitHash ) ); pool = address(uint160(uint256(hashed))); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IPoolActions} from './pool/IPoolActions.sol'; import {IPoolEvents} from './pool/IPoolEvents.sol'; import {IPoolStorage} from './pool/IPoolStorage.sol'; interface IPool is IPoolActions, IPoolEvents, IPoolStorage {}
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @title KyberSwap v2 factory /// @notice Deploys KyberSwap v2 pools and manages control over government fees interface IFactory { /// @notice Emitted when a pool is created /// @param token0 First pool token by address sort order /// @param token1 Second pool token by address sort order /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @param tickDistance Minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint24 indexed swapFeeUnits, int24 tickDistance, address pool ); /// @notice Emitted when a new fee is enabled for pool creation via the factory /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @param tickDistance Minimum number of ticks between initialized ticks for pools created with the given fee event SwapFeeEnabled(uint24 indexed swapFeeUnits, int24 indexed tickDistance); /// @notice Emitted when vesting period changes /// @param vestingPeriod The maximum time duration for which LP fees /// are proportionally burnt upon LP removals event VestingPeriodUpdated(uint32 vestingPeriod); /// @notice Emitted when configMaster changes /// @param oldConfigMaster configMaster before the update /// @param newConfigMaster configMaster after the update event ConfigMasterUpdated(address oldConfigMaster, address newConfigMaster); /// @notice Emitted when fee configuration changes /// @param feeTo Recipient of government fees /// @param governmentFeeUnits Fee amount, in fee units, /// to be collected out of the fee charged for a pool swap event FeeConfigurationUpdated(address feeTo, uint24 governmentFeeUnits); /// @notice Emitted when whitelist feature is enabled event WhitelistEnabled(); /// @notice Emitted when whitelist feature is disabled event WhitelistDisabled(); /// @notice Returns the maximum time duration for which LP fees /// are proportionally burnt upon LP removals function vestingPeriod() external view returns (uint32); /// @notice Returns the tick distance for a specified fee. /// @dev Once added, cannot be updated or removed. /// @param swapFeeUnits Swap fee, in fee units. /// @return The tick distance. Returns 0 if fee has not been added. function feeAmountTickDistance(uint24 swapFeeUnits) external view returns (int24); /// @notice Returns the address which can update the fee configuration function configMaster() external view returns (address); /// @notice Returns the keccak256 hash of the Pool creation code /// This is used for pre-computation of pool addresses function poolInitHash() external view returns (bytes32); /// @notice Returns the pool oracle contract for twap function poolOracle() external view returns (address); /// @notice Fetches the recipient of government fees /// and current government fee charged in fee units function feeConfiguration() external view returns (address _feeTo, uint24 _governmentFeeUnits); /// @notice Returns the status of whitelisting feature of NFT managers /// If true, anyone can mint liquidity tokens /// Otherwise, only whitelisted NFT manager(s) are allowed to mint liquidity tokens function whitelistDisabled() external view returns (bool); //// @notice Returns all whitelisted NFT managers /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens function getWhitelistedNFTManagers() external view returns (address[] memory); /// @notice Checks if sender is a whitelisted NFT manager /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens /// @param sender address to be checked /// @return true if sender is a whistelisted NFT manager, false otherwise function isWhitelistedNFTManager(address sender) external view returns (bool); /// @notice Returns the pool address for a given pair of tokens and a swap fee /// @dev Token order does not matter /// @param tokenA Contract address of either token0 or token1 /// @param tokenB Contract address of the other token /// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @return pool The pool address. Returns null address if it does not exist function getPool( address tokenA, address tokenB, uint24 swapFeeUnits ) external view returns (address pool); /// @notice Fetch parameters to be used for pool creation /// @dev Called by the pool constructor to fetch the parameters of the pool /// @return factory The factory address /// @return poolOracle The pool oracle for twap /// @return token0 First pool token by address sort order /// @return token1 Second pool token by address sort order /// @return swapFeeUnits Fee to be collected upon every swap in the pool, in fee units /// @return tickDistance Minimum number of ticks between initialized ticks function parameters() external view returns ( address factory, address poolOracle, address token0, address token1, uint24 swapFeeUnits, int24 tickDistance ); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param swapFeeUnits Desired swap fee for the pool, in fee units /// @dev Token order does not matter. tickDistance is determined from the fee. /// Call will revert under any of these conditions: /// 1) pool already exists /// 2) invalid swap fee /// 3) invalid token arguments /// @return pool The address of the newly created pool function createPool( address tokenA, address tokenB, uint24 swapFeeUnits ) external returns (address pool); /// @notice Enables a fee amount with the given tickDistance /// @dev Fee amounts may never be removed once enabled /// @param swapFeeUnits The fee amount to enable, in fee units /// @param tickDistance The distance between ticks to be enforced for all pools created with the given fee amount function enableSwapFee(uint24 swapFeeUnits, int24 tickDistance) external; /// @notice Updates the address which can update the fee configuration /// @dev Must be called by the current configMaster function updateConfigMaster(address) external; /// @notice Updates the vesting period /// @dev Must be called by the current configMaster function updateVestingPeriod(uint32) external; /// @notice Updates the address receiving government fees and fee quantity /// @dev Only configMaster is able to perform the update /// @param feeTo Address to receive government fees collected from pools /// @param governmentFeeUnits Fee amount, in fee units, /// to be collected out of the fee charged for a pool swap function updateFeeConfiguration(address feeTo, uint24 governmentFeeUnits) external; /// @notice Enables the whitelisting feature /// @dev Only configMaster is able to perform the update function enableWhitelist() external; /// @notice Disables the whitelisting feature /// @dev Only configMaster is able to perform the update function disableWhitelist() external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; pragma abicoder v2; import '../callback/ISwapCallback.sol'; /// @notice Functions for swapping tokens via KyberSwap v2 /// - Support swap with exact input or exact output /// - Support swap with a price limit /// - Support swap within a single pool and between multiple pools interface IRouter is ISwapCallback { /// @dev Params for swapping exact input amount /// @param tokenIn the token to swap /// @param tokenOut the token to receive /// @param fee the pool's fee /// @param recipient address to receive tokenOut /// @param deadline time that the transaction will be expired /// @param amountIn the tokenIn amount to swap /// @param amountOutMinimum the minimum receive amount /// @param limitSqrtP the price limit, if reached, stop swapping struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 minAmountOut; uint160 limitSqrtP; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function swapExactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); /// @dev Params for swapping exact input using multiple pools /// @param path the encoded path to swap from tokenIn to tokenOut /// If the swap is from token0 -> token1 -> token2, then path is encoded as [token0, fee01, token1, fee12, token2] /// @param recipient address to receive tokenOut /// @param deadline time that the transaction will be expired /// @param amountIn the tokenIn amount to swap /// @param amountOutMinimum the minimum receive amount struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 minAmountOut; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function swapExactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); /// @dev Params for swapping exact output amount /// @param tokenIn the token to swap /// @param tokenOut the token to receive /// @param fee the pool's fee /// @param recipient address to receive tokenOut /// @param deadline time that the transaction will be expired /// @param amountOut the tokenOut amount of tokenOut /// @param amountInMaximum the minimum input amount /// @param limitSqrtP the price limit, if reached, stop swapping struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 maxAmountIn; uint160 limitSqrtP; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function swapExactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); /// @dev Params for swapping exact output using multiple pools /// @param path the encoded path to swap from tokenIn to tokenOut /// If the swap is from token0 -> token1 -> token2, then path is encoded as [token2, fee12, token1, fee01, token0] /// @param recipient address to receive tokenOut /// @param deadline time that the transaction will be expired /// @param amountOut the tokenOut amount of tokenOut /// @param amountInMaximum the minimum input amount struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 maxAmountIn; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function swapExactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @title Interface for WETH interface IWETH is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; /// @title Validate if the transaction is still valid abstract contract DeadlineValidation { modifier onlyNotExpired(uint256 deadline) { require(_blockTimestamp() <= deadline, 'Expired'); _; } /// @dev Override this function to test easier with block timestamp function _blockTimestamp() internal view virtual returns (uint256) { return block.timestamp; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; pragma abicoder v2; import {IMulticall} from '../../interfaces/periphery/IMulticall.sol'; /// @title Multicall /// @notice Enables calling multiple methods in a single call to the contract abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) external payable override returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {TokenHelper} from '../libraries/TokenHelper.sol'; import {IRouterTokenHelperWithFee} from '../../interfaces/periphery/IRouterTokenHelperWithFee.sol'; import {IWETH} from '../../interfaces/IWETH.sol'; import {RouterTokenHelper} from './RouterTokenHelper.sol'; abstract contract RouterTokenHelperWithFee is RouterTokenHelper, IRouterTokenHelperWithFee { uint256 constant FEE_UNITS = 100000; constructor(address _factory, address _WETH) RouterTokenHelper(_factory, _WETH) {} function unwrapWethWithFee( uint256 minAmount, address recipient, uint256 feeUnits, address feeRecipient ) public payable override { require(feeUnits > 0 && feeUnits <= 1000, 'High fee'); uint256 balanceWETH = IWETH(WETH).balanceOf(address(this)); require(balanceWETH >= minAmount, 'Insufficient WETH'); if (balanceWETH > 0) { IWETH(WETH).withdraw(balanceWETH); uint256 feeAmount = (balanceWETH * feeUnits) / FEE_UNITS; if (feeAmount > 0) TokenHelper.transferEth(feeRecipient, feeAmount); TokenHelper.transferEth(recipient, balanceWETH - feeAmount); } } function transferAllTokensWithFee( address token, uint256 minAmount, address recipient, uint256 feeUnits, address feeRecipient ) public payable override { require(feeUnits > 0 && feeUnits <= 1000, 'High fee'); uint256 balanceToken = IERC20(token).balanceOf(address(this)); require(balanceToken >= minAmount, 'Insufficient token'); if (balanceToken > 0) { uint256 feeAmount = (balanceToken * feeUnits) / FEE_UNITS; if (feeAmount > 0) TokenHelper.transferToken(IERC20(token), feeAmount, address(this), feeRecipient); TokenHelper.transferToken(IERC20(token), balanceToken - feeAmount, address(this), recipient); } } }
// SPDX-License-Identifier: Unlicense /* * @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.8.9; library BytesLib { function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, '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(_bytes.length >= _start + 20, 'toAddress_outOfBounds'); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, 'toUint16_outOfBounds'); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { require(_bytes.length >= _start + 3, 'toUint24_outOfBounds'); uint24 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x3), _start)) } return tempUint; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolActions { /// @notice Sets the initial price for the pool and seeds reinvestment liquidity /// @dev Assumes the caller has sent the necessary token amounts /// required for initializing reinvestment liquidity prior to calling this function /// @param initialSqrtP the initial sqrt price of the pool /// @param qty0 token0 quantity sent to and locked permanently in the pool /// @param qty1 token1 quantity sent to and locked permanently in the pool function unlockPool(uint160 initialSqrtP) external returns (uint256 qty0, uint256 qty1); /// @notice Adds liquidity for the specified recipient/tickLower/tickUpper position /// @dev Any token0 or token1 owed for the liquidity provision have to be paid for when /// the IMintCallback#mintCallback is called to this method's caller /// The quantity of token0/token1 to be sent depends on /// tickLower, tickUpper, the amount of liquidity, and the current price of the pool. /// Also sends reinvestment tokens (fees) to the recipient for any fees collected /// while the position is in range /// Reinvestment tokens have to be burnt via #burnRTokens in exchange for token0 and token1 /// @param recipient Address for which the added liquidity is credited to /// @param tickLower Recipient position's lower tick /// @param tickUpper Recipient position's upper tick /// @param ticksPrevious The nearest tick that is initialized and <= the lower & upper ticks /// @param qty Liquidity quantity to mint /// @param data Data (if any) to be passed through to the callback /// @return qty0 token0 quantity sent to the pool in exchange for the minted liquidity /// @return qty1 token1 quantity sent to the pool in exchange for the minted liquidity /// @return feeGrowthInside position's updated feeGrowthInside value function mint( address recipient, int24 tickLower, int24 tickUpper, int24[2] calldata ticksPrevious, uint128 qty, bytes calldata data ) external returns ( uint256 qty0, uint256 qty1, uint256 feeGrowthInside ); /// @notice Remove liquidity from the caller /// Also sends reinvestment tokens (fees) to the caller for any fees collected /// while the position is in range /// Reinvestment tokens have to be burnt via #burnRTokens in exchange for token0 and token1 /// @param tickLower Position's lower tick for which to burn liquidity /// @param tickUpper Position's upper tick for which to burn liquidity /// @param qty Liquidity quantity to burn /// @return qty0 token0 quantity sent to the caller /// @return qty1 token1 quantity sent to the caller /// @return feeGrowthInside position's updated feeGrowthInside value function burn( int24 tickLower, int24 tickUpper, uint128 qty ) external returns ( uint256 qty0, uint256 qty1, uint256 feeGrowthInside ); /// @notice Burns reinvestment tokens in exchange to receive the fees collected in token0 and token1 /// @param qty Reinvestment token quantity to burn /// @param isLogicalBurn true if burning rTokens without returning any token0/token1 /// otherwise should transfer token0/token1 to sender /// @return qty0 token0 quantity sent to the caller for burnt reinvestment tokens /// @return qty1 token1 quantity sent to the caller for burnt reinvestment tokens function burnRTokens(uint256 qty, bool isLogicalBurn) external returns (uint256 qty0, uint256 qty1); /// @notice Swap token0 -> token1, or vice versa /// @dev This method's caller receives a callback in the form of ISwapCallback#swapCallback /// @dev swaps will execute up to limitSqrtP or swapQty is fully used /// @param recipient The address to receive the swap output /// @param swapQty The swap quantity, which implicitly configures the swap as exact input (>0), or exact output (<0) /// @param isToken0 Whether the swapQty is specified in token0 (true) or token1 (false) /// @param limitSqrtP the limit of sqrt price after swapping /// could be MAX_SQRT_RATIO-1 when swapping 1 -> 0 and MIN_SQRT_RATIO+1 when swapping 0 -> 1 for no limit swap /// @param data Any data to be passed through to the callback /// @return qty0 Exact token0 qty sent to recipient if < 0. Minimally received quantity if > 0. /// @return qty1 Exact token1 qty sent to recipient if < 0. Minimally received quantity if > 0. function swap( address recipient, int256 swapQty, bool isToken0, uint160 limitSqrtP, bytes calldata data ) external returns (int256 qty0, int256 qty1); /// @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 IFlashCallback#flashCallback /// @dev Fees collected are sent to the feeTo address if it is set in Factory /// @param recipient The address which will receive the token0 and token1 quantities /// @param qty0 token0 quantity to be loaned to the recipient /// @param qty1 token1 quantity to be loaned to the recipient /// @param data Any data to be passed through to the callback function flash( address recipient, uint256 qty0, uint256 qty1, bytes calldata data ) external; /// @notice sync fee of position /// @param tickLower Position's lower tick /// @param tickUpper Position's upper tick function tweakPosZeroLiq(int24 tickLower, int24 tickUpper) external returns(uint256 feeGrowthInsideLast); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolEvents { /// @notice Emitted only once per pool when #initialize is first called /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize /// @param sqrtP The initial price of the pool /// @param tick The initial tick of the pool event Initialize(uint160 sqrtP, int24 tick); /// @notice Emitted when liquidity is minted for a given position /// @dev transfers reinvestment tokens for any collected fees earned by the position /// @param sender address that minted the liquidity /// @param owner address of owner of the position /// @param tickLower position's lower tick /// @param tickUpper position's upper tick /// @param qty liquidity minted to the position range /// @param qty0 token0 quantity needed to mint the liquidity /// @param qty1 token1 quantity needed to mint the liquidity event Mint( address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 qty, uint256 qty0, uint256 qty1 ); /// @notice Emitted when a position's liquidity is removed /// @dev transfers reinvestment tokens for any collected fees earned by the position /// @param owner address of owner of the position /// @param tickLower position's lower tick /// @param tickUpper position's upper tick /// @param qty liquidity removed /// @param qty0 token0 quantity withdrawn from removal of liquidity /// @param qty1 token1 quantity withdrawn from removal of liquidity event Burn( address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 qty, uint256 qty0, uint256 qty1 ); /// @notice Emitted when reinvestment tokens are burnt /// @param owner address which burnt the reinvestment tokens /// @param qty reinvestment token quantity burnt /// @param qty0 token0 quantity sent to owner for burning reinvestment tokens /// @param qty1 token1 quantity sent to owner for burning reinvestment tokens event BurnRTokens(address indexed owner, uint256 qty, uint256 qty0, uint256 qty1); /// @notice Emitted for swaps by the pool between token0 and token1 /// @param sender Address that initiated the swap call, and that received the callback /// @param recipient Address that received the swap output /// @param deltaQty0 Change in pool's token0 balance /// @param deltaQty1 Change in pool's token1 balance /// @param sqrtP Pool's sqrt price after the swap /// @param liquidity Pool's liquidity after the swap /// @param currentTick Log base 1.0001 of pool's price after the swap event Swap( address indexed sender, address indexed recipient, int256 deltaQty0, int256 deltaQty1, uint160 sqrtP, uint128 liquidity, int24 currentTick ); /// @notice Emitted by the pool for any flash loans of token0/token1 /// @param sender The address that initiated the flash loan, and that received the callback /// @param recipient The address that received the flash loan quantities /// @param qty0 token0 quantity loaned to the recipient /// @param qty1 token1 quantity loaned to the recipient /// @param paid0 token0 quantity paid for the flash, which can exceed qty0 + fee /// @param paid1 token1 quantity paid for the flash, which can exceed qty0 + fee event Flash( address indexed sender, address indexed recipient, uint256 qty0, uint256 qty1, uint256 paid0, uint256 paid1 ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {IFactory} from '../IFactory.sol'; import {IPoolOracle} from '../oracle/IPoolOracle.sol'; interface IPoolStorage { /// @notice The contract that deployed the pool, which must adhere to the IFactory interface /// @return The contract address function factory() external view returns (IFactory); /// @notice The oracle contract that stores necessary data for price oracle /// @return The contract address function poolOracle() external view returns (IPoolOracle); /// @notice The first of the two tokens of the pool, sorted by address /// @return The token contract address function token0() external view returns (IERC20); /// @notice The second of the two tokens of the pool, sorted by address /// @return The token contract address function token1() external view returns (IERC20); /// @notice The fee to be charged for a swap in basis points /// @return The swap fee in basis points function swapFeeUnits() external view returns (uint24); /// @notice The pool tick distance /// @dev Ticks can only be initialized and used at multiples of this value /// It remains an int24 to avoid casting even though it is >= 1. /// e.g: a tickDistance of 5 means ticks can be initialized every 5th tick, i.e., ..., -10, -5, 0, 5, 10, ... /// @return The tick distance function tickDistance() external view returns (int24); /// @notice Maximum gross liquidity that an initialized tick can have /// @dev This is to prevent overflow the pool's active base liquidity (uint128) /// 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 maxTickLiquidity() external view returns (uint128); /// @notice Look up information about a specific tick in the pool /// @param tick The tick to look up /// @return liquidityGross total liquidity amount from positions that uses this tick as a lower or upper tick /// liquidityNet how much liquidity changes when the pool tick crosses above the tick /// feeGrowthOutside the fee growth on the other side of the tick relative to the current tick /// secondsPerLiquidityOutside the seconds per unit of liquidity spent on the other side of the tick relative to the current tick function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside, uint128 secondsPerLiquidityOutside ); /// @notice Returns the previous and next initialized ticks of a specific tick /// @dev If specified tick is uninitialized, the returned values are zero. /// @param tick The tick to look up function initializedTicks(int24 tick) external view returns (int24 previous, int24 next); /// @notice Returns the information about a position by the position's key /// @return liquidity the liquidity quantity of the position /// @return feeGrowthInsideLast fee growth inside the tick range as of the last mint / burn action performed function getPositions( address owner, int24 tickLower, int24 tickUpper ) external view returns (uint128 liquidity, uint256 feeGrowthInsideLast); /// @notice Fetches the pool's prices, ticks and lock status /// @return sqrtP sqrt of current price: sqrt(token1/token0) /// @return currentTick pool's current tick /// @return nearestCurrentTick pool's nearest initialized tick that is <= currentTick /// @return locked true if pool is locked, false otherwise function getPoolState() external view returns ( uint160 sqrtP, int24 currentTick, int24 nearestCurrentTick, bool locked ); /// @notice Fetches the pool's liquidity values /// @return baseL pool's base liquidity without reinvest liqudity /// @return reinvestL the liquidity is reinvested into the pool /// @return reinvestLLast last cached value of reinvestL, used for calculating reinvestment token qty function getLiquidityState() external view returns ( uint128 baseL, uint128 reinvestL, uint128 reinvestLLast ); /// @return feeGrowthGlobal All-time fee growth per unit of liquidity of the pool function getFeeGrowthGlobal() external view returns (uint256); /// @return secondsPerLiquidityGlobal All-time seconds per unit of liquidity of the pool /// @return lastUpdateTime The timestamp in which secondsPerLiquidityGlobal was last updated function getSecondsPerLiquidityData() external view returns (uint128 secondsPerLiquidityGlobal, uint32 lastUpdateTime); /// @notice Calculates and returns the active time per unit of liquidity until current block.timestamp /// @param tickLower The lower tick (of a position) /// @param tickUpper The upper tick (of a position) /// @return secondsPerLiquidityInside active time (multiplied by 2^96) /// between the 2 ticks, per unit of liquidity. function getSecondsPerLiquidityInside(int24 tickLower, int24 tickUpper) external view returns (uint128 secondsPerLiquidityInside); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IPoolOracle { /// @notice Owner withdrew funds in the pool oracle in case some funds are stuck there event OwnerWithdrew( address indexed owner, address indexed token, uint256 indexed amount ); /// @notice Emitted by the Pool Oracle for increases to the number of observations that can be stored /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index /// just before a mint/swap/burn. /// @param pool The pool address to update /// @param observationCardinalityNextOld The previous value of the next observation cardinality /// @param observationCardinalityNextNew The updated value of the next observation cardinality event IncreaseObservationCardinalityNext( address pool, uint16 observationCardinalityNextOld, uint16 observationCardinalityNextNew ); /// @notice Initalize observation data for the caller. function initializeOracle(uint32 time) external returns (uint16 cardinality, uint16 cardinalityNext); /// @notice Write a new oracle entry into the array /// and update the observation index and cardinality /// Read the Oralce.write function for more details function writeNewEntry( uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint16 cardinality, uint16 cardinalityNext ) external returns (uint16 indexUpdated, uint16 cardinalityUpdated); /// @notice Write a new oracle entry into the array, take the latest observaion data as inputs /// and update the observation index and cardinality /// Read the Oralce.write function for more details function write( uint32 blockTimestamp, int24 tick, uint128 liquidity ) external returns (uint16 indexUpdated, uint16 cardinalityUpdated); /// @notice Increase the maximum number of price observations that this pool will store /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to /// the input observationCardinalityNext. /// @param pool The pool address to be updated /// @param observationCardinalityNext The desired minimum number of observations for the pool to store function increaseObservationCardinalityNext( address pool, uint16 observationCardinalityNext ) external; /// @notice Returns the accumulator values as of each time seconds ago from the latest block time in the array of `secondsAgos` /// @dev Reverts if `secondsAgos` > oldest observation /// @dev It fetches the latest current tick data from the pool /// Read the Oracle.observe function for more details function observeFromPool( address pool, uint32[] memory secondsAgos ) external view returns (int56[] memory tickCumulatives); /// @notice Returns the accumulator values as the time seconds ago from the latest block time of secondsAgo /// @dev Reverts if `secondsAgo` > oldest observation /// @dev It fetches the latest current tick data from the pool /// Read the Oracle.observeSingle function for more details function observeSingleFromPool( address pool, uint32 secondsAgo ) external view returns (int56 tickCumulative); /// @notice Return the latest pool observation data given the pool address function getPoolObservation(address pool) external view returns (bool initialized, uint16 index, uint16 cardinality, uint16 cardinalityNext); /// @notice Returns data about a specific observation index /// @param pool The pool address of the observations array to fetch /// @param index The element of the observations array to fetch /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time /// ago, rather than at a specific index in the array. /// @return blockTimestamp The timestamp of the observation, /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, /// Returns initialized whether the observation has been initialized and the values are safe to use function getObservationAt(address pool, uint256 index) external view returns ( uint32 blockTimestamp, int56 tickCumulative, bool initialized ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @title Callback for IPool#swap /// @notice Any contract that calls IPool#swap must implement this interface interface ISwapCallback { /// @notice Called to `msg.sender` after swap execution of IPool#swap. /// @dev This function's implementation must pay tokens owed to the pool for the swap. /// The caller of this method must be checked to be a Pool deployed by the canonical Factory. /// deltaQty0 and deltaQty1 can both be 0 if no tokens were swapped. /// @param deltaQty0 The token0 quantity that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send deltaQty0 of token0 to the pool. /// @param deltaQty1 The token1 quantity that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send deltaQty1 of token1 to the pool. /// @param data Data passed through by the caller via the IPool#swap call function swapCallback( int256 deltaQty0, int256 deltaQty1, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; pragma abicoder v2; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract interface IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; /// @title Helper to transfer token or ETH library TokenHelper { using SafeERC20 for IERC20; /// @dev Transfer token from the sender to the receiver /// @notice If the sender is the contract address, should just call transfer token to receiver /// otherwise, tansfer tokens from the sender to the receiver function transferToken( IERC20 token, uint256 amount, address sender, address receiver ) internal { if (sender == address(this)) { token.safeTransfer(receiver, amount); } else { token.safeTransferFrom(sender, receiver, amount); } } /// @dev Transfer ETh to the receiver function transferEth(address receiver, uint256 amount) internal { if (receiver == address(this)) return; (bool success, ) = payable(receiver).call{value: amount}(''); require(success, 'transfer eth failed'); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import './IRouterTokenHelper.sol'; interface IRouterTokenHelperWithFee is IRouterTokenHelper { /// @notice Unwraps the contract's WETH balance and sends it to recipient as ETH, with a percentage between /// 0 (exclusive), and 1 (inclusive) going to feeRecipient /// @dev The minAmount parameter prevents malicious contracts from stealing WETH from users. function unwrapWethWithFee( uint256 minAmount, address recipient, uint256 feeUnits, address feeRecipient ) external payable; /// @notice Transfers the full amount of a token held by this contract to recipient, with a percentage between /// 0 (exclusive) and 1 (inclusive) going to feeRecipient /// @dev The minAmount parameter prevents malicious contracts from stealing the token from users function transferAllTokensWithFee( address token, uint256 minAmount, address recipient, uint256 feeBips, address feeRecipient ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {TokenHelper} from '../libraries/TokenHelper.sol'; import {IRouterTokenHelper} from '../../interfaces/periphery/IRouterTokenHelper.sol'; import {IWETH} from '../../interfaces/IWETH.sol'; import {ImmutablePeripheryStorage} from './ImmutablePeripheryStorage.sol'; abstract contract RouterTokenHelper is IRouterTokenHelper, ImmutablePeripheryStorage { constructor(address _factory, address _WETH) ImmutablePeripheryStorage(_factory, _WETH) {} receive() external payable { require(msg.sender == WETH, 'Not WETH'); } /// @dev Unwrap all ETH balance and send to the recipient function unwrapWeth(uint256 minAmount, address recipient) external payable override { uint256 balanceWETH = IWETH(WETH).balanceOf(address(this)); require(balanceWETH >= minAmount, 'Insufficient WETH'); if (balanceWETH > 0) { IWETH(WETH).withdraw(balanceWETH); TokenHelper.transferEth(recipient, balanceWETH); } } /// @dev Transfer all tokens from the contract to the recipient function transferAllTokens( address token, uint256 minAmount, address recipient ) public payable virtual override { uint256 balanceToken = IERC20(token).balanceOf(address(this)); require(balanceToken >= minAmount, 'Insufficient token'); if (balanceToken > 0) { TokenHelper.transferToken(IERC20(token), balanceToken, address(this), recipient); } } /// @dev Send all ETH balance of this contract to the sender function refundEth() external payable override { if (address(this).balance > 0) TokenHelper.transferEth(msg.sender, address(this).balance); } /// @dev Transfer tokenAmount amount of token from the sender to the recipient function _transferTokens( address token, address sender, address recipient, uint256 tokenAmount ) internal { if (token == WETH && address(this).balance >= tokenAmount) { IWETH(WETH).deposit{value: tokenAmount}(); IWETH(WETH).transfer(recipient, tokenAmount); } else { TokenHelper.transferToken(IERC20(token), tokenAmount, sender, recipient); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; interface IRouterTokenHelper { /// @notice Unwraps the contract's WETH balance and sends it to recipient as ETH. /// @dev The minAmount parameter prevents malicious contracts from stealing WETH from users. /// @param minAmount The minimum amount of WETH to unwrap /// @param recipient The address receiving ETH function unwrapWeth(uint256 minAmount, address recipient) external payable; /// @notice Refunds any ETH balance held by this contract to the `msg.sender` /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps /// that use ether for the input amount function refundEth() external payable; /// @notice Transfers the full amount of a token held by this contract to recipient /// @dev The minAmount parameter prevents malicious contracts from stealing the token from users /// @param token The contract address of the token which will be transferred to `recipient` /// @param minAmount The minimum amount of token required for a transfer /// @param recipient The destination address of the token function transferAllTokens( address token, uint256 minAmount, address recipient ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.9; import {IFactory} from '../../interfaces/IFactory.sol'; /// @title Immutable state /// @notice Immutable state used by periphery contracts abstract contract ImmutablePeripheryStorage { address public immutable factory; address public immutable WETH; bytes32 internal immutable poolInitHash; constructor(address _factory, address _WETH) { factory = _factory; WETH = _WETH; poolInitHash = IFactory(_factory).poolInitHash(); } }
{ "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"refundEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"deltaQty0","type":"int256"},{"internalType":"int256","name":"deltaQty1","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"internalType":"struct IRouter.ExactInputParams","name":"params","type":"tuple"}],"name":"swapExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint160","name":"limitSqrtP","type":"uint160"}],"internalType":"struct IRouter.ExactInputSingleParams","name":"params","type":"tuple"}],"name":"swapExactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"}],"internalType":"struct IRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"swapExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"uint160","name":"limitSqrtP","type":"uint160"}],"internalType":"struct IRouter.ExactOutputSingleParams","name":"params","type":"tuple"}],"name":"swapExactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"transferAllTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeUnits","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"transferAllTokensWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"unwrapWeth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeUnits","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"unwrapWethWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040526000196000553480156200001757600080fd5b506040516200308e3803806200308e8339810160408190526200003a9162000118565b818181818181816001600160a01b03166080816001600160a01b031681525050806001600160a01b031660a0816001600160a01b031681525050816001600160a01b031663d04b86b06040518163ffffffff1660e01b815260040160206040518083038186803b158015620000ae57600080fd5b505afa158015620000c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e9919062000150565b60c052506200016a9650505050505050565b80516001600160a01b03811681146200011357600080fd5b919050565b600080604083850312156200012c57600080fd5b6200013783620000fb565b91506200014760208401620000fb565b90509250929050565b6000602082840312156200016357600080fd5b5051919050565b60805160a05160c051612eb6620001d86000396000611ab401526000818160f30152818161020c01528181610b8101528181610cb1015281816110df0152818161120f01528181611ae401528181611b440152611c0c0152600081816102c40152611a900152612eb66000f3fe6080604052600436106100d65760003560e01c8063ad8e3d5d1161007f578063bfba6b2211610059578063bfba6b221461028c578063c222e83a1461029f578063c45a0155146102b2578063fa483e72146102e657600080fd5b8063ad8e3d5d14610253578063bac37ef714610266578063bf1316c11461027957600080fd5b8063a8c9ed67116100b0578063a8c9ed67146101c7578063ac9650d8146101da578063ad5c4648146101fa57600080fd5b80631b262321146101865780631faa4133146101995780635d946c25146101a157600080fd5b36610181573373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461017f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4e6f74205745544800000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b61017f610194366004612452565b610306565b61017f6104dd565b6101b46101af3660046125f4565b6104ef565b6040519081526020015b60405180910390f35b6101b46101d53660046126ab565b610678565b6101ed6101e83660046126c8565b61085c565b6040516101be91906127b3565b34801561020657600080fd5b5061022e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101be565b6101b4610261366004612833565b6109ce565b61017f61027436600461286e565b610b50565b61017f61028736600461289e565b610d31565b6101b461029a3660046126ab565b610e55565b61017f6102ad3660046128e0565b611036565b3480156102be57600080fd5b5061022e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102f257600080fd5b5061017f61030136600461292a565b6112c8565b60008211801561031857506103e88211155b61037e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f48696768206665650000000000000000000000000000000000000000000000006044820152606401610176565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a082319060240160206040518083038186803b1580156103e657600080fd5b505afa1580156103fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041e91906129aa565b90508481101561048a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e00000000000000000000000000006044820152606401610176565b80156104d5576000620186a06104a085846129f2565b6104aa9190612a2f565b905080156104be576104be878230866114e7565b6104d3876104cc8385612a6a565b30886114e7565b505b505050505050565b47156104ed576104ed334761154d565b565b60008160400151806104fe4290565b1115610566576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45787069726564000000000000000000000000000000000000000000000000006044820152606401610176565b335b60006105778560000151611639565b90506105d0856060015182610590578660200151610592565b305b600060405180604001604052806105ac8b60000151611673565b81526020018773ffffffffffffffffffffffffffffffffffffffff1681525061169f565b606086015280156105f05784513092506105e99061183e565b85526105fd565b8460600151935050610603565b50610568565b8360800151831015610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f526f757465723a20696e73756666696369656e7420616d6f756e744f757400006044820152606401610176565b5050919050565b60006080820135804211156106e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45787069726564000000000000000000000000000000000000000000000000006044820152606401610176565b6107e660a08401356107016080860160608701612a81565b610712610100870160e08801612a81565b604080518082019091528061072a60208a018a612a81565b61073a60608b0160408c01612a9e565b61074a60408c0160208d01612a81565b604051606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116602083015260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166034820152921b166037820152604b0160405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff1681525061169f565b91508260c00135821015610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f526f757465723a20696e73756666696369656e7420616d6f756e744f757400006044820152606401610176565b50919050565b60608167ffffffffffffffff811115610877576108776124b1565b6040519080825280602002602001820160405280156108aa57816020015b60608152602001906001900390816108955790505b50905060005b828110156109c757600080308686858181106108ce576108ce612ac3565b90506020028101906108e09190612af2565b6040516108ee929190612b5e565b600060405180830381855af49150503d8060008114610929576040519150601f19603f3d011682016040523d82523d6000602084013e61092e565b606091505b5091509150816109945760448151101561094757600080fd5b600481019050808060200190518101906109619190612b6e565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101769190612be5565b808484815181106109a7576109a7612ac3565b6020026020010181905250505080806109bf90612bf8565b9150506108b0565b5092915050565b6000604082013580421115610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45787069726564000000000000000000000000000000000000000000000000006044820152606401610176565b610ab26060840135610a576040860160208701612a81565b6040805180820190915260009080610a6f8980612af2565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525033602090910152611867565b5060005491508260800135821115610b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f526f757465723a20616d6f756e74496e20697320746f6f2068696768000000006044820152606401610176565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600055919050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a082319060240160206040518083038186803b158015610bd857600080fd5b505afa158015610bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1091906129aa565b905082811015610c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e73756666696369656e7420574554480000000000000000000000000000006044820152606401610176565b8015610d2c576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b158015610d0a57600080fd5b505af1158015610d1e573d6000803e3d6000fd5b50505050610d2c828261154d565b505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8516906370a082319060240160206040518083038186803b158015610d9957600080fd5b505afa158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd191906129aa565b905082811015610e3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e00000000000000000000000000006044820152606401610176565b8015610e4f57610e4f848230856114e7565b50505050565b6000608082013580421115610ec6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45787069726564000000000000000000000000000000000000000000000000006044820152606401610176565b610fc660a0840135610ede6080860160608701612a81565b610eef610100870160e08801612a81565b6040518060400160405280886020016020810190610f0d9190612a81565b610f1d60608b0160408c01612a9e565b610f2a60208c018c612a81565b604051606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116602083015260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166034820152921b166037820152604b0160405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff16815250611867565b91508260c00135821115610b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f526f757465723a20616d6f756e74496e20697320746f6f2068696768000000006044820152606401610176565b60008211801561104857506103e88211155b6110ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f48696768206665650000000000000000000000000000000000000000000000006044820152606401610176565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a082319060240160206040518083038186803b15801561113657600080fd5b505afa15801561114a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116e91906129aa565b9050848110156111da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e73756666696369656e7420574554480000000000000000000000000000006044820152606401610176565b80156112c1576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b15801561126857600080fd5b505af115801561127c573d6000803e3d6000fd5b505050506000620186a0848361129291906129f2565b61129c9190612a2f565b905080156112ae576112ae838261154d565b6104d5856112bc8385612a6a565b61154d565b5050505050565b60008413806112d75750600083135b61133d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526f757465723a20696e76616c69642064656c746120717469657300000000006044820152606401610176565b600061134b82840184612c31565b9050600080600061135f8460000151611a4d565b925092509250611370838383611a89565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611404576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f526f757465723a20696e76616c69642063616c6c6261636b2073656e646572006044820152606401610176565b60008060008a13611444578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161089611475565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b9150915081156114945761148f8587602001513384611ae2565b6114db565b855161149f90611639565b156114c45785516114af9061183e565b86526114be8133600089611867565b506114db565b806000819055506114db8487602001513384611ae2565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff821630141561152b5761152673ffffffffffffffffffffffffffffffffffffffff85168285611c9e565b610e4f565b610e4f73ffffffffffffffffffffffffffffffffffffffff8516838386611d72565b73ffffffffffffffffffffffffffffffffffffffff821630141561156f575050565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146115c9576040519150601f19603f3d011682016040523d82523d6000602084013e6115ce565b606091505b5050905080610d2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f7472616e7366657220657468206661696c6564000000000000000000000000006044820152606401610176565b600061164760036014612ccb565b6014611654600382612ccb565b61165e9190612ccb565b6116689190612ccb565b825110159050919050565b606061169960006014611687600382612ccb565b6116919190612ccb565b849190611dd0565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff84166116c0573093505b60008060006116d28560000151611a4d565b9194509250905073ffffffffffffffffffffffffffffffffffffffff80831690841610600080611703868686611a89565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6117288e611f4a565b8673ffffffffffffffffffffffffffffffffffffffff8e161561174b578d611784565b876117745761176f600173fffd8963efd1fc6a506488495d951d5263988d26612ce3565b611784565b6117846401000276a36001612d18565b8d6040516020016117959190612d50565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016117c4959493929190612d98565b6040805180830381600087803b1580156117dd57600080fd5b505af11580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118159190612ddf565b91509150826118245781611826565b805b61182f90612e03565b9b9a5050505050505050505050565b606061169961184f60036014612ccb565b61185b60036014612ccb565b84516116919190612a6a565b600073ffffffffffffffffffffffffffffffffffffffff8416611888573093505b600080600061189a8560000151611a4d565b9194509250905073ffffffffffffffffffffffffffffffffffffffff808316908416106000806118cb858786611a89565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6118f08e611f4a565b6118f990612e03565b8673ffffffffffffffffffffffffffffffffffffffff8e161561191c578d611955565b87611936576119316401000276a36001612d18565b611955565b611955600173fffd8963efd1fc6a506488495d951d5263988d26612ce3565b8d6040516020016119669190612d50565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401611995959493929190612d98565b6040805180830381600087803b1580156119ae57600080fd5b505af11580156119c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e69190612ddf565b91509150600083611a0057826119fb83612e03565b611a0a565b81611a0a84612e03565b909850905073ffffffffffffffffffffffffffffffffffffffff8a16151580611a3257508b81145b611a3e57611a3e612e3c565b50505050505050949350505050565b60008080611a5b8482611f7c565b9250611a6884601461200c565b9050611a80611a7960036014612ccb565b8590611f7c565b91509193909250565b6000611ad87f00000000000000000000000000000000000000000000000000000000000000008585857f000000000000000000000000000000000000000000000000000000000000000061208c565b90505b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015611b3d5750804710155b15611c92577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611baa57600080fd5b505af1158015611bbe573d6000803e3d6000fd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb92506044019050602060405180830381600087803b158015611c5457600080fd5b505af1158015611c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8c9190612e6b565b50610e4f565b610e4f848285856114e7565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610d2c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526121d5565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610e4f9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611cf0565b606081611dde81601f612ccb565b1015611e46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610176565b611e508284612ccb565b84511015611eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610176565b606082158015611ed95760405191506000825260208201604052611f41565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611f12578051835260209283019201611efa565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210611f7857600080fd5b5090565b6000611f89826014612ccb565b83511015611ff3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610176565b5001602001516c01000000000000000000000000900490565b6000612019826003612ccb565b83511015612083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610176565b50016003015190565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16106120c85783856120cb565b84845b6040805173ffffffffffffffffffffffffffffffffffffffff808516602083015283169181019190915262ffffff86166060820152919650945060009087906080016040516020818303038152906040528051906020012084604051602001612194939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120979650505050505050565b6000612237826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166122e19092919063ffffffff16565b805190915015610d2c57808060200190518101906122559190612e6b565b610d2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610176565b6060611ad8848460008585843b612354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610176565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161237d9190612e8d565b60006040518083038185875af1925050503d80600081146123ba576040519150601f19603f3d011682016040523d82523d6000602084013e6123bf565b606091505b50915091506123cf8282866123da565b979650505050505050565b606083156123e9575081611adb565b8251156123f95782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101769190612be5565b73ffffffffffffffffffffffffffffffffffffffff8116811461244f57600080fd5b50565b600080600080600060a0868803121561246a57600080fd5b85356124758161242d565b945060208601359350604086013561248c8161242d565b92506060860135915060808601356124a38161242d565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612503576125036124b1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612550576125506124b1565b604052919050565b600067ffffffffffffffff821115612572576125726124b1565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126125af57600080fd5b81356125c26125bd82612558565b612509565b8181528460208386010111156125d757600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561260657600080fd5b813567ffffffffffffffff8082111561261e57600080fd5b9083019060a0828603121561263257600080fd5b61263a6124e0565b82358281111561264957600080fd5b6126558782860161259e565b825250602083013591506126688261242d565b81602082015260408301356040820152606083013560608201526080830135608082015280935050505092915050565b6000610100828403121561085657600080fd5b600061010082840312156126be57600080fd5b611adb8383612698565b600080602083850312156126db57600080fd5b823567ffffffffffffffff808211156126f357600080fd5b818501915085601f83011261270757600080fd5b81358181111561271657600080fd5b8660208260051b850101111561272b57600080fd5b60209290920196919550909350505050565b60005b83811015612758578181015183820152602001612740565b83811115610e4f5750506000910152565b6000815180845261278181602086016020860161273d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015612826577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452612814858351612769565b945092850192908501906001016127da565b5092979650505050505050565b60006020828403121561284557600080fd5b813567ffffffffffffffff81111561285c57600080fd5b820160a08185031215611adb57600080fd5b6000806040838503121561288157600080fd5b8235915060208301356128938161242d565b809150509250929050565b6000806000606084860312156128b357600080fd5b83356128be8161242d565b92506020840135915060408401356128d58161242d565b809150509250925092565b600080600080608085870312156128f657600080fd5b8435935060208501356129088161242d565b925060408501359150606085013561291f8161242d565b939692955090935050565b6000806000806060858703121561294057600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561296657600080fd5b818701915087601f83011261297a57600080fd5b81358181111561298957600080fd5b88602082850101111561299b57600080fd5b95989497505060200194505050565b6000602082840312156129bc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612a2a57612a2a6129c3565b500290565b600082612a65577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082821015612a7c57612a7c6129c3565b500390565b600060208284031215612a9357600080fd5b8135611adb8161242d565b600060208284031215612ab057600080fd5b813562ffffff81168114611adb57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b2757600080fd5b83018035915067ffffffffffffffff821115612b4257600080fd5b602001915036819003821315612b5757600080fd5b9250929050565b8183823760009101908152919050565b600060208284031215612b8057600080fd5b815167ffffffffffffffff811115612b9757600080fd5b8201601f81018413612ba857600080fd5b8051612bb66125bd82612558565b818152856020838501011115612bcb57600080fd5b612bdc82602083016020860161273d565b95945050505050565b602081526000611adb6020830184612769565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612c2a57612c2a6129c3565b5060010190565b600060208284031215612c4357600080fd5b813567ffffffffffffffff80821115612c5b57600080fd5b9083019060408286031215612c6f57600080fd5b604051604081018181108382111715612c8a57612c8a6124b1565b604052823582811115612c9c57600080fd5b612ca88782860161259e565b82525060208301359250612cbb8361242d565b6020810192909252509392505050565b60008219821115612cde57612cde6129c3565b500190565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015612d1057612d106129c3565b039392505050565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115612d4757612d476129c3565b01949350505050565b602081526000825160406020840152612d6c6060840182612769565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401528091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352866020840152851515604084015280851660608401525060a060808301526123cf60a0830184612769565b60008060408385031215612df257600080fd5b505080516020909101519092909150565b60007f8000000000000000000000000000000000000000000000000000000000000000821415612e3557612e356129c3565b5060000390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600060208284031215612e7d57600080fd5b81518015158114611adb57600080fd5b60008251612e9f81846020870161273d565b919091019291505056fea164736f6c6343000809000a000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23
-----Decoded View---------------
Arg [0] : _factory (address): 0xc7a590291e07b9fe9e64b86c58fd8fc764308c4a
Arg [1] : _WETH (address): 0x5c7f8a570d578ed84e63fdfa7b1ee72deae1ae23
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c7a590291e07b9fe9e64b86c58fd8fc764308c4a
Arg [1] : 0000000000000000000000005c7f8a570d578ed84e63fdfa7b1ee72deae1ae23
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.