More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 627,500 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Multicall | 12947227 | 45 mins ago | IN | 0 ETH | 0.00011388 | ||||
Multicall | 12946561 | 1 hr ago | IN | 0 ETH | 0.00000946 | ||||
Swap Exact Input... | 12946533 | 1 hr ago | IN | 0.0042 ETH | 0.0000101 | ||||
Swap Exact Input... | 12946312 | 1 hr ago | IN | 0.00062529 ETH | 0.00001886 | ||||
Multicall | 12945016 | 2 hrs ago | IN | 0 ETH | 0.00001938 | ||||
Swap Exact Input... | 12943862 | 2 hrs ago | IN | 0.02202705 ETH | 0.00003602 | ||||
Swap Exact Input... | 12943311 | 3 hrs ago | IN | 0.00161971 ETH | 0.00001566 | ||||
Swap Exact Input... | 12942263 | 3 hrs ago | IN | 0.00352027 ETH | 0.00012466 | ||||
Swap Exact Input... | 12941806 | 4 hrs ago | IN | 0.00483568 ETH | 0.00003616 | ||||
Multicall | 12940630 | 4 hrs ago | IN | 0 ETH | 0.00007289 | ||||
Multicall | 12939925 | 5 hrs ago | IN | 0 ETH | 0.00001472 | ||||
Multicall | 12938294 | 6 hrs ago | IN | 0 ETH | 0.00001257 | ||||
Multicall | 12937170 | 6 hrs ago | IN | 0 ETH | 0.00001245 | ||||
Multicall | 12936374 | 7 hrs ago | IN | 0 ETH | 0.0000123 | ||||
Multicall | 12935343 | 7 hrs ago | IN | 0 ETH | 0.00001237 | ||||
Multicall | 12934507 | 8 hrs ago | IN | 0 ETH | 0.00007515 | ||||
Multicall | 12934475 | 8 hrs ago | IN | 0 ETH | 0.00007502 | ||||
Multicall | 12934103 | 8 hrs ago | IN | 0 ETH | 0.00007341 | ||||
Swap Exact Input... | 12933185 | 9 hrs ago | IN | 0 ETH | 0.00007023 | ||||
Swap Exact Input... | 12933169 | 9 hrs ago | IN | 0.09470984 ETH | 0.00001084 | ||||
Swap Exact Input... | 12933118 | 9 hrs ago | IN | 0 ETH | 0.0000575 | ||||
Swap Exact Input... | 12933118 | 9 hrs ago | IN | 0 ETH | 0.00006718 | ||||
Swap Exact Input... | 12933108 | 9 hrs ago | IN | 0 ETH | 0.00006072 | ||||
Swap Exact Input... | 12933108 | 9 hrs ago | IN | 0 ETH | 0.00007039 | ||||
Swap Exact Input... | 12933106 | 9 hrs ago | IN | 0 ETH | 0.00006994 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12947227 | 45 mins ago | 0.00469015 ETH | ||||
12947227 | 45 mins ago | 0.00469015 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12947227 | 45 mins ago | 0 ETH | ||||
12946561 | 1 hr ago | 0.00417483 ETH | ||||
12946561 | 1 hr ago | 0.00417483 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946561 | 1 hr ago | 0 ETH | ||||
12946533 | 1 hr ago | 0 ETH | ||||
12946533 | 1 hr ago | 0.0042 ETH | ||||
12946533 | 1 hr ago | 0 ETH | ||||
12946533 | 1 hr ago | 0 ETH | ||||
12946312 | 1 hr ago | 0 ETH | ||||
12946312 | 1 hr ago | 0.00062529 ETH | ||||
12946312 | 1 hr ago | 0 ETH |
Loading...
Loading
Contract Name:
Router
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
No with 200 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(); } }
{ "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "optimizer": { "enabled": false, "runs": 200 }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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
60e06040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000553480156200003557600080fd5b506040516200409e3803806200409e83398181016040528101906200005b9190620001ca565b8181818181818173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1663d04b86b06040518163ffffffff1660e01b815260040160206040518083038186803b1580156200011057600080fd5b505afa15801562000125573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014b91906200024c565b60c0818152505050505050505050506200027e565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001928262000165565b9050919050565b620001a48162000185565b8114620001b057600080fd5b50565b600081519050620001c48162000199565b92915050565b60008060408385031215620001e457620001e362000160565b5b6000620001f485828601620001b3565b92505060206200020785828601620001b3565b9150509250929050565b6000819050919050565b620002268162000211565b81146200023257600080fd5b50565b60008151905062000246816200021b565b92915050565b60006020828403121562000265576200026462000160565b5b6000620002758482850162000235565b91505092915050565b60805160a05160c051613db2620002ec600039600061199f01526000818160cd0152818161092401528181610ab401528181610bab01528181610f0301528181610ffa015281816119ce01528181611a2e0152611aaf0152600081816110d5015261197b0152613db26000f3fe6080604052600436106100c65760003560e01c8063ad8e3d5d1161007f578063bfba6b2211610059578063bfba6b22146102a9578063c222e83a146102d9578063c45a0155146102f5578063fa483e72146103205761015b565b8063ad8e3d5d14610241578063bac37ef714610271578063bf1316c11461028d5761015b565b80631b262321146101605780631faa41331461017c5780635d946c2514610186578063a8c9ed67146101b6578063ac9650d8146101e6578063ad5c4648146102165761015b565b3661015b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610159576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101509061222d565b60405180910390fd5b005b600080fd5b61017a600480360381019061017591906122f5565b610349565b005b6101846104c8565b005b6101a0600480360381019061019b9190612568565b6104de565b6040516101ad91906125c0565b60405180910390f35b6101d060048036038101906101cb9190612600565b610631565b6040516101dd91906125c0565b60405180910390f35b61020060048036038101906101fb919061268e565b610788565b60405161020d9190612825565b60405180910390f35b34801561022257600080fd5b5061022b610922565b6040516102389190612856565b60405180910390f35b61025b60048036038101906102569190612890565b610946565b60405161026891906125c0565b60405180910390f35b61028b600480360381019061028691906128d9565b610ab0565b005b6102a760048036038101906102a29190612919565b610c44565b005b6102c360048036038101906102be919061298c565b610d30565b6040516102d091906125c0565b60405180910390f35b6102f360048036038101906102ee91906129ba565b610eae565b005b34801561030157600080fd5b5061030a6110d3565b6040516103179190612856565b60405180910390f35b34801561032c57600080fd5b5061034760048036038101906103429190612aad565b6110f7565b005b60008211801561035b57506103e88211155b61039a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039190612b6d565b60405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016103d59190612856565b60206040518083038186803b1580156103ed57600080fd5b505afa158015610401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104259190612ba2565b90508481101561046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046190612c1b565b60405180910390fd5b60008111156104c0576000620186a084836104859190612c6a565b61048f9190612cf3565b905060008111156104a7576104a6878230866112d7565b5b6104be8782846104b79190612d24565b30886112d7565b505b505050505050565b60004711156104dc576104db334761136f565b5b565b60008160400151806104ee61145a565b111561052f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052690612da4565b60405180910390fd5b60003390505b6001156105e357600061054b8560000151611462565b90506105a4856060015182610564578660200151610566565b305b600060405180604001604052806105808b600001516114a1565b81526020018773ffffffffffffffffffffffffffffffffffffffff168152506114d9565b85606001818152505080156105d0573091506105c385600001516116b0565b85600001819052506105dd565b84606001519350506105e3565b50610535565b836080015183101561062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062190612e10565b60405180910390fd5b5050919050565b600081608001358061064161145a565b1115610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067990612da4565b60405180910390fd5b6107398360a0013584606001602081019061069d9190612e30565b8560e00160208101906106b09190612e89565b60405180604001604052808860000160208101906106ce9190612e30565b8960400160208101906106e19190612ef1565b8a60200160208101906106f49190612e30565b60405160200161070693929190612f9c565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff168152506114d9565b91508260c00135821015610782576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077990612e10565b60405180910390fd5b50919050565b60608282905067ffffffffffffffff8111156107a7576107a6612386565b5b6040519080825280602002602001820160405280156107da57816020015b60608152602001906001900390816107c55790505b50905060005b8383905081101561091b576000803073ffffffffffffffffffffffffffffffffffffffff1686868581811061081857610817612fd9565b5b905060200281019061082a9190613017565b6040516108389291906130aa565b600060405180830381855af49150503d8060008114610873576040519150601f19603f3d011682016040523d82523d6000602084013e610878565b606091505b5091509150816108e75760448151101561089157600080fd5b600481019050808060200190518101906108ab9190613164565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108de91906131f1565b60405180910390fd5b808484815181106108fb576108fa612fd9565b5b60200260200101819052505050808061091390613213565b9150506107e0565b5092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600081604001358061095661145a565b1115610997576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098e90612da4565b60405180910390fd5b610a3683606001358460200160208101906109b29190612e30565b600060405180604001604052808880600001906109cf9190613017565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505081526020013373ffffffffffffffffffffffffffffffffffffffff168152506116f4565b5060005491508260800135821115610a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7a906132a8565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008190555050919050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610b0b9190612856565b60206040518083038186803b158015610b2357600080fd5b505afa158015610b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5b9190612ba2565b905082811015610ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9790613314565b60405180910390fd5b6000811115610c3f577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b8152600401610c0291906125c0565b600060405180830381600087803b158015610c1c57600080fd5b505af1158015610c30573d6000803e3d6000fd5b50505050610c3e828261136f565b5b505050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c7f9190612856565b60206040518083038186803b158015610c9757600080fd5b505afa158015610cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccf9190612ba2565b905082811015610d14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0b90612c1b565b60405180910390fd5b6000811115610d2a57610d29848230856112d7565b5b50505050565b6000816080013580610d4061145a565b1115610d81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7890612da4565b60405180910390fd5b610e388360a00135846060016020810190610d9c9190612e30565b8560e0016020810190610daf9190612e89565b6040518060400160405280886020016020810190610dcd9190612e30565b896040016020810190610de09190612ef1565b8a6000016020810190610df39190612e30565b604051602001610e0593929190612f9c565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff168152506116f4565b91508260c00135821115610e81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e78906132a8565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008190555050919050565b600082118015610ec057506103e88211155b610eff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef690612b6d565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f5a9190612856565b60206040518083038186803b158015610f7257600080fd5b505afa158015610f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610faa9190612ba2565b905084811015610fef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe690613314565b60405180910390fd5b60008111156110cc577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040161105191906125c0565b600060405180830381600087803b15801561106b57600080fd5b505af115801561107f573d6000803e3d6000fd5b505050506000620186a084836110959190612c6a565b61109f9190612cf3565b905060008111156110b5576110b4838261136f565b5b6110ca8582846110c59190612d24565b61136f565b505b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008413806111065750600083135b611145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113c90613380565b60405180910390fd5b60008282810190611156919061340c565b9050600080600061116a846000015161191a565b92509250925061117b838383611974565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111df906134a1565b60405180910390fd5b60008060008a13611228578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161089611259565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b9150915081156112785761127385876020015133846119cc565b6112cb565b6112858660000151611462565b156112b25761129786600001516116b0565b86600001819052506112ac81336000896116f4565b506112ca565b806000819055506112c984876020015133846119cc565b5b5b50505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561133b5761133681848673ffffffffffffffffffffffffffffffffffffffff16611b739092919063ffffffff16565b611369565b6113688282858773ffffffffffffffffffffffffffffffffffffffff16611bf9909392919063ffffffff16565b5b50505050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156113a857611456565b60008273ffffffffffffffffffffffffffffffffffffffff16826040516113ce906134e7565b60006040518083038185875af1925050503d806000811461140b576040519150601f19603f3d011682016040523d82523d6000602084013e611410565b606091505b5050905080611454576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144b90613548565b60405180910390fd5b505b5050565b600042905090565b6000600360146114729190613568565b6014600360146114829190613568565b61148c9190613568565b6114969190613568565b825110159050919050565b60606114d260006014600360146114b89190613568565b6114c29190613568565b84611c829092919063ffffffff16565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611513573093505b6000806000611525856000015161191a565b92509250925060008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610905060008061156c868686611974565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6115918e611da0565b8660008e73ffffffffffffffffffffffffffffffffffffffff16146115b6578d6115f5565b876115e157600173fffd8963efd1fc6a506488495d951d5263988d266115dc91906135be565b6115f4565b60016401000276a36115f391906135f2565b5b5b8d6040516020016116069190613688565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161163595949392919061372d565b6040805180830381600087803b15801561164e57600080fd5b505af1158015611662573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611686919061379c565b91509150826116955781611697565b805b6116a0906137dc565b9650505050505050949350505050565b60606116ed600360146116c39190613568565b600360146116d19190613568565b84516116dd9190612d24565b84611c829092919063ffffffff16565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561172e573093505b6000806000611740856000015161191a565b92509250925060008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16109050600080611787858786611974565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6117ac8e611da0565b6117b5906137dc565b8660008e73ffffffffffffffffffffffffffffffffffffffff16146117da578d611819565b876117f65760016401000276a36117f191906135f2565b611818565b600173fffd8963efd1fc6a506488495d951d5263988d2661181791906135be565b5b5b8d60405160200161182a9190613688565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161185995949392919061372d565b6040805180830381600087803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118aa919061379c565b915091506000836118c55782826118c0906137dc565b6118d1565b81836118d0906137dc565b5b809250819950505060008a73ffffffffffffffffffffffffffffffffffffffff161415806118fe57508b81145b61190b5761190a613825565b5b50505050505050949350505050565b6000806000611933600085611dd690919063ffffffff16565b9250611949601485611e4c90919063ffffffff16565b905061196b6003601461195c9190613568565b85611dd690919063ffffffff16565b91509193909250565b60006119c37f00000000000000000000000000000000000000000000000000000000000000008585857f0000000000000000000000000000000000000000000000000000000000000000611eb3565b90509392505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015611a275750804710155b15611b60577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611a9457600080fd5b505af1158015611aa8573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401611b08929190613854565b602060405180830381600087803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5a91906138a9565b50611b6d565b611b6c848285856112d7565b5b50505050565b611bf48363a9059cbb60e01b8484604051602401611b92929190613854565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611f63565b505050565b611c7c846323b872dd60e01b858585604051602401611c1a939291906138d6565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611f63565b50505050565b606081601f83611c929190613568565b1015611cd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cca90613959565b60405180910390fd5b8183611cdf9190613568565b84511015611d22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d19906139c5565b60405180910390fd5b6060821560008114611d435760405191506000825260208201604052611d94565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611d815780518352602083019250602081019050611d64565b50868552601f19601f8301166040525050505b50809150509392505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210611dce57600080fd5b819050919050565b6000601482611de59190613568565b83511015611e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1f90613a31565b60405180910390fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b6000600382611e5b9190613568565b83511015611e9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9590613a9d565b60405180910390fd5b60008260038501015190508091505092915050565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610611eef578385611ef2565b84845b8095508196505050600086868686604051602001611f1293929190613acc565b6040516020818303038152906040528051906020012084604051602001611f3b93929190613b85565b6040516020818303038152906040528051906020012090508060001c91505095945050505050565b6000611fc5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661202a9092919063ffffffff16565b90506000815111156120255780806020019051810190611fe591906138a9565b612024576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201b90613c3f565b60405180910390fd5b5b505050565b60606120398484600085612042565b90509392505050565b606082471015612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90613cd1565b60405180910390fd5b61209085612156565b6120cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c690613d3d565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516120f89190613d8e565b60006040518083038185875af1925050503d8060008114612135576040519150601f19603f3d011682016040523d82523d6000602084013e61213a565b606091505b509150915061214a828286612169565b92505050949350505050565b600080823b905060008111915050919050565b60608315612179578290506121c9565b60008351111561218c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121c091906131f1565b60405180910390fd5b9392505050565b600082825260208201905092915050565b7f4e6f742057455448000000000000000000000000000000000000000000000000600082015250565b60006122176008836121d0565b9150612222826121e1565b602082019050919050565b600060208201905081810360008301526122468161220a565b9050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061228c82612261565b9050919050565b61229c81612281565b81146122a757600080fd5b50565b6000813590506122b981612293565b92915050565b6000819050919050565b6122d2816122bf565b81146122dd57600080fd5b50565b6000813590506122ef816122c9565b92915050565b600080600080600060a0868803121561231157612310612257565b5b600061231f888289016122aa565b9550506020612330888289016122e0565b9450506040612341888289016122aa565b9350506060612352888289016122e0565b9250506080612363888289016122aa565b9150509295509295909350565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6123be82612375565b810181811067ffffffffffffffff821117156123dd576123dc612386565b5b80604052505050565b60006123f061224d565b90506123fc82826123b5565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561242b5761242a612386565b5b61243482612375565b9050602081019050919050565b82818337600083830152505050565b600061246361245e84612410565b6123e6565b90508281526020810184848401111561247f5761247e61240b565b5b61248a848285612441565b509392505050565b600082601f8301126124a7576124a6612406565b5b81356124b7848260208601612450565b91505092915050565b600060a082840312156124d6576124d5612370565b5b6124e060a06123e6565b9050600082013567ffffffffffffffff811115612500576124ff612401565b5b61250c84828501612492565b6000830152506020612520848285016122aa565b6020830152506040612534848285016122e0565b6040830152506060612548848285016122e0565b606083015250608061255c848285016122e0565b60808301525092915050565b60006020828403121561257e5761257d612257565b5b600082013567ffffffffffffffff81111561259c5761259b61225c565b5b6125a8848285016124c0565b91505092915050565b6125ba816122bf565b82525050565b60006020820190506125d560008301846125b1565b92915050565b600080fd5b600061010082840312156125f7576125f66125db565b5b81905092915050565b6000610100828403121561261757612616612257565b5b6000612625848285016125e0565b91505092915050565b600080fd5b600080fd5b60008083601f84011261264e5761264d612406565b5b8235905067ffffffffffffffff81111561266b5761266a61262e565b5b60208301915083602082028301111561268757612686612633565b5b9250929050565b600080602083850312156126a5576126a4612257565b5b600083013567ffffffffffffffff8111156126c3576126c261225c565b5b6126cf85828601612638565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612741578082015181840152602081019050612726565b83811115612750576000848401525b50505050565b600061276182612707565b61276b8185612712565b935061277b818560208601612723565b61278481612375565b840191505092915050565b600061279b8383612756565b905092915050565b6000602082019050919050565b60006127bb826126db565b6127c581856126e6565b9350836020820285016127d7856126f7565b8060005b8581101561281357848403895281516127f4858261278f565b94506127ff836127a3565b925060208a019950506001810190506127db565b50829750879550505050505092915050565b6000602082019050818103600083015261283f81846127b0565b905092915050565b61285081612281565b82525050565b600060208201905061286b6000830184612847565b92915050565b600060a08284031215612887576128866125db565b5b81905092915050565b6000602082840312156128a6576128a5612257565b5b600082013567ffffffffffffffff8111156128c4576128c361225c565b5b6128d084828501612871565b91505092915050565b600080604083850312156128f0576128ef612257565b5b60006128fe858286016122e0565b925050602061290f858286016122aa565b9150509250929050565b60008060006060848603121561293257612931612257565b5b6000612940868287016122aa565b9350506020612951868287016122e0565b9250506040612962868287016122aa565b9150509250925092565b60006101008284031215612983576129826125db565b5b81905092915050565b600061010082840312156129a3576129a2612257565b5b60006129b18482850161296c565b91505092915050565b600080600080608085870312156129d4576129d3612257565b5b60006129e2878288016122e0565b94505060206129f3878288016122aa565b9350506040612a04878288016122e0565b9250506060612a15878288016122aa565b91505092959194509250565b6000819050919050565b612a3481612a21565b8114612a3f57600080fd5b50565b600081359050612a5181612a2b565b92915050565b60008083601f840112612a6d57612a6c612406565b5b8235905067ffffffffffffffff811115612a8a57612a8961262e565b5b602083019150836001820283011115612aa657612aa5612633565b5b9250929050565b60008060008060608587031215612ac757612ac6612257565b5b6000612ad587828801612a42565b9450506020612ae687828801612a42565b935050604085013567ffffffffffffffff811115612b0757612b0661225c565b5b612b1387828801612a57565b925092505092959194509250565b7f4869676820666565000000000000000000000000000000000000000000000000600082015250565b6000612b576008836121d0565b9150612b6282612b21565b602082019050919050565b60006020820190508181036000830152612b8681612b4a565b9050919050565b600081519050612b9c816122c9565b92915050565b600060208284031215612bb857612bb7612257565b5b6000612bc684828501612b8d565b91505092915050565b7f496e73756666696369656e7420746f6b656e0000000000000000000000000000600082015250565b6000612c056012836121d0565b9150612c1082612bcf565b602082019050919050565b60006020820190508181036000830152612c3481612bf8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612c75826122bf565b9150612c80836122bf565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612cb957612cb8612c3b565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612cfe826122bf565b9150612d09836122bf565b925082612d1957612d18612cc4565b5b828204905092915050565b6000612d2f826122bf565b9150612d3a836122bf565b925082821015612d4d57612d4c612c3b565b5b828203905092915050565b7f4578706972656400000000000000000000000000000000000000000000000000600082015250565b6000612d8e6007836121d0565b9150612d9982612d58565b602082019050919050565b60006020820190508181036000830152612dbd81612d81565b9050919050565b7f526f757465723a20696e73756666696369656e7420616d6f756e744f75740000600082015250565b6000612dfa601e836121d0565b9150612e0582612dc4565b602082019050919050565b60006020820190508181036000830152612e2981612ded565b9050919050565b600060208284031215612e4657612e45612257565b5b6000612e54848285016122aa565b91505092915050565b612e6681612261565b8114612e7157600080fd5b50565b600081359050612e8381612e5d565b92915050565b600060208284031215612e9f57612e9e612257565b5b6000612ead84828501612e74565b91505092915050565b600062ffffff82169050919050565b612ece81612eb6565b8114612ed957600080fd5b50565b600081359050612eeb81612ec5565b92915050565b600060208284031215612f0757612f06612257565b5b6000612f1584828501612edc565b91505092915050565b60008160601b9050919050565b6000612f3682612f1e565b9050919050565b6000612f4882612f2b565b9050919050565b612f60612f5b82612281565b612f3d565b82525050565b60008160e81b9050919050565b6000612f7e82612f66565b9050919050565b612f96612f9182612eb6565b612f73565b82525050565b6000612fa88286612f4f565b601482019150612fb88285612f85565b600382019150612fc88284612f4f565b601482019150819050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261303457613033613008565b5b80840192508235915067ffffffffffffffff8211156130565761305561300d565b5b60208301925060018202360383131561307257613071613012565b5b509250929050565b600081905092915050565b6000613091838561307a565b935061309e838584612441565b82840190509392505050565b60006130b7828486613085565b91508190509392505050565b600067ffffffffffffffff8211156130de576130dd612386565b5b6130e782612375565b9050602081019050919050565b6000613107613102846130c3565b6123e6565b9050828152602081018484840111156131235761312261240b565b5b61312e848285612723565b509392505050565b600082601f83011261314b5761314a612406565b5b815161315b8482602086016130f4565b91505092915050565b60006020828403121561317a57613179612257565b5b600082015167ffffffffffffffff8111156131985761319761225c565b5b6131a484828501613136565b91505092915050565b600081519050919050565b60006131c3826131ad565b6131cd81856121d0565b93506131dd818560208601612723565b6131e681612375565b840191505092915050565b6000602082019050818103600083015261320b81846131b8565b905092915050565b600061321e826122bf565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561325157613250612c3b565b5b600182019050919050565b7f526f757465723a20616d6f756e74496e20697320746f6f206869676800000000600082015250565b6000613292601c836121d0565b915061329d8261325c565b602082019050919050565b600060208201905081810360008301526132c181613285565b9050919050565b7f496e73756666696369656e742057455448000000000000000000000000000000600082015250565b60006132fe6011836121d0565b9150613309826132c8565b602082019050919050565b6000602082019050818103600083015261332d816132f1565b9050919050565b7f526f757465723a20696e76616c69642064656c74612071746965730000000000600082015250565b600061336a601b836121d0565b915061337582613334565b602082019050919050565b600060208201905081810360008301526133998161335d565b9050919050565b6000604082840312156133b6576133b5612370565b5b6133c060406123e6565b9050600082013567ffffffffffffffff8111156133e0576133df612401565b5b6133ec84828501612492565b6000830152506020613400848285016122aa565b60208301525092915050565b60006020828403121561342257613421612257565b5b600082013567ffffffffffffffff8111156134405761343f61225c565b5b61344c848285016133a0565b91505092915050565b7f526f757465723a20696e76616c69642063616c6c6261636b2073656e64657200600082015250565b600061348b601f836121d0565b915061349682613455565b602082019050919050565b600060208201905081810360008301526134ba8161347e565b9050919050565b50565b60006134d160008361307a565b91506134dc826134c1565b600082019050919050565b60006134f2826134c4565b9150819050919050565b7f7472616e7366657220657468206661696c656400000000000000000000000000600082015250565b60006135326013836121d0565b915061353d826134fc565b602082019050919050565b6000602082019050818103600083015261356181613525565b9050919050565b6000613573826122bf565b915061357e836122bf565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156135b3576135b2612c3b565b5b828201905092915050565b60006135c982612261565b91506135d483612261565b9250828210156135e7576135e6612c3b565b5b828203905092915050565b60006135fd82612261565b915061360883612261565b92508273ffffffffffffffffffffffffffffffffffffffff0382111561363157613630612c3b565b5b828201905092915050565b61364581612281565b82525050565b600060408301600083015184820360008601526136688282612756565b915050602083015161367d602086018261363c565b508091505092915050565b600060208201905081810360008301526136a2818461364b565b905092915050565b6136b381612a21565b82525050565b60008115159050919050565b6136ce816136b9565b82525050565b6136dd81612261565b82525050565b600082825260208201905092915050565b60006136ff82612707565b61370981856136e3565b9350613719818560208601612723565b61372281612375565b840191505092915050565b600060a0820190506137426000830188612847565b61374f60208301876136aa565b61375c60408301866136c5565b61376960608301856136d4565b818103608083015261377b81846136f4565b90509695505050505050565b60008151905061379681612a2b565b92915050565b600080604083850312156137b3576137b2612257565b5b60006137c185828601613787565b92505060206137d285828601613787565b9150509250929050565b60006137e782612a21565b91507f800000000000000000000000000000000000000000000000000000000000000082141561381a57613819612c3b565b5b816000039050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60006040820190506138696000830185612847565b61387660208301846125b1565b9392505050565b613886816136b9565b811461389157600080fd5b50565b6000815190506138a38161387d565b92915050565b6000602082840312156138bf576138be612257565b5b60006138cd84828501613894565b91505092915050565b60006060820190506138eb6000830186612847565b6138f86020830185612847565b61390560408301846125b1565b949350505050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000613943600e836121d0565b915061394e8261390d565b602082019050919050565b6000602082019050818103600083015261397281613936565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b60006139af6011836121d0565b91506139ba82613979565b602082019050919050565b600060208201905081810360008301526139de816139a2565b9050919050565b7f746f416464726573735f6f75744f66426f756e64730000000000000000000000600082015250565b6000613a1b6015836121d0565b9150613a26826139e5565b602082019050919050565b60006020820190508181036000830152613a4a81613a0e565b9050919050565b7f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000600082015250565b6000613a876014836121d0565b9150613a9282613a51565b602082019050919050565b60006020820190508181036000830152613ab681613a7a565b9050919050565b613ac681612eb6565b82525050565b6000606082019050613ae16000830186612847565b613aee6020830185612847565b613afb6040830184613abd565b949350505050565b600081905092915050565b7fff00000000000000000000000000000000000000000000000000000000000000600082015250565b6000613b44600183613b03565b9150613b4f82613b0e565b600182019050919050565b6000819050919050565b6000819050919050565b613b7f613b7a82613b5a565b613b64565b82525050565b6000613b9082613b37565b9150613b9c8286612f4f565b601482019150613bac8285613b6e565b602082019150613bbc8284613b6e565b602082019150819050949350505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000613c29602a836121d0565b9150613c3482613bcd565b604082019050919050565b60006020820190508181036000830152613c5881613c1c565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000613cbb6026836121d0565b9150613cc682613c5f565b604082019050919050565b60006020820190508181036000830152613cea81613cae565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000613d27601d836121d0565b9150613d3282613cf1565b602082019050919050565b60006020820190508181036000830152613d5681613d1a565b9050919050565b6000613d6882612707565b613d72818561307a565b9350613d82818560208601612723565b80840191505092915050565b6000613d9a8284613d5d565b91508190509291505056fea164736f6c6343000809000a0000000000000000000000009fe607e5dcd0ea318dbb4d8a7b04fa553d6cb2c5000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f
Deployed Bytecode
0x6080604052600436106100c65760003560e01c8063ad8e3d5d1161007f578063bfba6b2211610059578063bfba6b22146102a9578063c222e83a146102d9578063c45a0155146102f5578063fa483e72146103205761015b565b8063ad8e3d5d14610241578063bac37ef714610271578063bf1316c11461028d5761015b565b80631b262321146101605780631faa41331461017c5780635d946c2514610186578063a8c9ed67146101b6578063ac9650d8146101e6578063ad5c4648146102165761015b565b3661015b577f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610159576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101509061222d565b60405180910390fd5b005b600080fd5b61017a600480360381019061017591906122f5565b610349565b005b6101846104c8565b005b6101a0600480360381019061019b9190612568565b6104de565b6040516101ad91906125c0565b60405180910390f35b6101d060048036038101906101cb9190612600565b610631565b6040516101dd91906125c0565b60405180910390f35b61020060048036038101906101fb919061268e565b610788565b60405161020d9190612825565b60405180910390f35b34801561022257600080fd5b5061022b610922565b6040516102389190612856565b60405180910390f35b61025b60048036038101906102569190612890565b610946565b60405161026891906125c0565b60405180910390f35b61028b600480360381019061028691906128d9565b610ab0565b005b6102a760048036038101906102a29190612919565b610c44565b005b6102c360048036038101906102be919061298c565b610d30565b6040516102d091906125c0565b60405180910390f35b6102f360048036038101906102ee91906129ba565b610eae565b005b34801561030157600080fd5b5061030a6110d3565b6040516103179190612856565b60405180910390f35b34801561032c57600080fd5b5061034760048036038101906103429190612aad565b6110f7565b005b60008211801561035b57506103e88211155b61039a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039190612b6d565b60405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016103d59190612856565b60206040518083038186803b1580156103ed57600080fd5b505afa158015610401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104259190612ba2565b90508481101561046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046190612c1b565b60405180910390fd5b60008111156104c0576000620186a084836104859190612c6a565b61048f9190612cf3565b905060008111156104a7576104a6878230866112d7565b5b6104be8782846104b79190612d24565b30886112d7565b505b505050505050565b60004711156104dc576104db334761136f565b5b565b60008160400151806104ee61145a565b111561052f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052690612da4565b60405180910390fd5b60003390505b6001156105e357600061054b8560000151611462565b90506105a4856060015182610564578660200151610566565b305b600060405180604001604052806105808b600001516114a1565b81526020018773ffffffffffffffffffffffffffffffffffffffff168152506114d9565b85606001818152505080156105d0573091506105c385600001516116b0565b85600001819052506105dd565b84606001519350506105e3565b50610535565b836080015183101561062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062190612e10565b60405180910390fd5b5050919050565b600081608001358061064161145a565b1115610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067990612da4565b60405180910390fd5b6107398360a0013584606001602081019061069d9190612e30565b8560e00160208101906106b09190612e89565b60405180604001604052808860000160208101906106ce9190612e30565b8960400160208101906106e19190612ef1565b8a60200160208101906106f49190612e30565b60405160200161070693929190612f9c565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff168152506114d9565b91508260c00135821015610782576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077990612e10565b60405180910390fd5b50919050565b60608282905067ffffffffffffffff8111156107a7576107a6612386565b5b6040519080825280602002602001820160405280156107da57816020015b60608152602001906001900390816107c55790505b50905060005b8383905081101561091b576000803073ffffffffffffffffffffffffffffffffffffffff1686868581811061081857610817612fd9565b5b905060200281019061082a9190613017565b6040516108389291906130aa565b600060405180830381855af49150503d8060008114610873576040519150601f19603f3d011682016040523d82523d6000602084013e610878565b606091505b5091509150816108e75760448151101561089157600080fd5b600481019050808060200190518101906108ab9190613164565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108de91906131f1565b60405180910390fd5b808484815181106108fb576108fa612fd9565b5b60200260200101819052505050808061091390613213565b9150506107e0565b5092915050565b7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f81565b600081604001358061095661145a565b1115610997576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098e90612da4565b60405180910390fd5b610a3683606001358460200160208101906109b29190612e30565b600060405180604001604052808880600001906109cf9190613017565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505081526020013373ffffffffffffffffffffffffffffffffffffffff168152506116f4565b5060005491508260800135821115610a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7a906132a8565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008190555050919050565b60007f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610b0b9190612856565b60206040518083038186803b158015610b2357600080fd5b505afa158015610b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5b9190612ba2565b905082811015610ba0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9790613314565b60405180910390fd5b6000811115610c3f577f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b8152600401610c0291906125c0565b600060405180830381600087803b158015610c1c57600080fd5b505af1158015610c30573d6000803e3d6000fd5b50505050610c3e828261136f565b5b505050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c7f9190612856565b60206040518083038186803b158015610c9757600080fd5b505afa158015610cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccf9190612ba2565b905082811015610d14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0b90612c1b565b60405180910390fd5b6000811115610d2a57610d29848230856112d7565b5b50505050565b6000816080013580610d4061145a565b1115610d81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7890612da4565b60405180910390fd5b610e388360a00135846060016020810190610d9c9190612e30565b8560e0016020810190610daf9190612e89565b6040518060400160405280886020016020810190610dcd9190612e30565b896040016020810190610de09190612ef1565b8a6000016020810190610df39190612e30565b604051602001610e0593929190612f9c565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff168152506116f4565b91508260c00135821115610e81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e78906132a8565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008190555050919050565b600082118015610ec057506103e88211155b610eff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef690612b6d565b60405180910390fd5b60007f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f5a9190612856565b60206040518083038186803b158015610f7257600080fd5b505afa158015610f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610faa9190612ba2565b905084811015610fef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe690613314565b60405180910390fd5b60008111156110cc577f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040161105191906125c0565b600060405180830381600087803b15801561106b57600080fd5b505af115801561107f573d6000803e3d6000fd5b505050506000620186a084836110959190612c6a565b61109f9190612cf3565b905060008111156110b5576110b4838261136f565b5b6110ca8582846110c59190612d24565b61136f565b505b5050505050565b7f0000000000000000000000009fe607e5dcd0ea318dbb4d8a7b04fa553d6cb2c581565b60008413806111065750600083135b611145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113c90613380565b60405180910390fd5b60008282810190611156919061340c565b9050600080600061116a846000015161191a565b92509250925061117b838383611974565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111df906134a1565b60405180910390fd5b60008060008a13611228578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161089611259565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b9150915081156112785761127385876020015133846119cc565b6112cb565b6112858660000151611462565b156112b25761129786600001516116b0565b86600001819052506112ac81336000896116f4565b506112ca565b806000819055506112c984876020015133846119cc565b5b5b50505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561133b5761133681848673ffffffffffffffffffffffffffffffffffffffff16611b739092919063ffffffff16565b611369565b6113688282858773ffffffffffffffffffffffffffffffffffffffff16611bf9909392919063ffffffff16565b5b50505050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156113a857611456565b60008273ffffffffffffffffffffffffffffffffffffffff16826040516113ce906134e7565b60006040518083038185875af1925050503d806000811461140b576040519150601f19603f3d011682016040523d82523d6000602084013e611410565b606091505b5050905080611454576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144b90613548565b60405180910390fd5b505b5050565b600042905090565b6000600360146114729190613568565b6014600360146114829190613568565b61148c9190613568565b6114969190613568565b825110159050919050565b60606114d260006014600360146114b89190613568565b6114c29190613568565b84611c829092919063ffffffff16565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611513573093505b6000806000611525856000015161191a565b92509250925060008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610905060008061156c868686611974565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6115918e611da0565b8660008e73ffffffffffffffffffffffffffffffffffffffff16146115b6578d6115f5565b876115e157600173fffd8963efd1fc6a506488495d951d5263988d266115dc91906135be565b6115f4565b60016401000276a36115f391906135f2565b5b5b8d6040516020016116069190613688565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161163595949392919061372d565b6040805180830381600087803b15801561164e57600080fd5b505af1158015611662573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611686919061379c565b91509150826116955781611697565b805b6116a0906137dc565b9650505050505050949350505050565b60606116ed600360146116c39190613568565b600360146116d19190613568565b84516116dd9190612d24565b84611c829092919063ffffffff16565b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561172e573093505b6000806000611740856000015161191a565b92509250925060008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16109050600080611787858786611974565b73ffffffffffffffffffffffffffffffffffffffff166324b31a0c8b6117ac8e611da0565b6117b5906137dc565b8660008e73ffffffffffffffffffffffffffffffffffffffff16146117da578d611819565b876117f65760016401000276a36117f191906135f2565b611818565b600173fffd8963efd1fc6a506488495d951d5263988d2661181791906135be565b5b5b8d60405160200161182a9190613688565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161185995949392919061372d565b6040805180830381600087803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118aa919061379c565b915091506000836118c55782826118c0906137dc565b6118d1565b81836118d0906137dc565b5b809250819950505060008a73ffffffffffffffffffffffffffffffffffffffff161415806118fe57508b81145b61190b5761190a613825565b5b50505050505050949350505050565b6000806000611933600085611dd690919063ffffffff16565b9250611949601485611e4c90919063ffffffff16565b905061196b6003601461195c9190613568565b85611dd690919063ffffffff16565b91509193909250565b60006119c37f0000000000000000000000009fe607e5dcd0ea318dbb4d8a7b04fa553d6cb2c58585857fb323685a0ba07b4131380b999008d536a5dc52221581debd699b83b0835e0b68611eb3565b90509392505050565b7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015611a275750804710155b15611b60577f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611a9457600080fd5b505af1158015611aa8573d6000803e3d6000fd5b50505050507f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401611b08929190613854565b602060405180830381600087803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5a91906138a9565b50611b6d565b611b6c848285856112d7565b5b50505050565b611bf48363a9059cbb60e01b8484604051602401611b92929190613854565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611f63565b505050565b611c7c846323b872dd60e01b858585604051602401611c1a939291906138d6565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611f63565b50505050565b606081601f83611c929190613568565b1015611cd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cca90613959565b60405180910390fd5b8183611cdf9190613568565b84511015611d22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d19906139c5565b60405180910390fd5b6060821560008114611d435760405191506000825260208201604052611d94565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611d815780518352602083019250602081019050611d64565b50868552601f19601f8301166040525050505b50809150509392505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210611dce57600080fd5b819050919050565b6000601482611de59190613568565b83511015611e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1f90613a31565b60405180910390fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b6000600382611e5b9190613568565b83511015611e9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9590613a9d565b60405180910390fd5b60008260038501015190508091505092915050565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610611eef578385611ef2565b84845b8095508196505050600086868686604051602001611f1293929190613acc565b6040516020818303038152906040528051906020012084604051602001611f3b93929190613b85565b6040516020818303038152906040528051906020012090508060001c91505095945050505050565b6000611fc5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661202a9092919063ffffffff16565b90506000815111156120255780806020019051810190611fe591906138a9565b612024576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201b90613c3f565b60405180910390fd5b5b505050565b60606120398484600085612042565b90509392505050565b606082471015612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90613cd1565b60405180910390fd5b61209085612156565b6120cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c690613d3d565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516120f89190613d8e565b60006040518083038185875af1925050503d8060008114612135576040519150601f19603f3d011682016040523d82523d6000602084013e61213a565b606091505b509150915061214a828286612169565b92505050949350505050565b600080823b905060008111915050919050565b60608315612179578290506121c9565b60008351111561218c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121c091906131f1565b60405180910390fd5b9392505050565b600082825260208201905092915050565b7f4e6f742057455448000000000000000000000000000000000000000000000000600082015250565b60006122176008836121d0565b9150612222826121e1565b602082019050919050565b600060208201905081810360008301526122468161220a565b9050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061228c82612261565b9050919050565b61229c81612281565b81146122a757600080fd5b50565b6000813590506122b981612293565b92915050565b6000819050919050565b6122d2816122bf565b81146122dd57600080fd5b50565b6000813590506122ef816122c9565b92915050565b600080600080600060a0868803121561231157612310612257565b5b600061231f888289016122aa565b9550506020612330888289016122e0565b9450506040612341888289016122aa565b9350506060612352888289016122e0565b9250506080612363888289016122aa565b9150509295509295909350565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6123be82612375565b810181811067ffffffffffffffff821117156123dd576123dc612386565b5b80604052505050565b60006123f061224d565b90506123fc82826123b5565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561242b5761242a612386565b5b61243482612375565b9050602081019050919050565b82818337600083830152505050565b600061246361245e84612410565b6123e6565b90508281526020810184848401111561247f5761247e61240b565b5b61248a848285612441565b509392505050565b600082601f8301126124a7576124a6612406565b5b81356124b7848260208601612450565b91505092915050565b600060a082840312156124d6576124d5612370565b5b6124e060a06123e6565b9050600082013567ffffffffffffffff811115612500576124ff612401565b5b61250c84828501612492565b6000830152506020612520848285016122aa565b6020830152506040612534848285016122e0565b6040830152506060612548848285016122e0565b606083015250608061255c848285016122e0565b60808301525092915050565b60006020828403121561257e5761257d612257565b5b600082013567ffffffffffffffff81111561259c5761259b61225c565b5b6125a8848285016124c0565b91505092915050565b6125ba816122bf565b82525050565b60006020820190506125d560008301846125b1565b92915050565b600080fd5b600061010082840312156125f7576125f66125db565b5b81905092915050565b6000610100828403121561261757612616612257565b5b6000612625848285016125e0565b91505092915050565b600080fd5b600080fd5b60008083601f84011261264e5761264d612406565b5b8235905067ffffffffffffffff81111561266b5761266a61262e565b5b60208301915083602082028301111561268757612686612633565b5b9250929050565b600080602083850312156126a5576126a4612257565b5b600083013567ffffffffffffffff8111156126c3576126c261225c565b5b6126cf85828601612638565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612741578082015181840152602081019050612726565b83811115612750576000848401525b50505050565b600061276182612707565b61276b8185612712565b935061277b818560208601612723565b61278481612375565b840191505092915050565b600061279b8383612756565b905092915050565b6000602082019050919050565b60006127bb826126db565b6127c581856126e6565b9350836020820285016127d7856126f7565b8060005b8581101561281357848403895281516127f4858261278f565b94506127ff836127a3565b925060208a019950506001810190506127db565b50829750879550505050505092915050565b6000602082019050818103600083015261283f81846127b0565b905092915050565b61285081612281565b82525050565b600060208201905061286b6000830184612847565b92915050565b600060a08284031215612887576128866125db565b5b81905092915050565b6000602082840312156128a6576128a5612257565b5b600082013567ffffffffffffffff8111156128c4576128c361225c565b5b6128d084828501612871565b91505092915050565b600080604083850312156128f0576128ef612257565b5b60006128fe858286016122e0565b925050602061290f858286016122aa565b9150509250929050565b60008060006060848603121561293257612931612257565b5b6000612940868287016122aa565b9350506020612951868287016122e0565b9250506040612962868287016122aa565b9150509250925092565b60006101008284031215612983576129826125db565b5b81905092915050565b600061010082840312156129a3576129a2612257565b5b60006129b18482850161296c565b91505092915050565b600080600080608085870312156129d4576129d3612257565b5b60006129e2878288016122e0565b94505060206129f3878288016122aa565b9350506040612a04878288016122e0565b9250506060612a15878288016122aa565b91505092959194509250565b6000819050919050565b612a3481612a21565b8114612a3f57600080fd5b50565b600081359050612a5181612a2b565b92915050565b60008083601f840112612a6d57612a6c612406565b5b8235905067ffffffffffffffff811115612a8a57612a8961262e565b5b602083019150836001820283011115612aa657612aa5612633565b5b9250929050565b60008060008060608587031215612ac757612ac6612257565b5b6000612ad587828801612a42565b9450506020612ae687828801612a42565b935050604085013567ffffffffffffffff811115612b0757612b0661225c565b5b612b1387828801612a57565b925092505092959194509250565b7f4869676820666565000000000000000000000000000000000000000000000000600082015250565b6000612b576008836121d0565b9150612b6282612b21565b602082019050919050565b60006020820190508181036000830152612b8681612b4a565b9050919050565b600081519050612b9c816122c9565b92915050565b600060208284031215612bb857612bb7612257565b5b6000612bc684828501612b8d565b91505092915050565b7f496e73756666696369656e7420746f6b656e0000000000000000000000000000600082015250565b6000612c056012836121d0565b9150612c1082612bcf565b602082019050919050565b60006020820190508181036000830152612c3481612bf8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612c75826122bf565b9150612c80836122bf565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612cb957612cb8612c3b565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612cfe826122bf565b9150612d09836122bf565b925082612d1957612d18612cc4565b5b828204905092915050565b6000612d2f826122bf565b9150612d3a836122bf565b925082821015612d4d57612d4c612c3b565b5b828203905092915050565b7f4578706972656400000000000000000000000000000000000000000000000000600082015250565b6000612d8e6007836121d0565b9150612d9982612d58565b602082019050919050565b60006020820190508181036000830152612dbd81612d81565b9050919050565b7f526f757465723a20696e73756666696369656e7420616d6f756e744f75740000600082015250565b6000612dfa601e836121d0565b9150612e0582612dc4565b602082019050919050565b60006020820190508181036000830152612e2981612ded565b9050919050565b600060208284031215612e4657612e45612257565b5b6000612e54848285016122aa565b91505092915050565b612e6681612261565b8114612e7157600080fd5b50565b600081359050612e8381612e5d565b92915050565b600060208284031215612e9f57612e9e612257565b5b6000612ead84828501612e74565b91505092915050565b600062ffffff82169050919050565b612ece81612eb6565b8114612ed957600080fd5b50565b600081359050612eeb81612ec5565b92915050565b600060208284031215612f0757612f06612257565b5b6000612f1584828501612edc565b91505092915050565b60008160601b9050919050565b6000612f3682612f1e565b9050919050565b6000612f4882612f2b565b9050919050565b612f60612f5b82612281565b612f3d565b82525050565b60008160e81b9050919050565b6000612f7e82612f66565b9050919050565b612f96612f9182612eb6565b612f73565b82525050565b6000612fa88286612f4f565b601482019150612fb88285612f85565b600382019150612fc88284612f4f565b601482019150819050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261303457613033613008565b5b80840192508235915067ffffffffffffffff8211156130565761305561300d565b5b60208301925060018202360383131561307257613071613012565b5b509250929050565b600081905092915050565b6000613091838561307a565b935061309e838584612441565b82840190509392505050565b60006130b7828486613085565b91508190509392505050565b600067ffffffffffffffff8211156130de576130dd612386565b5b6130e782612375565b9050602081019050919050565b6000613107613102846130c3565b6123e6565b9050828152602081018484840111156131235761312261240b565b5b61312e848285612723565b509392505050565b600082601f83011261314b5761314a612406565b5b815161315b8482602086016130f4565b91505092915050565b60006020828403121561317a57613179612257565b5b600082015167ffffffffffffffff8111156131985761319761225c565b5b6131a484828501613136565b91505092915050565b600081519050919050565b60006131c3826131ad565b6131cd81856121d0565b93506131dd818560208601612723565b6131e681612375565b840191505092915050565b6000602082019050818103600083015261320b81846131b8565b905092915050565b600061321e826122bf565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561325157613250612c3b565b5b600182019050919050565b7f526f757465723a20616d6f756e74496e20697320746f6f206869676800000000600082015250565b6000613292601c836121d0565b915061329d8261325c565b602082019050919050565b600060208201905081810360008301526132c181613285565b9050919050565b7f496e73756666696369656e742057455448000000000000000000000000000000600082015250565b60006132fe6011836121d0565b9150613309826132c8565b602082019050919050565b6000602082019050818103600083015261332d816132f1565b9050919050565b7f526f757465723a20696e76616c69642064656c74612071746965730000000000600082015250565b600061336a601b836121d0565b915061337582613334565b602082019050919050565b600060208201905081810360008301526133998161335d565b9050919050565b6000604082840312156133b6576133b5612370565b5b6133c060406123e6565b9050600082013567ffffffffffffffff8111156133e0576133df612401565b5b6133ec84828501612492565b6000830152506020613400848285016122aa565b60208301525092915050565b60006020828403121561342257613421612257565b5b600082013567ffffffffffffffff8111156134405761343f61225c565b5b61344c848285016133a0565b91505092915050565b7f526f757465723a20696e76616c69642063616c6c6261636b2073656e64657200600082015250565b600061348b601f836121d0565b915061349682613455565b602082019050919050565b600060208201905081810360008301526134ba8161347e565b9050919050565b50565b60006134d160008361307a565b91506134dc826134c1565b600082019050919050565b60006134f2826134c4565b9150819050919050565b7f7472616e7366657220657468206661696c656400000000000000000000000000600082015250565b60006135326013836121d0565b915061353d826134fc565b602082019050919050565b6000602082019050818103600083015261356181613525565b9050919050565b6000613573826122bf565b915061357e836122bf565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156135b3576135b2612c3b565b5b828201905092915050565b60006135c982612261565b91506135d483612261565b9250828210156135e7576135e6612c3b565b5b828203905092915050565b60006135fd82612261565b915061360883612261565b92508273ffffffffffffffffffffffffffffffffffffffff0382111561363157613630612c3b565b5b828201905092915050565b61364581612281565b82525050565b600060408301600083015184820360008601526136688282612756565b915050602083015161367d602086018261363c565b508091505092915050565b600060208201905081810360008301526136a2818461364b565b905092915050565b6136b381612a21565b82525050565b60008115159050919050565b6136ce816136b9565b82525050565b6136dd81612261565b82525050565b600082825260208201905092915050565b60006136ff82612707565b61370981856136e3565b9350613719818560208601612723565b61372281612375565b840191505092915050565b600060a0820190506137426000830188612847565b61374f60208301876136aa565b61375c60408301866136c5565b61376960608301856136d4565b818103608083015261377b81846136f4565b90509695505050505050565b60008151905061379681612a2b565b92915050565b600080604083850312156137b3576137b2612257565b5b60006137c185828601613787565b92505060206137d285828601613787565b9150509250929050565b60006137e782612a21565b91507f800000000000000000000000000000000000000000000000000000000000000082141561381a57613819612c3b565b5b816000039050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60006040820190506138696000830185612847565b61387660208301846125b1565b9392505050565b613886816136b9565b811461389157600080fd5b50565b6000815190506138a38161387d565b92915050565b6000602082840312156138bf576138be612257565b5b60006138cd84828501613894565b91505092915050565b60006060820190506138eb6000830186612847565b6138f86020830185612847565b61390560408301846125b1565b949350505050565b7f736c6963655f6f766572666c6f77000000000000000000000000000000000000600082015250565b6000613943600e836121d0565b915061394e8261390d565b602082019050919050565b6000602082019050818103600083015261397281613936565b9050919050565b7f736c6963655f6f75744f66426f756e6473000000000000000000000000000000600082015250565b60006139af6011836121d0565b91506139ba82613979565b602082019050919050565b600060208201905081810360008301526139de816139a2565b9050919050565b7f746f416464726573735f6f75744f66426f756e64730000000000000000000000600082015250565b6000613a1b6015836121d0565b9150613a26826139e5565b602082019050919050565b60006020820190508181036000830152613a4a81613a0e565b9050919050565b7f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000600082015250565b6000613a876014836121d0565b9150613a9282613a51565b602082019050919050565b60006020820190508181036000830152613ab681613a7a565b9050919050565b613ac681612eb6565b82525050565b6000606082019050613ae16000830186612847565b613aee6020830185612847565b613afb6040830184613abd565b949350505050565b600081905092915050565b7fff00000000000000000000000000000000000000000000000000000000000000600082015250565b6000613b44600183613b03565b9150613b4f82613b0e565b600182019050919050565b6000819050919050565b6000819050919050565b613b7f613b7a82613b5a565b613b64565b82525050565b6000613b9082613b37565b9150613b9c8286612f4f565b601482019150613bac8285613b6e565b602082019150613bbc8284613b6e565b602082019150819050949350505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000613c29602a836121d0565b9150613c3482613bcd565b604082019050919050565b60006020820190508181036000830152613c5881613c1c565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000613cbb6026836121d0565b9150613cc682613c5f565b604082019050919050565b60006020820190508181036000830152613cea81613cae565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000613d27601d836121d0565b9150613d3282613cf1565b602082019050919050565b60006020820190508181036000830152613d5681613d1a565b9050919050565b6000613d6882612707565b613d72818561307a565b9350613d82818560208601612723565b80840191505092915050565b6000613d9a8284613d5d565b91508190509291505056fea164736f6c6343000809000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009fe607e5dcd0ea318dbb4d8a7b04fa553d6cb2c5000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f
-----Decoded View---------------
Arg [0] : _factory (address): 0x9Fe607e5dCd0Ea318dBB4D8a7B04fa553d6cB2c5
Arg [1] : _WETH (address): 0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009fe607e5dcd0ea318dbb4d8a7b04fa553d6cb2c5
Arg [1] : 000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.