Source Code
Overview
GLMR Balance
GLMR Value
$0.00Latest 25 from a total of 52 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Remove Liquidity... | 1083078 | 1346 days ago | IN | 0 GLMR | 0.01552097 | ||||
| Add Liquidity ET... | 1078425 | 1347 days ago | IN | 6.09914989 GLMR | 0.01274576 | ||||
| Add Liquidity ET... | 1078419 | 1347 days ago | IN | 3 GLMR | 0.38340792 | ||||
| Remove Liquidity | 815102 | 1385 days ago | IN | 0 GLMR | 0.01495531 | ||||
| Remove Liquidity... | 815093 | 1385 days ago | IN | 0 GLMR | 0.01570895 | ||||
| Remove Liquidity | 815071 | 1385 days ago | IN | 0 GLMR | 0.01657413 | ||||
| Swap Exact Token... | 812060 | 1386 days ago | IN | 0 GLMR | 0.01237315 | ||||
| Swap ETH For Exa... | 812056 | 1386 days ago | IN | 0.00004821 GLMR | 0.0136217 | ||||
| Swap Exact Token... | 812043 | 1386 days ago | IN | 0 GLMR | 0.01237315 | ||||
| Swap ETH For Exa... | 812040 | 1386 days ago | IN | 0.00000014 GLMR | 0.01362069 | ||||
| Swap Exact Token... | 812036 | 1386 days ago | IN | 0 GLMR | 0.01162773 | ||||
| Swap Exact Token... | 812030 | 1386 days ago | IN | 0 GLMR | 0.01162773 | ||||
| Swap ETH For Exa... | 812026 | 1386 days ago | IN | 0.00006451 GLMR | 0.01362069 | ||||
| Swap Exact Token... | 812023 | 1386 days ago | IN | 0 GLMR | 0.01237315 | ||||
| Swap ETH For Exa... | 812018 | 1386 days ago | IN | 0.0000435 GLMR | 0.0136217 | ||||
| Swap Exact Token... | 812011 | 1386 days ago | IN | 0 GLMR | 0.01237315 | ||||
| Swap Exact Token... | 812007 | 1386 days ago | IN | 0 GLMR | 0.01162773 | ||||
| Swap Exact Token... | 812003 | 1386 days ago | IN | 0 GLMR | 0.01163017 | ||||
| Swap Exact Token... | 812001 | 1386 days ago | IN | 0 GLMR | 0.0123695 | ||||
| Swap ETH For Exa... | 811983 | 1386 days ago | IN | 0.00000137 GLMR | 0.0136217 | ||||
| Swap Tokens For ... | 811975 | 1386 days ago | IN | 0 GLMR | 0.01215432 | ||||
| Remove Liquidity... | 811814 | 1386 days ago | IN | 0 GLMR | 0.01570611 | ||||
| Remove Liquidity | 811806 | 1386 days ago | IN | 0 GLMR | 0.01514938 | ||||
| Remove Liquidity | 811770 | 1386 days ago | IN | 0 GLMR | 0.01515232 | ||||
| Add Liquidity ET... | 811745 | 1386 days ago | IN | 0.00001 GLMR | 0.01244643 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 1083078 | 1346 days ago | 9.09914849 GLMR | ||||
| 1083078 | 1346 days ago | 9.09914849 GLMR | ||||
| 1078425 | 1347 days ago | 0.00000139 GLMR | ||||
| 1078425 | 1347 days ago | 6.0991485 GLMR | ||||
| 1078419 | 1347 days ago | 3 GLMR | ||||
| 815093 | 1385 days ago | 0.00017715 GLMR | ||||
| 815093 | 1385 days ago | 0.00017715 GLMR | ||||
| 812060 | 1386 days ago | 0.00003278 GLMR | ||||
| 812060 | 1386 days ago | 0.00003278 GLMR | ||||
| 812056 | 1386 days ago | 0.00000047 GLMR | ||||
| 812056 | 1386 days ago | 0.00004774 GLMR | ||||
| 812043 | 1386 days ago | 0.00000137 GLMR | ||||
| 812043 | 1386 days ago | 0.00000137 GLMR | ||||
| 812040 | 1386 days ago | 0 GLMR | ||||
| 812040 | 1386 days ago | 0.00000014 GLMR | ||||
| 812026 | 1386 days ago | 0.00002121 GLMR | ||||
| 812026 | 1386 days ago | 0.0000433 GLMR | ||||
| 812023 | 1386 days ago | 0.00004304 GLMR | ||||
| 812023 | 1386 days ago | 0.00004304 GLMR | ||||
| 812018 | 1386 days ago | 0.00000021 GLMR | ||||
| 812018 | 1386 days ago | 0.00004328 GLMR | ||||
| 812011 | 1386 days ago | 0.00009046 GLMR | ||||
| 812011 | 1386 days ago | 0.00009046 GLMR | ||||
| 812001 | 1386 days ago | 0 GLMR | ||||
| 812001 | 1386 days ago | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ImpossibleRouter
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
pragma experimental ABIEncoderV2;
import './libraries/TransferHelper.sol';
import './libraries/ReentrancyGuard.sol';
import './libraries/ImpossibleLibrary.sol';
import './libraries/SafeMath.sol';
import './interfaces/IImpossibleSwapFactory.sol';
import './interfaces/IImpossibleRouterExtension.sol';
import './interfaces/IImpossibleRouter.sol';
import './interfaces/IERC20.sol';
import './interfaces/IWETH.sol';
import './interfaces/IImpossibleWrappedToken.sol';
import './interfaces/IImpossibleWrapperFactory.sol';
/**
@title Router for Impossible Swap V3
@author Impossible Finance
@notice This router builds upon basic Uni V2 Router02 by allowing custom
calculations based on settings in pairs (uni/xybk/custom fees)
@dev See documentation at: https://docs.impossible.finance/impossible-swap/overview
@dev Very little logical changes made in Router02. Most changes to accomodate xybk are in Library
*/
contract ImpossibleRouter is IImpossibleRouter, ReentrancyGuard {
using SafeMath for uint256;
address public immutable override factory;
address public immutable override wrapFactory;
address private utilitySettingAdmin;
address public override routerExtension; // Can be set by utility setting admin once only
address public override WETH; // Can be set by utility setting admin once only
modifier ensure(uint256 deadline) {
require(deadline >= block.timestamp, 'ImpossibleRouter: EXPIRED');
_;
}
/**
@notice Constructor for IF Router
@param _pairFactory Address of IF Pair Factory
@param _wrapFactory Address of IF
@param _utilitySettingAdmin Admin address allowed to set addresses of utility contracts (once)
*/
constructor(
address _pairFactory,
address _wrapFactory,
address _utilitySettingAdmin
) {
factory = _pairFactory;
wrapFactory = _wrapFactory;
utilitySettingAdmin = _utilitySettingAdmin;
}
receive() external payable {
assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract
}
/**
@notice Used to set addresses of utility contracts
@dev Only allows setter to set these addresses once for trustlessness
@dev Must set both WETH and routerExtension at the same time, else swap will be bricked
@param _WETH address of WETH contract
@param _routerExtension address of router interface contract
*/
function setUtilities(address _WETH, address _routerExtension) public {
require(WETH == address(0x0) && routerExtension == address(0x0));
require(msg.sender == utilitySettingAdmin, 'IF: ?');
WETH = _WETH;
routerExtension = _routerExtension;
}
/**
@notice Helper function for sending tokens that might need to be wrapped
@param token The address of the token that might have a wrapper
@param src The source to take underlying tokens from
@param dst The destination to send wrapped tokens to
@param amt The amount of tokens to send (wrapped tokens, not underlying)
*/
function wrapSafeTransfer(
address token,
address src,
address dst,
uint256 amt
) internal {
address underlying = IImpossibleWrapperFactory(wrapFactory).wrappedTokensToTokens(token);
if (underlying == address(0x0)) {
TransferHelper.safeTransferFrom(token, src, dst, amt);
} else {
uint256 underlyingAmt = IImpossibleWrappedToken(token).amtToUnderlyingAmt(amt);
TransferHelper.safeTransferFrom(underlying, src, address(this), underlyingAmt);
TransferHelper.safeApprove(underlying, token, underlyingAmt);
IImpossibleWrappedToken(token).deposit(dst, underlyingAmt);
}
}
/**
@notice Helper function for sending tokens that might need to be unwrapped
@param token The address of the token that might be wrapped
@param dst The destination to send underlying tokens to
@param amt The amount of wrapped tokens to send (wrapped tokens, not underlying)
*/
function unwrapSafeTransfer(
address token,
address dst,
uint256 amt
) internal {
address underlying = IImpossibleWrapperFactory(wrapFactory).wrappedTokensToTokens(token);
if (underlying == address(0x0)) {
TransferHelper.safeTransfer(token, dst, amt);
} else {
IImpossibleWrappedToken(token).withdraw(dst, amt);
}
}
/**
@notice Swap function - receive maximum output given fixed input
@dev Openzeppelin reentrancy guards
@param amountIn The exact input amount`
@param amountOutMin The minimum output amount allowed for a successful swap
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
amounts = ImpossibleLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amounts[amounts.length - 1]);
}
/**
@notice Swap function - receive desired output amount given a maximum input amount
@dev Openzeppelin reentrancy guards
@param amountOut The exact output amount desired
@param amountInMax The maximum input amount allowed for a successful swap
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amountOut);
}
/**
@notice Swap function - receive maximum output given fixed input of ETH
@dev Openzeppelin reentrancy guards
@param amountOutMin The minimum output amount allowed for a successful swap
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsOut(factory, msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]));
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amounts[amounts.length - 1]);
}
/**
@notice Swap function - receive desired ETH output amount given a maximum input amount
@dev Openzeppelin reentrancy guards
@param amountOut The exact output amount desired
@param amountInMax The maximum input amount allowed for a successful swap
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
/**
@notice Swap function - receive maximum ETH output given fixed input of tokens
@dev Openzeppelin reentrancy guards
@param amountIn The amount of input tokens
@param amountOutMin The minimum ETH output amount required for successful swaps
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
/**
@notice Swap function - receive maximum tokens output given fixed ETH input
@dev Openzeppelin reentrancy guards
@param amountOut The minimum output amount in tokens required for successful swaps
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
@return amounts Array of actual output token amounts received per swap, sequentially.
*/
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= msg.value, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]));
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amountOut);
// refund dust eth, if any
if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
}
/**
@notice Swap function for fee on transfer tokens, no WETH/WBNB
@param amountIn The amount of input tokens
@param amountOutMin The minimum token output amount required for successful swaps
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
*/
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant {
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn);
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 balance = IERC20(path[path.length - 1]).balanceOf(address(this));
require(balance >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
unwrapSafeTransfer(path[path.length - 1], to, balance);
}
/**
@notice Swap function for fee on transfer tokens with WETH/WBNB
@param amountOutMin The minimum underlying token output amount required for successful swaps
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
*/
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
uint256 amountIn = msg.value;
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn));
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 balance = IERC20(path[path.length - 1]).balanceOf(address(this));
require(balance >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
unwrapSafeTransfer(path[path.length - 1], to, balance);
}
/**
@notice Swap function for fee on transfer tokens, no WETH/WBNB
@param amountIn The amount of input tokens
@param amountOutMin The minimum ETH output amount required for successful swaps
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@param to The address that receives the output tokens
@param deadline The block number after which this transaction is invalid
*/
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn);
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).withdraw(amountOut);
TransferHelper.safeTransferETH(to, amountOut);
}
/**
@notice Function for basic add liquidity functionality
@dev Openzeppelin reentrancy guards
@param tokenA The address of underlying tokenA to add
@param tokenB The address of underlying tokenB to add
@param amountADesired The desired amount of tokenA to add
@param amountBDesired The desired amount of tokenB to add
@param amountAMin The min amount of tokenA to add (amountAMin:amountBDesired sets bounds on ratio)
@param amountBMin The min amount of tokenB to add (amountADesired:amountBMin sets bounds on ratio)
@param to The address to mint LP tokens to
@param deadline The block number after which this transaction is invalid
@return amountA Amount of tokenA added as liquidity to pair
@return amountB Actual amount of tokenB added as liquidity to pair
@return liquidity Actual amount of LP tokens minted
*/
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
virtual
override
ensure(deadline)
nonReentrant
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
)
{
(amountA, amountB) = IImpossibleRouterExtension(routerExtension).addLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin
);
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
wrapSafeTransfer(tokenA, msg.sender, pair, amountA);
wrapSafeTransfer(tokenB, msg.sender, pair, amountB);
liquidity = IImpossiblePair(pair).mint(to);
}
/**
@notice Function for add liquidity functionality with 1 token being WETH/WBNB
@dev Openzeppelin reentrancy guards
@param token The address of the non-ETH underlying token to add
@param amountTokenDesired The desired amount of non-ETH underlying token to add
@param amountTokenMin The min amount of non-ETH underlying token to add (amountTokenMin:ETH sent sets bounds on ratio)
@param amountETHMin The min amount of WETH/WBNB to add (amountTokenDesired:amountETHMin sets bounds on ratio)
@param to The address to mint LP tokens to
@param deadline The block number after which this transaction is invalid
@return amountToken Amount of non-ETH underlying token added as liquidity to pair
@return amountETH Actual amount of WETH/WBNB added as liquidity to pair
@return liquidity Actual amount of LP tokens minted
*/
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
virtual
override
ensure(deadline)
nonReentrant
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
)
{
(amountToken, amountETH) = IImpossibleRouterExtension(routerExtension).addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
wrapSafeTransfer(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IImpossiblePair(pair).mint(to);
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); // refund dust eth, if any
}
/**
@notice Function for basic remove liquidity functionality
@dev Openzeppelin reentrancy guards
@param tokenA The address of underlying tokenA in LP token
@param tokenB The address of underlying tokenB in LP token
@param liquidity The amount of LP tokens to burn
@param amountAMin The min amount of underlying tokenA that has to be received
@param amountBMin The min amount of underlying tokenB that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@return amountA Actual amount of underlying tokenA received
@return amountB Actual amount of underlying tokenB received
*/
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountA, uint256 amountB) {
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(amountA, amountB) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
tokenA,
tokenB,
pair,
amountAMin,
amountBMin
);
unwrapSafeTransfer(tokenA, to, amountA);
unwrapSafeTransfer(tokenB, to, amountB);
}
/**
@notice Function for remove liquidity functionality with 1 token being WETH/WBNB
@dev Openzeppelin reentrancy guards
@param token The address of the non-ETH underlying token to receive
@param liquidity The amount of LP tokens to burn
@param amountTokenMin The desired amount of non-ETH underlying token that has to be received
@param amountETHMin The min amount of ETH that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@return amountToken Actual amount of non-ETH underlying token received
@return amountETH Actual amount of WETH/WBNB received
*/
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountToken, uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(amountToken, amountETH) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
token,
WETH,
pair,
amountTokenMin,
amountETHMin
);
unwrapSafeTransfer(token, to, amountToken);
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
/**
@notice Function for remove liquidity functionality using EIP712 permit
@dev Openzeppelin reentrancy guards
@param tokenA The address of underlying tokenA in LP token
@param tokenB The address of underlying tokenB in LP token
@param liquidity The amount of LP tokens to burn
@param amountAMin The min amount of underlying tokenA that has to be received
@param amountBMin The min amount of underlying tokenB that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@param approveMax How much tokens are approved for transfer (liquidity, or max)
@param v,r,s Variables that construct a valid EVM signature
@return amountA Actual amount of underlying tokenA received
@return amountB Actual amount of underlying tokenB received
*/
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountA, uint256 amountB) {
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
return removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline);
}
/**
@notice Function for remove liquidity functionality using EIP712 permit with 1 token being WETH/WBNB
@param token The address of the non-ETH underlying token to receive
@param liquidity The amount of LP tokens to burn
@param amountTokenMin The desired amount of non-ETH underlying token that has to be received
@param amountETHMin The min amount of ETH that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@param approveMax How much tokens are approved for transfer (liquidity, or max)
@param v,r,s Variables that construct a valid EVM signature
@return amountToken Actual amount of non-ETH underlying token received
@return amountETH Actual amount of WETH/WBNB received
*/
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountToken, uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline);
}
/**
@notice Function for remove liquidity functionality with 1 token being WETH/WBNB
@dev This is used when non-WETH/WBNB underlying token is fee-on-transfer: e.g. FEI algo stable v1
@dev Openzeppelin reentrancy guards
@param token The address of the non-ETH underlying token to receive
@param liquidity The amount of LP tokens to burn
@param amountTokenMin The desired amount of non-ETH underlying token that has to be received
@param amountETHMin The min amount of ETH that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@return amountETH Actual amount of WETH/WBNB received
*/
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(, amountETH) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
token,
WETH,
pair,
amountTokenMin,
amountETHMin
);
unwrapSafeTransfer(token, to, IERC20(token).balanceOf(address(this)));
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
/**
@notice Function for remove liquidity functionality using EIP712 permit with 1 token being WETH/WBNB
@dev This is used when non-WETH/WBNB underlying token is fee-on-transfer: e.g. FEI algo stable v1
@param token The address of the non-ETH underlying token to receive
@param liquidity The amount of LP tokens to burn
@param amountTokenMin The desired amount of non-ETH underlying token that has to be received
@param amountETHMin The min amount of ETH that has to be received
@param to The address to send underlying tokens to
@param deadline The block number after which this transaction is invalid
@param approveMax How much tokens are approved for transfer (liquidity, or max)
@param v,r,s Variables that construct a valid EVM signature
@return amountETH Actual amount of WETH/WBNB received
*/
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
amountETH = removeLiquidityETHSupportingFeeOnTransferTokens(
token,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.6.0;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeApprove: approve failed'
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeTransfer: transfer failed'
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::transferFrom: transferFrom failed'
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, 'ReentrancyGuard: reentrant call');
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}/// SPDX-License-Identifier: GPL-3
pragma solidity >=0.5.0;
import '../interfaces/IImpossiblePair.sol';
import '../interfaces/IERC20.sol';
import './SafeMath.sol';
import './Math.sol';
library ImpossibleLibrary {
using SafeMath for uint256;
/**
@notice Sorts tokens in ascending order
@param tokenA The address of token A
@param tokenB The address of token B
@return token0 The address of token 0 (lexicographically smaller than addr of token 1)
@return token1 The address of token 1 (lexicographically larger than addr of token 0)
*/
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'ImpossibleLibrary: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'ImpossibleLibrary: ZERO_ADDRESS');
}
/**
@notice Computes the pair contract create2 address deterministically
@param factory The address of the token factory (pair contract deployer)
@param tokenA The address of token A
@param tokenB The address of token B
@return pair The address of the pair containing token A and B
*/
function pairFor(
address factory,
address tokenA,
address tokenB
) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'fc84b622ba228c468b74c2d99bfe9454ffac280ac017f05a02feb9f739aeb1e4' // init code hash
)
)
)
);
}
/**
@notice Obtains the token reserves in the pair contract
@param factory The address of the token factory (pair contract deployer)
@param tokenA The address of token A
@param tokenB The address of token B
@return reserveA The amount of token A in reserves
@return reserveB The amount of token B in reserves
@return pair The address of the pair containing token A and B
*/
function getReserves(
address factory,
address tokenA,
address tokenB
)
internal
view
returns (
uint256 reserveA,
uint256 reserveB,
address pair
)
{
(address token0, ) = sortTokens(tokenA, tokenB);
pair = pairFor(factory, tokenA, tokenB);
(uint256 reserve0, uint256 reserve1) = IImpossiblePair(pair).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
/**
@notice Quote returns amountB based on some amountA, in the ratio of reserveA:reserveB
@param amountA The amount of token A
@param reserveA The amount of reserveA
@param reserveB The amount of reserveB
@return amountB The amount of token B that matches amount A in the ratio of reserves
*/
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) internal pure returns (uint256 amountB) {
require(amountA > 0, 'ImpossibleLibrary: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'ImpossibleLibrary: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
/**
@notice Internal function to compute the K value for an xybk pair based on token balances and boost
@dev More details on math at: https://docs.impossible.finance/impossible-swap/swap-math
@dev Implementation is the same as in pair
@param boost0 Current boost0 in pair
@param boost1 Current boost1 in pair
@param balance0 Current state of balance0 in pair
@param balance1 Current state of balance1 in pair
@return k Value of K invariant
*/
function xybkComputeK(
uint256 boost0,
uint256 boost1,
uint256 balance0,
uint256 balance1
) internal pure returns (uint256 k) {
uint256 boost = (balance0 > balance1) ? boost0.sub(1) : boost1.sub(1);
uint256 denom = boost.mul(2).add(1); // 1+2*boost
uint256 term = boost.mul(balance0.add(balance1)).div(denom.mul(2)); // boost*(x+y)/(2+4*boost)
k = (Math.sqrt(term**2 + balance0.mul(balance1).div(denom)) + term)**2;
}
/**
@notice Internal helper function for calculating artificial liquidity
@dev More details on math at: https://docs.impossible.finance/impossible-swap/swap-math
@param _boost The boost variable on the correct side for the pair contract
@param _sqrtK The sqrt of the invariant variable K in xybk formula
@return uint256 The artificial liquidity term
*/
function calcArtiLiquidityTerm(uint256 _boost, uint256 _sqrtK) internal pure returns (uint256) {
return (_boost - 1).mul(_sqrtK);
}
/**
@notice Quotes maximum output given exact input amount of tokens and addresses of tokens in pair
@dev The library function considers custom swap fees/invariants/asymmetric tuning of pairs
@dev However, library function doesn't consider limits created by hardstops
@param amountIn The input amount of token A
@param tokenIn The address of input token
@param tokenOut The address of output token
@param factory The address of the factory contract
@return amountOut The maximum output amount of token B for a valid swap
*/
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256 amountOut) {
require(amountIn > 0, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
uint256 reserveIn;
uint256 reserveOut;
uint256 amountInPostFee;
address pair;
bool isMatch;
{
// Avoid stack too deep
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut);
}
uint256 artiLiqTerm;
bool isXybk;
{
// Avoid stack too deep
uint256 fee;
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
amountInPostFee = amountIn.mul(10000 - fee);
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
}
/// If xybk invariant, set reserveIn/reserveOut to artificial liquidity instead of actual liquidity
if (isXybk) {
(uint256 boost0, uint256 boost1) = IImpossiblePair(pair).calcBoost();
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
/// since balance0=balance1 only at sqrtK, if final balanceIn >= sqrtK means balanceIn >= balanceOut
/// Use post-fee balances to maintain consistency with pair contract K invariant check
if (amountInPostFee.add(reserveIn.mul(10000)) >= sqrtK.mul(10000)) {
/// If tokenIn = token0, balanceIn > sqrtK => balance0>sqrtK, use boost0
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
/// If balance started from <sqrtK and ended at >sqrtK and boosts are different, there'll be different amountIn/Out
/// Don't need to check in other case for reserveIn < reserveIn.add(x) <= sqrtK since that case doesnt cross midpt
if (reserveIn < sqrtK && boost0 != boost1) {
/// Break into 2 trades => start point -> midpoint (sqrtK, sqrtK), then midpoint -> final point
amountOut = reserveOut.sub(sqrtK);
amountInPostFee = amountInPostFee.sub((sqrtK.sub(reserveIn)).mul(10000));
reserveIn = sqrtK;
reserveOut = sqrtK;
}
} else {
/// If tokenIn = token0, balanceIn < sqrtK => balance0<sqrtK, use boost1
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
}
}
uint256 numerator = amountInPostFee.mul(reserveOut.add(artiLiqTerm));
uint256 denominator = (reserveIn.add(artiLiqTerm)).mul(10000).add(amountInPostFee);
uint256 lastSwapAmountOut = numerator / denominator;
amountOut = (lastSwapAmountOut > reserveOut) ? reserveOut.add(amountOut) : lastSwapAmountOut.add(amountOut);
}
/**
@notice Quotes minimum input given exact output amount of tokens and addresses of tokens in pair
@dev The library function considers custom swap fees/invariants/asymmetric tuning of pairs
@dev However, library function doesn't consider limits created by hardstops
@param amountOut The desired output amount of token A
@param tokenIn The address of input token
@param tokenOut The address of output token
@param factory The address of the factory contract
@return amountIn The minimum input amount of token A for a valid swap
*/
function getAmountIn(
uint256 amountOut,
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256 amountIn) {
require(amountOut > 0, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
uint256 reserveIn;
uint256 reserveOut;
uint256 artiLiqTerm;
uint256 fee;
bool isMatch;
{
// Avoid stack too deep
bool isXybk;
uint256 boost0;
uint256 boost1;
{
// Avoid stack too deep
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
}
{
// Avoid stack too deep
address pair;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut);
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
(boost0, boost1) = IImpossiblePair(pair).calcBoost();
}
if (isXybk) {
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
/// since balance0=balance1 only at sqrtK, if final balanceOut >= sqrtK means balanceOut >= balanceIn
if (reserveOut.sub(amountOut) >= sqrtK) {
/// If tokenIn = token0, balanceOut > sqrtK => balance1>sqrtK, use boost1
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
} else {
/// If tokenIn = token0, balanceOut < sqrtK => balance0>sqrtK, use boost0
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
/// If balance started from <sqrtK and ended at >sqrtK and boosts are different, there'll be different amountIn/Out
/// Don't need to check in other case for reserveOut > reserveOut.sub(x) >= sqrtK since that case doesnt cross midpt
if (reserveOut > sqrtK && boost0 != boost1) {
/// Break into 2 trades => start point -> midpoint (sqrtK, sqrtK), then midpoint -> final point
amountIn = sqrtK.sub(reserveIn).mul(10000); /// Still need to divide by (10000 - fee). Do with below calculation to prevent early truncation
amountOut = amountOut.sub(reserveOut.sub(sqrtK));
reserveOut = sqrtK;
reserveIn = sqrtK;
}
}
}
}
uint256 numerator = (reserveIn.add(artiLiqTerm)).mul(amountOut).mul(10000);
uint256 denominator = (reserveOut.add(artiLiqTerm)).sub(amountOut);
amountIn = (amountIn.add((numerator / denominator)).div(10000 - fee)).add(1);
}
/**
@notice Quotes maximum output given some uncertain input amount of tokens and addresses of tokens in pair
@dev The library function considers custom swap fees/invariants/asymmetric tuning of pairs
@dev However, library function doesn't consider limits created by hardstops
@param tokenIn The address of input token
@param tokenOut The address of output token
@param factory The address of the factory contract
@return uint256 The maximum possible output amount of token A
@return uint256 The maximum possible output amount of token B
*/
function getAmountOutFeeOnTransfer(
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256, uint256) {
uint256 reserveIn;
uint256 reserveOut;
address pair;
bool isMatch;
{
// Avoid stack too deep
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut); /// Should be reserve0/1 but reuse variables to save stack
}
uint256 amountOut;
uint256 artiLiqTerm;
uint256 amountInPostFee;
bool isXybk;
{
// Avoid stack too deep
uint256 fee;
uint256 balanceIn = IERC20(tokenIn).balanceOf(address(pair));
require(balanceIn > reserveIn, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
amountInPostFee = (balanceIn.sub(reserveIn)).mul(10000 - fee);
}
/// If xybk invariant, set reserveIn/reserveOut to artificial liquidity instead of actual liquidity
if (isXybk) {
(uint256 boost0, uint256 boost1) = IImpossiblePair(pair).calcBoost();
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
/// since balance0=balance1 only at sqrtK, if final balanceIn >= sqrtK means balanceIn >= balanceOut
/// Use post-fee balances to maintain consistency with pair contract K invariant check
if (amountInPostFee.add(reserveIn.mul(10000)) >= sqrtK.mul(10000)) {
/// If tokenIn = token0, balanceIn > sqrtK => balance0>sqrtK, use boost0
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
/// If balance started from <sqrtK and ended at >sqrtK and boosts are different, there'll be different amountIn/Out
/// Don't need to check in other case for reserveIn < reserveIn.add(x) <= sqrtK since that case doesnt cross midpt
if (reserveIn < sqrtK && boost0 != boost1) {
/// Break into 2 trades => start point -> midpoint (sqrtK, sqrtK), then midpoint -> final point
amountOut = reserveOut.sub(sqrtK);
amountInPostFee = amountInPostFee.sub(sqrtK.sub(reserveIn));
reserveOut = sqrtK;
reserveIn = sqrtK;
}
} else {
/// If tokenIn = token0, balanceIn < sqrtK => balance0<sqrtK, use boost0
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
}
}
uint256 numerator = amountInPostFee.mul(reserveOut.add(artiLiqTerm));
uint256 denominator = (reserveIn.add(artiLiqTerm)).mul(10000).add(amountInPostFee);
uint256 lastSwapAmountOut = numerator / denominator;
amountOut = (lastSwapAmountOut > reserveOut) ? reserveOut.add(amountOut) : lastSwapAmountOut.add(amountOut);
return isMatch ? (uint256(0), amountOut) : (amountOut, uint256(0));
}
/**
@notice Quotes maximum output given exact input amount of tokens and addresses of tokens in trade sequence
@dev The library function considers custom swap fees/invariants/asymmetric tuning of pairs
@dev However, library function doesn't consider limits created by hardstops
@param factory The address of the IF factory
@param amountIn The input amount of token A
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@return amounts The maximum possible output amount of all tokens through sequential swaps
*/
function getAmountsOut(
address factory,
uint256 amountIn,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'ImpossibleLibrary: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
amounts[i + 1] = getAmountOut(amounts[i], path[i], path[i + 1], factory);
}
}
/**
@notice Quotes minimum input given exact output amount of tokens and addresses of tokens in trade sequence
@dev The library function considers custom swap fees/invariants/asymmetric tuning of pairs
@dev However, library function doesn't consider limits created by hardstops
@param factory The address of the IF factory
@param amountOut The output amount of token A
@param path[] An array of token addresses. Trades are made from arr idx 0 to arr end idx sequentially
@return amounts The minimum output amount required of all tokens through sequential swaps
*/
function getAmountsIn(
address factory,
uint256 amountOut,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'ImpossibleLibrary: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
amounts[i - 1] = getAmountIn(amounts[i], path[i - 1], path[i], factory);
}
}
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, 'SafeMath: division by zero');
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
interface IImpossibleSwapFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
event UpdatedGovernance(address governance);
function feeTo() external view returns (address);
function governance() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setGovernance(address) external;
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
import './IImpossiblePair.sol';
interface IImpossibleRouterExtension {
function factory() external returns (address factoryAddr);
function swap(uint256[] memory amounts, address[] memory path) external;
function swapSupportingFeeOnTransferTokens(address[] memory path) external;
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidity(
address tokenA,
address tokenB,
address pair,
uint256 amountAMin,
uint256 amountBMin
) external returns (uint256 amountA, uint256 amountB);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut
) external view returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
address tokenIn,
address tokenOut
) external view returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
}// SPDX-License-Identifier: GPL-3
pragma solidity >=0.6.2;
interface IImpossibleRouter {
function factory() external view returns (address factoryAddr);
function routerExtension() external view returns (address routerExtensionAddr);
function wrapFactory() external view returns (address wrapFactoryAddr);
function WETH() external view returns (address WETHAddr);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}// SPDX-License-Identifier: GPL-3
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
import './IERC20.sol';
interface IImpossibleWrappedToken is IERC20 {
function deposit(address, uint256) external returns (uint256);
function withdraw(address, uint256) external returns (uint256);
function amtToUnderlyingAmt(uint256) external returns (uint256);
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
interface IImpossibleWrapperFactory {
event WrapCreated(address, address, uint256, uint256);
event WrapDeleted(address, address);
function tokensToWrappedTokens(address) external view returns (address);
function wrappedTokensToTokens(address) external view returns (address);
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
import './IImpossibleERC20.sol';
interface IImpossiblePair is IImpossibleERC20 {
enum TradeState {
SELL_ALL,
SELL_TOKEN_0,
SELL_TOKEN_1,
SELL_NONE
}
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint256 reserve0, uint256 reserve1);
event ChangeInvariant(bool _isXybk, uint256 _newBoost0, uint256 _newBoost1);
event UpdatedTradeFees(uint256 _oldFee, uint256 _newFee);
event UpdatedDelay(uint256 _oldDelay, uint256 _newDelay);
event UpdatedTradeState(TradeState _tradeState);
event UpdatedWithdrawalFeeRatio(uint256 _oldWithdrawalFee, uint256 _newWithdrawalFee);
event UpdatedBoost(
uint32 _oldBoost0,
uint32 _oldBoost1,
uint32 _newBoost0,
uint32 _newBoost1,
uint256 _start,
uint256 _end
);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
function factory() external view returns (address);
function token0() external view returns (address); // address of token0
function token1() external view returns (address); // address of token1
function getReserves() external view returns (uint256, uint256); // reserves of token0/token1
function calcBoost() external view returns (uint256, uint256);
function mint(address) external returns (uint256);
function burn(address) external returns (uint256, uint256);
function swap(
uint256,
uint256,
address,
bytes calldata
) external;
function skim(address to) external;
function sync() external;
function getPairSettings()
external
view
returns (
uint16,
TradeState,
bool
); // Uses single storage slot, save gas
function delay() external view returns (uint256); // Amount of time delay required before any change to boost etc, denoted in seconds
function initialize(
address,
address,
address,
address
) external;
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
// a library for performing various math operations
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}// SPDX-License-Identifier: GPL-3
pragma solidity =0.7.6;
interface IImpossibleERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_wrapFactory","type":"address"},{"internalType":"address","name":"_utilitySettingAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerExtension","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_routerExtension","type":"address"}],"name":"setUtilities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrapFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004a8238038062004a82833981016040819052620000349162000096565b60016000819055606093841b6001600160601b03199081166080529290931b90911660a05281546001600160a01b0319166001600160a01b03909116179055620000df565b80516001600160a01b03811681146200009157600080fd5b919050565b600080600060608486031215620000ab578283fd5b620000b68462000079565b9250620000c66020850162000079565b9150620000d66040850162000079565b90509250925092565b60805160601c60a05160601c61491062000172600039806104085280612a625280612dda5250806104ad528061074b528061080852806109a85280610ae95280610d035280610daf5280610f1852806113e452806114fd52806116b1528061186f5280611bf85280611e675280611fce528061200052806121db52806123c552806126eb528061280152506149106000f3fe6080604052600436106101395760003560e01c80638803dbee116100ab578063c45a01551161006f578063c45a01551461035c578063ded9382a14610371578063e8e3370014610391578063f305d719146103c0578063fa7de13b146103d3578063fb3bdb41146103f357610154565b80638803dbee146102d4578063ad5c4648146102f4578063af2979eb14610309578063b6f9de9514610329578063baa2abde1461033c57610154565b80634a25d94a116100fd5780634a25d94a1461021f578063590c61f01461023f5780635b0d5984146102545780635c11d79514610281578063791ac947146102a15780637ff36ab5146102c157610154565b8063017e2d551461015957806302751cec1461018457806318cbafe5146101b25780632195995c146101df57806338ed1739146101ff57610154565b36610154576003546001600160a01b0316331461015257fe5b005b600080fd5b34801561016557600080fd5b5061016e610406565b60405161017b91906144b8565b60405180910390f35b34801561019057600080fd5b506101a461019f366004614222565b61042a565b60405161017b92919061473d565b3480156101be57600080fd5b506101d26101cd3660046143d0565b610681565b60405161017b91906145d0565b3480156101eb57600080fd5b506101a46101fa3660046140fe565b61099e565b34801561020b57600080fd5b506101d261021a3660046143d0565b610a73565b34801561022b57600080fd5b506101d261023a3660046143d0565b610c39565b34801561024b57600080fd5b5061016e610d92565b34801561026057600080fd5b5061027461026f36600461427f565b610da1565b60405161017b9190614734565b34801561028d57600080fd5b5061015261029c3660046143d0565b610e7e565b3480156102ad57600080fd5b506101526102bc3660046143d0565b6110d4565b6101d26102cf366004614348565b61131c565b3480156102e057600080fd5b506101d26102ef3660046143d0565b61163b565b34801561030057600080fd5b5061016e6117e7565b34801561031557600080fd5b50610274610324366004614222565b6117f6565b610152610337366004614348565b611abd565b34801561034857600080fd5b506101a461035736600461408d565b611df1565b34801561036857600080fd5b5061016e611fcc565b34801561037d57600080fd5b506101a461038c36600461427f565b611ff0565b34801561039d57600080fd5b506103b16103ac3660046141a7565b6120d3565b60405161017b9392919061474b565b6103b16103ce366004614222565b6122b3565b3480156103df57600080fd5b506101526103ee366004614055565b6125a0565b6101d2610401366004614348565b612623565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008082428110156104575760405162461bcd60e51b815260040161044e906146fd565b60405180910390fd5b6002600054141561049d576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546104dd907f0000000000000000000000000000000000000000000000000000000000000000908c906001600160a01b0316612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd9061051090339085908e9060040161450d565b602060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105629190614314565b5060025460035460405163e54dc2d760e01b81526001600160a01b039283169263e54dc2d7926105a0928f929091169086908e908e90600401614531565b6040805180830381600087803b1580156105b957600080fd5b505af11580156105cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f191906143ad565b90945092506106018a8786612a48565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d90610631908690600401614734565b600060405180830381600087803b15801561064b57600080fd5b505af115801561065f573d6000803e3d6000fd5b5050505061066d8684612b8f565b505060016000559097909650945050505050565b606081428110156106a45760405162461bcd60e51b815260040161044e906146fd565b600260005414156106ea576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b03168686600019810181811061070b57fe5b9050602002016020810190610720919061401d565b6001600160a01b0316146107465760405162461bcd60e51b815260040161044e906146c6565b6107a47f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b915086826001845103815181106107b757fe5b602002602001015110156107dd5760405162461bcd60e51b815260040161044e9061467a565b61088a868660008181106107ed57fe5b9050602002016020810190610802919061401d565b336108707f00000000000000000000000000000000000000000000000000000000000000008a8a600081811061083457fe5b9050602002016020810190610849919061401d565b8b8b600181811061085657fe5b905060200201602081019061086b919061401d565b612988565b8560008151811061087d57fe5b6020026020010151612dc0565b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906108be9085908a908a906004016145e3565b600060405180830381600087803b1580156108d857600080fd5b505af11580156108ec573d6000803e3d6000fd5b505060035484516001600160a01b039091169250632e1a7d4d91508490600019810190811061091757fe5b60200260200101516040518263ffffffff1660e01b815260040161093b9190614734565b600060405180830381600087803b15801561095557600080fd5b505af1158015610969573d6000803e3d6000fd5b5050505061098e848360018551038151811061098157fe5b6020026020010151612b8f565b5060016000559695505050505050565b60008060006109ce7f00000000000000000000000000000000000000000000000000000000000000008f8f612988565b90506000876109dd578c6109e1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610a1c903390309086908f908e908e908e906004016144cc565b600060405180830381600087803b158015610a3657600080fd5b505af1158015610a4a573d6000803e3d6000fd5b50505050610a5d8f8f8f8f8f8f8f611df1565b9350935050509b509b9950505050505050505050565b60608142811015610a965760405162461bcd60e51b815260040161044e906146fd565b60026000541415610adc576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905550610b427f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b91508682600184510381518110610b5557fe5b60200260200101511015610b7b5760405162461bcd60e51b815260040161044e9061467a565b610b8b868660008181106107ed57fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d98490610bbf9085908a908a906004016145e3565b600060405180830381600087803b158015610bd957600080fd5b505af1158015610bed573d6000803e3d6000fd5b5050505061098e868660018989905003818110610c0657fe5b9050602002016020810190610c1b919061401d565b8584600186510381518110610c2c57fe5b6020026020010151612a48565b60608142811015610c5c5760405162461bcd60e51b815260040161044e906146fd565b60026000541415610ca2576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b031686866000198101818110610cc357fe5b9050602002016020810190610cd8919061401d565b6001600160a01b031614610cfe5760405162461bcd60e51b815260040161044e906146c6565b610d5c7f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b91508682600081518110610d6c57fe5b602002602001015111156107dd5760405162461bcd60e51b815260040161044e90614632565b6002546001600160a01b031681565b6003546000908190610ddf907f0000000000000000000000000000000000000000000000000000000000000000908e906001600160a01b0316612988565b9050600086610dee578b610df2565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e2d903390309086908e908d908d908d906004016144cc565b600060405180830381600087803b158015610e4757600080fd5b505af1158015610e5b573d6000803e3d6000fd5b50505050610e6d8d8d8d8d8d8d6117f6565b9d9c50505050505050505050505050565b8042811015610e9f5760405162461bcd60e51b815260040161044e906146fd565b60026000541415610ee5576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905550610f6c85856000818110610efd57fe5b9050602002016020810190610f12919061401d565b33610f667f000000000000000000000000000000000000000000000000000000000000000089896000818110610f4457fe5b9050602002016020810190610f59919061401d565b8a8a600181811061085657fe5b8a612dc0565b600254604051636fb0847760e01b81526001600160a01b0390911690636fb0847790610f9e90889088906004016145b4565b600060405180830381600087803b158015610fb857600080fd5b505af1158015610fcc573d6000803e3d6000fd5b505050506000858560018888905003818110610fe457fe5b9050602002016020810190610ff9919061401d565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161102491906144b8565b60206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190614330565b9050868110156110965760405162461bcd60e51b815260040161044e9061467a565b6110c5868660001981018181106110a957fe5b90506020020160208101906110be919061401d565b8583612a48565b50506001600055505050505050565b80428110156110f55760405162461bcd60e51b815260040161044e906146fd565b6002600054141561113b576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b03168585600019810181811061115c57fe5b9050602002016020810190611171919061401d565b6001600160a01b0316146111975760405162461bcd60e51b815260040161044e906146c6565b6111a785856000818110610efd57fe5b600254604051636fb0847760e01b81526001600160a01b0390911690636fb08477906111d990889088906004016145b4565b600060405180830381600087803b1580156111f357600080fd5b505af1158015611207573d6000803e3d6000fd5b50506003546040516370a0823160e01b8152600093506001600160a01b0390911691506370a082319061123e9030906004016144b8565b60206040518083038186803b15801561125657600080fd5b505afa15801561126a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128e9190614330565b9050868110156112b05760405162461bcd60e51b815260040161044e9061467a565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d906112e0908490600401614734565b600060405180830381600087803b1580156112fa57600080fd5b505af115801561130e573d6000803e3d6000fd5b505050506110c58482612b8f565b6060814281101561133f5760405162461bcd60e51b815260040161044e906146fd565b60026000541415611385576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b03169087908790816113a457fe5b90506020020160208101906113b9919061401d565b6001600160a01b0316146113df5760405162461bcd60e51b815260040161044e906146c6565b61143d7f000000000000000000000000000000000000000000000000000000000000000034888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b9150868260018451038151811061145057fe5b602002602001015110156114765760405162461bcd60e51b815260040161044e9061467a565b60035482516001600160a01b039091169063d0e30db090849060009061149857fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156114cb57600080fd5b505af11580156114df573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb915061152790507f00000000000000000000000000000000000000000000000000000000000000008989600081610f4457fe5b8460008151811061153457fe5b60200260200101516040518363ffffffff1660e01b815260040161155992919061459b565b602060405180830381600087803b15801561157357600080fd5b505af1158015611587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ab9190614314565b6115b157fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906115e59085908a908a906004016145e3565b600060405180830381600087803b1580156115ff57600080fd5b505af1158015611613573d6000803e3d6000fd5b5050505061162c868660018989905003818110610c0657fe5b50600160005595945050505050565b6060814281101561165e5760405162461bcd60e51b815260040161044e906146fd565b600260005414156116a4576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260008190555061170a7f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b9150868260008151811061171a57fe5b602002602001015111156117405760405162461bcd60e51b815260040161044e90614632565b611750868660008181106107ed57fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906117849085908a908a906004016145e3565b600060405180830381600087803b15801561179e57600080fd5b505af11580156117b2573d6000803e3d6000fd5b5050505061098e8686600189899050038181106117cb57fe5b90506020020160208101906117e0919061401d565b858a612a48565b6003546001600160a01b031681565b600081428110156118195760405162461bcd60e51b815260040161044e906146fd565b6002600054141561185f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600090815560035461189f907f0000000000000000000000000000000000000000000000000000000000000000908b906001600160a01b0316612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd906118d290339085908d9060040161450d565b602060405180830381600087803b1580156118ec57600080fd5b505af1158015611900573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119249190614314565b5060025460035460405163e54dc2d760e01b81526001600160a01b039283169263e54dc2d792611962928e929091169086908d908d90600401614531565b6040805180830381600087803b15801561197b57600080fd5b505af115801561198f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b391906143ad565b6040516370a0823160e01b8152909450611a4091508a9087906001600160a01b038316906370a08231906119eb9030906004016144b8565b60206040518083038186803b158015611a0357600080fd5b505afa158015611a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3b9190614330565b612a48565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d90611a70908690600401614734565b600060405180830381600087803b158015611a8a57600080fd5b505af1158015611a9e573d6000803e3d6000fd5b50505050611aac8584612b8f565b505060016000559695505050505050565b8042811015611ade5760405162461bcd60e51b815260040161044e906146fd565b60026000541415611b24576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b0316908690869081611b4357fe5b9050602002016020810190611b58919061401d565b6001600160a01b031614611b7e5760405162461bcd60e51b815260040161044e906146c6565b60035460408051630d0e30db60e41b8152905134926001600160a01b03169163d0e30db091849160048082019260009290919082900301818588803b158015611bc657600080fd5b505af1158015611bda573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb9150611c2290507f00000000000000000000000000000000000000000000000000000000000000008989600081610f4457fe5b836040518363ffffffff1660e01b8152600401611c4092919061459b565b602060405180830381600087803b158015611c5a57600080fd5b505af1158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c929190614314565b611c9857fe5b600254604051636fb0847760e01b81526001600160a01b0390911690636fb0847790611cca90899089906004016145b4565b600060405180830381600087803b158015611ce457600080fd5b505af1158015611cf8573d6000803e3d6000fd5b505050506000868660018989905003818110611d1057fe5b9050602002016020810190611d25919061401d565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611d5091906144b8565b60206040518083038186803b158015611d6857600080fd5b505afa158015611d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da09190614330565b905087811015611dc25760405162461bcd60e51b815260040161044e9061467a565b6110c587876000198101818110611dd557fe5b9050602002016020810190611dea919061401d565b8683612a48565b6000808242811015611e155760405162461bcd60e51b815260040161044e906146fd565b60026000541415611e5b576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000908155611e8d7f00000000000000000000000000000000000000000000000000000000000000008c8c612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd90611ec090339085908e9060040161450d565b602060405180830381600087803b158015611eda57600080fd5b505af1158015611eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f129190614314565b5060025460405163e54dc2d760e01b81526001600160a01b039091169063e54dc2d790611f4b908e908e9086908e908e90600401614531565b6040805180830381600087803b158015611f6457600080fd5b505af1158015611f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9c91906143ad565b9094509250611fac8b8786612a48565b611fb78a8785612a48565b50506001600055909890975095505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60035460009081908190612030907f0000000000000000000000000000000000000000000000000000000000000000908f906001600160a01b0316612988565b905060008761203f578c612043565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf9061207e903390309086908f908e908e908e906004016144cc565b600060405180830381600087803b15801561209857600080fd5b505af11580156120ac573d6000803e3d6000fd5b505050506120be8e8e8e8e8e8e61042a565b909f909e509c50505050505050505050505050565b600080600083428110156120f95760405162461bcd60e51b815260040161044e906146fd565b6002600054141561213f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905554604051633351733f60e01b81526001600160a01b0390911690633351733f9061217e908f908f908f908f908f908f90600401614565565b6040805180830381600087803b15801561219757600080fd5b505af11580156121ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cf91906143ad565b909450925060006122017f00000000000000000000000000000000000000000000000000000000000000008e8e612988565b905061220f8d338388612dc0565b61221b8c338387612dc0565b6040516335313c2160e11b81526001600160a01b03821690636a62784290612247908a906004016144b8565b602060405180830381600087803b15801561226157600080fd5b505af1158015612275573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122999190614330565b925050600160008190555050985098509895505050505050565b600080600083428110156122d95760405162461bcd60e51b815260040161044e906146fd565b6002600054141561231f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905554600354604051633351733f60e01b81526001600160a01b0392831692633351733f92612363928f92909116908e9034908f908f90600401614565565b6040805180830381600087803b15801561237c57600080fd5b505af1158015612390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b491906143ad565b60035491955093506000906123f5907f0000000000000000000000000000000000000000000000000000000000000000908d906001600160a01b0316612988565b90506124038b338388612dc0565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505060035460405163a9059cbb60e01b81526001600160a01b03909116935063a9059cbb925061249e91508490889060040161459b565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190614314565b6124f657fe5b6040516335313c2160e11b81526001600160a01b03821690636a62784290612522908a906004016144b8565b602060405180830381600087803b15801561253c57600080fd5b505af1158015612550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125749190614330565b92508334111561258a5761258a33853403612b8f565b5060016000819055505096509650969350505050565b6003546001600160a01b03161580156125c257506002546001600160a01b0316155b6125cb57600080fd5b6001546001600160a01b031633146125f55760405162461bcd60e51b815260040161044e90614613565b600380546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b606081428110156126465760405162461bcd60e51b815260040161044e906146fd565b6002600054141561268c576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b03169087908790816126ab57fe5b90506020020160208101906126c0919061401d565b6001600160a01b0316146126e65760405162461bcd60e51b815260040161044e906146c6565b6127447f000000000000000000000000000000000000000000000000000000000000000088888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b9150348260008151811061275457fe5b6020026020010151111561277a5760405162461bcd60e51b815260040161044e90614632565b60035482516001600160a01b039091169063d0e30db090849060009061279c57fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156127cf57600080fd5b505af11580156127e3573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb915061282b90507f00000000000000000000000000000000000000000000000000000000000000008989600081610f4457fe5b8460008151811061283857fe5b60200260200101516040518363ffffffff1660e01b815260040161285d92919061459b565b602060405180830381600087803b15801561287757600080fd5b505af115801561288b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128af9190614314565b6128b557fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906128e99085908a908a906004016145e3565b600060405180830381600087803b15801561290357600080fd5b505af1158015612917573d6000803e3d6000fd5b5050505061294c86866001898990500381811061293057fe5b9050602002016020810190612945919061401d565b8589612a48565b8160008151811061295957fe5b602002602001015134111561162c5761162c338360008151811061297957fe5b60200260200101513403612b8f565b600080600061299785856130d5565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501206001600160f81b031960688401529a90941b9093166069840152607d8301989098527ffc84b622ba228c468b74c2d99bfe9454ffac280ac017f05a02feb9f739aeb1e4609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b604051632a4d95e760e21b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a936579c90612a979087906004016144b8565b60206040518083038186803b158015612aaf57600080fd5b505afa158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190614039565b90506001600160a01b038116612b0757612b028484846131b3565b612b89565b60405163f3fef3a360e01b81526001600160a01b0385169063f3fef3a390612b35908690869060040161459b565b602060405180830381600087803b158015612b4f57600080fd5b505af1158015612b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b879190614330565b505b50505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b60208310612bdb5780518252601f199092019160209182019101612bbc565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612c3d576040519150601f19603f3d011682016040523d82523d6000602084013e612c42565b606091505b5050905080612c825760405162461bcd60e51b81526004018080602001828103825260348152602001806148056034913960400191505060405180910390fd5b505050565b6060600282511015612ce0576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a20494e56414c49445f5041544800604482015290519081900360640190fd5b815167ffffffffffffffff81118015612cf857600080fd5b50604051908082528060200260200182016040528015612d22578160200160208202803683370190505b5090508281600081518110612d3357fe5b60200260200101818152505060005b6001835103811015612db857612d96828281518110612d5d57fe5b6020026020010151848381518110612d7157fe5b6020026020010151858460010181518110612d8857fe5b6020026020010151886132ff565b828260010181518110612da557fe5b6020908102919091010152600101612d42565b509392505050565b604051632a4d95e760e21b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a936579c90612e0f9088906004016144b8565b60206040518083038186803b158015612e2757600080fd5b505afa158015612e3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5f9190614039565b90506001600160a01b038116612e8057612e7b85858585613668565b612b87565b604051635ac402df60e11b81526000906001600160a01b0387169063b58805be90612eaf908690600401614734565b602060405180830381600087803b158015612ec957600080fd5b505af1158015612edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f019190614330565b9050612f0f82863084613668565b612f1a8287836137c4565b6040516311f9fbc960e21b81526001600160a01b038716906347e7ef2490612f48908790859060040161459b565b602060405180830381600087803b158015612f6257600080fd5b505af1158015612f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9a9190614330565b50505050505050565b6060600282511015612ffc576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a20494e56414c49445f5041544800604482015290519081900360640190fd5b815167ffffffffffffffff8111801561301457600080fd5b5060405190808252806020026020018201604052801561303e578160200160208202803683370190505b509050828160018351038151811061305257fe5b60209081029190910101528151600019015b8015612db8576130b282828151811061307957fe5b602002602001015184600184038151811061309057fe5b60200260200101518584815181106130a457fe5b602002602001015188613910565b8260018303815181106130c157fe5b602090810291909101015260001901613064565b600080826001600160a01b0316846001600160a01b031614156131295760405162461bcd60e51b81526004018080602001828103825260268152602001806148b56026913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b03161061314957828461314c565b83835b90925090506001600160a01b0382166131ac576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a205a45524f5f4144445245535300604482015290519081900360640190fd5b9250929050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b6020831061322f5780518252601f199092019160209182019101613210565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613291576040519150601f19603f3d011682016040523d82523d6000602084013e613296565b606091505b50915091508180156132c45750805115806132c457508080602001905160208110156132c157600080fd5b50515b612b875760405162461bcd60e51b815260040180806020018281038252602d815260200180614888602d913960400191505060405180910390fd5b600080851161333f5760405162461bcd60e51b815260040180806020018281038252602c815260200180614788602c913960400191505060405180910390fd5b6000806000806000806133528a8a6130d5565b509050806001600160a01b03168a6001600160a01b0316149150613377888b8b613c2b565b80955081975082985050505050600080600080856001600160a01b031663e94e3d8d6040518163ffffffff1660e01b815260040160606040518083038186803b1580156133c357600080fd5b505afa1580156133d7573d6000803e3d6000fd5b505050506040513d60608110156133ed57600080fd5b5080516020820151604090920151945061ffff16925090506134148e612710849003613ced565b9650600081600381111561342457fe5b14806134445750600181600381111561343957fe5b148015613444575084155b806134625750600281600381111561345857fe5b1480156134625750845b61349d5760405162461bcd60e51b81526004018080602001828103825260248152602001806148396024913960400191505060405180910390fd5b505080156135f157600080856001600160a01b031663b6b9f61b6040518163ffffffff1660e01b8152600401604080518083038186803b1580156134e057600080fd5b505afa1580156134f4573d6000803e3d6000fd5b505050506040513d604081101561350a57600080fd5b5080516020909101519092509050600061354661354184848961352d578c61352f565b8d5b8a61353a578e61353c565b8d5b613d56565b613de3565b905061355481612710613ced565b61356a6135638c612710613ced565b8a90613e35565b106135d5576135858661357d578261357f565b835b82613e84565b9450808a1080156135965750818314155b156135d0576135a58982613e9b565b9a506135c76135c06127106135ba848e613e9b565b90613ced565b8990613e9b565b97508099508098505b6135ed565b6135ea866135e3578361357f565b8282613e84565b94505b5050505b60006136076136008885613e35565b8790613ced565b905060006136258761361f6127106135ba8d89613e35565b90613e35565b9050600081838161363257fe5b04905088811161364b57613646818c613e35565b613655565b613655898c613e35565b9f9e505050505050505050505050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b178152925182516000948594938a169392918291908083835b602083106136ec5780518252601f1990920191602091820191016136cd565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461374e576040519150601f19603f3d011682016040523d82523d6000602084013e613753565b606091505b5091509150818015613781575080511580613781575080806020019051602081101561377e57600080fd5b50515b6137bc5760405162461bcd60e51b81526004018080602001828103825260318152602001806147d46031913960400191505060405180910390fd5b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1781529251825160009485949389169392918291908083835b602083106138405780518252601f199092019160209182019101613821565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146138a2576040519150601f19603f3d011682016040523d82523d6000602084013e6138a7565b606091505b50915091508180156138d55750805115806138d557508080602001905160208110156138d257600080fd5b50515b612b875760405162461bcd60e51b815260040180806020018281038252602b81526020018061485d602b913960400191505060405180910390fd5b60008085116139505760405162461bcd60e51b815260040180806020018281038252602c815260200180614788602c913960400191505060405180910390fd5b60008060008060008060008060006139688d8d6130d5565b506001600160a01b038e81169116149450600090506139888b8e8e613c2b565b809350819a50829b505050506000816001600160a01b031663e94e3d8d6040518163ffffffff1660e01b815260040160606040518083038186803b1580156139cf57600080fd5b505afa1580156139e3573d6000803e3d6000fd5b505050506040513d60608110156139f957600080fd5b508051602082015160409092015161ffff9091169850955090506000816003811115613a2157fe5b1480613a4157506001816003811115613a3657fe5b148015613a41575085155b80613a5f57506002816003811115613a5557fe5b148015613a5f5750855b613a9a5760405162461bcd60e51b81526004018080602001828103825260248152602001806148396024913960400191505060405180910390fd5b816001600160a01b031663b6b9f61b6040518163ffffffff1660e01b8152600401604080518083038186803b158015613ad257600080fd5b505afa158015613ae6573d6000803e3d6000fd5b505050506040513d6040811015613afc57600080fd5b50805160209091015190945092505083159050613bc0576000613b3b613541848488613b28578b613b2a565b8c5b89613b35578d61353c565b8c613d56565b905080613b518f8a613e9b90919063ffffffff16565b10613b6b57613b64856135e3578361357f565b9650613bbe565b613b798561357d578261357f565b96508088118015613b8a5750818314155b15613bbe57613b9f6127106135ba838c613e9b565b9950613bb5613bae8983613e9b565b8f90613e9b565b9d508097508098505b505b5060009150613bd990506127106135ba8d818a89613e35565b90506000613bf18c613beb8888613e35565b90613e9b565b9050613c1b600161361f8661271003613c15858781613c0c57fe5b8e919004613e35565b90613eeb565b9c9b505050505050505050505050565b600080600080613c3b86866130d5565b509050613c49878787612988565b9150600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401604080518083038186803b158015613c8657600080fd5b505afa158015613c9a573d6000803e3d6000fd5b505050506040513d6040811015613cb057600080fd5b50805160209091015190925090506001600160a01b0388811690841614613cd8578082613cdb565b81815b909a9099509397509295505050505050565b6000811580613d0857505080820282828281613d0557fe5b04145b613d50576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b92915050565b600080828411613d7057613d6b856001613e9b565b613d7b565b613d7b866001613e9b565b90506000613d8f600161361f846002613ced565b90506000613db5613da1836002613ced565b613c15613dae8989613e35565b8690613ced565b9050600281613dd5613dcb85613c158b8b613ced565b6002850a01613de3565b010a98975050505050505050565b60006003821115613e26575080600160028204015b81811015613e2057809150600281828581613e0f57fe5b040181613e1857fe5b049050613df8565b50613e30565b8115613e30575060015b919050565b80820182811015613d50576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fd5b6000613e94600019840183613ced565b9392505050565b80820382811115613d50576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b6000613e9483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183613fb45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613f79578181015183820152602001613f61565b50505050905090810190601f168015613fa65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613fc057fe5b0495945050505050565b60008083601f840112613fdb578182fd5b50813567ffffffffffffffff811115613ff2578182fd5b60208301915083602080830285010111156131ac57600080fd5b803560ff81168114613e3057600080fd5b60006020828403121561402e578081fd5b8135613e9481614761565b60006020828403121561404a578081fd5b8151613e9481614761565b60008060408385031215614067578081fd5b823561407281614761565b9150602083013561408281614761565b809150509250929050565b600080600080600080600060e0888a0312156140a7578283fd5b87356140b281614761565b965060208801356140c281614761565b955060408801359450606088013593506080880135925060a08801356140e781614761565b8092505060c0880135905092959891949750929550565b60008060008060008060008060008060006101608c8e03121561411f578384fd5b8b3561412a81614761565b9a5060208c013561413a81614761565b995060408c0135985060608c0135975060808c0135965060a08c013561415f81614761565b955060c08c0135945060e08c013561417681614779565b93506141856101008d0161400c565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600080600080600080610100898b0312156141c3578384fd5b88356141ce81614761565b975060208901356141de81614761565b965060408901359550606089013594506080890135935060a0890135925060c089013561420a81614761565b8092505060e089013590509295985092959890939650565b60008060008060008060c0878903121561423a578182fd5b863561424581614761565b9550602087013594506040870135935060608701359250608087013561426a81614761565b8092505060a087013590509295509295509295565b6000806000806000806000806000806101408b8d03121561429e578384fd5b8a356142a981614761565b995060208b0135985060408b0135975060608b0135965060808b01356142ce81614761565b955060a08b0135945060c08b01356142e581614779565b93506142f360e08c0161400c565b92506101008b013591506101208b013590509295989b9194979a5092959850565b600060208284031215614325578081fd5b8151613e9481614779565b600060208284031215614341578081fd5b5051919050565b60008060008060006080868803121561435f578283fd5b85359450602086013567ffffffffffffffff81111561437c578384fd5b61438888828901613fca565b909550935050604086013561439c81614761565b949793965091946060013592915050565b600080604083850312156143bf578182fd5b505080516020909101519092909150565b60008060008060008060a087890312156143e8578384fd5b8635955060208701359450604087013567ffffffffffffffff81111561440c578485fd5b61441889828a01613fca565b909550935050606087013561442c81614761565b80925050608087013590509295509295509295565b60008284526020808501945082825b8581101561447e57813561446381614761565b6001600160a01b031687529582019590820190600101614450565b509495945050505050565b6000815180845260208085019450808401835b8381101561447e5781518752958201959082019060010161449c565b6001600160a01b0391909116815260200190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b03929092168252602082015260400190565b6000602082526145c8602083018486614441565b949350505050565b600060208252613e946020830184614489565b6000604082526145f66040830186614489565b8281036020840152614609818587614441565b9695505050505050565b60208082526005908201526449463a203f60d81b604082015260600190565b60208082526028908201527f496d706f737369626c65526f757465723a204558434553534956455f494e50556040820152671517d05353d5539560c21b606082015260800190565b6020808252602c908201527f496d706f737369626c65526f757465723a20494e53554646494349454e545f4f60408201526b155514155517d05353d5539560a21b606082015260800190565b6020808252601e908201527f496d706f737369626c65526f757465723a20494e56414c49445f504154480000604082015260600190565b60208082526019908201527f496d706f737369626c65526f757465723a204558504952454400000000000000604082015260600190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461477657600080fd5b50565b801515811461477657600080fdfe496d706f737369626c654c6962726172793a20494e53554646494349454e545f494e5055545f414d4f554e545265656e7472616e637947756172643a207265656e7472616e742063616c6c005472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472616e7366657246726f6d206661696c65645472616e7366657248656c7065723a3a736166655472616e736665724554483a20455448207472616e73666572206661696c6564496d706f737369626c654c6962726172793a2054524144455f4e4f545f414c4c4f5745445472616e7366657248656c7065723a3a73616665417070726f76653a20617070726f7665206661696c65645472616e7366657248656c7065723a3a736166655472616e736665723a207472616e73666572206661696c6564496d706f737369626c654c6962726172793a204944454e544943414c5f414444524553534553a26469706673582212201d47bb6aa4c4e5a635ca01716e6be81c6af6f3e867a84fc2495526c9765ca44264736f6c6343000706003300000000000000000000000045603612891b6406a06854813e18443fc8ec7c7300000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c10000000000000000000000003c9584426432eb851e5689230d5cfc50659103d5
Deployed Bytecode
0x6080604052600436106101395760003560e01c80638803dbee116100ab578063c45a01551161006f578063c45a01551461035c578063ded9382a14610371578063e8e3370014610391578063f305d719146103c0578063fa7de13b146103d3578063fb3bdb41146103f357610154565b80638803dbee146102d4578063ad5c4648146102f4578063af2979eb14610309578063b6f9de9514610329578063baa2abde1461033c57610154565b80634a25d94a116100fd5780634a25d94a1461021f578063590c61f01461023f5780635b0d5984146102545780635c11d79514610281578063791ac947146102a15780637ff36ab5146102c157610154565b8063017e2d551461015957806302751cec1461018457806318cbafe5146101b25780632195995c146101df57806338ed1739146101ff57610154565b36610154576003546001600160a01b0316331461015257fe5b005b600080fd5b34801561016557600080fd5b5061016e610406565b60405161017b91906144b8565b60405180910390f35b34801561019057600080fd5b506101a461019f366004614222565b61042a565b60405161017b92919061473d565b3480156101be57600080fd5b506101d26101cd3660046143d0565b610681565b60405161017b91906145d0565b3480156101eb57600080fd5b506101a46101fa3660046140fe565b61099e565b34801561020b57600080fd5b506101d261021a3660046143d0565b610a73565b34801561022b57600080fd5b506101d261023a3660046143d0565b610c39565b34801561024b57600080fd5b5061016e610d92565b34801561026057600080fd5b5061027461026f36600461427f565b610da1565b60405161017b9190614734565b34801561028d57600080fd5b5061015261029c3660046143d0565b610e7e565b3480156102ad57600080fd5b506101526102bc3660046143d0565b6110d4565b6101d26102cf366004614348565b61131c565b3480156102e057600080fd5b506101d26102ef3660046143d0565b61163b565b34801561030057600080fd5b5061016e6117e7565b34801561031557600080fd5b50610274610324366004614222565b6117f6565b610152610337366004614348565b611abd565b34801561034857600080fd5b506101a461035736600461408d565b611df1565b34801561036857600080fd5b5061016e611fcc565b34801561037d57600080fd5b506101a461038c36600461427f565b611ff0565b34801561039d57600080fd5b506103b16103ac3660046141a7565b6120d3565b60405161017b9392919061474b565b6103b16103ce366004614222565b6122b3565b3480156103df57600080fd5b506101526103ee366004614055565b6125a0565b6101d2610401366004614348565b612623565b7f00000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c181565b60008082428110156104575760405162461bcd60e51b815260040161044e906146fd565b60405180910390fd5b6002600054141561049d576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546104dd907f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73908c906001600160a01b0316612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd9061051090339085908e9060040161450d565b602060405180830381600087803b15801561052a57600080fd5b505af115801561053e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105629190614314565b5060025460035460405163e54dc2d760e01b81526001600160a01b039283169263e54dc2d7926105a0928f929091169086908e908e90600401614531565b6040805180830381600087803b1580156105b957600080fd5b505af11580156105cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f191906143ad565b90945092506106018a8786612a48565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d90610631908690600401614734565b600060405180830381600087803b15801561064b57600080fd5b505af115801561065f573d6000803e3d6000fd5b5050505061066d8684612b8f565b505060016000559097909650945050505050565b606081428110156106a45760405162461bcd60e51b815260040161044e906146fd565b600260005414156106ea576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b03168686600019810181811061070b57fe5b9050602002016020810190610720919061401d565b6001600160a01b0316146107465760405162461bcd60e51b815260040161044e906146c6565b6107a47f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7389888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b915086826001845103815181106107b757fe5b602002602001015110156107dd5760405162461bcd60e51b815260040161044e9061467a565b61088a868660008181106107ed57fe5b9050602002016020810190610802919061401d565b336108707f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738a8a600081811061083457fe5b9050602002016020810190610849919061401d565b8b8b600181811061085657fe5b905060200201602081019061086b919061401d565b612988565b8560008151811061087d57fe5b6020026020010151612dc0565b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906108be9085908a908a906004016145e3565b600060405180830381600087803b1580156108d857600080fd5b505af11580156108ec573d6000803e3d6000fd5b505060035484516001600160a01b039091169250632e1a7d4d91508490600019810190811061091757fe5b60200260200101516040518263ffffffff1660e01b815260040161093b9190614734565b600060405180830381600087803b15801561095557600080fd5b505af1158015610969573d6000803e3d6000fd5b5050505061098e848360018551038151811061098157fe5b6020026020010151612b8f565b5060016000559695505050505050565b60008060006109ce7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738f8f612988565b90506000876109dd578c6109e1565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610a1c903390309086908f908e908e908e906004016144cc565b600060405180830381600087803b158015610a3657600080fd5b505af1158015610a4a573d6000803e3d6000fd5b50505050610a5d8f8f8f8f8f8f8f611df1565b9350935050509b509b9950505050505050505050565b60608142811015610a965760405162461bcd60e51b815260040161044e906146fd565b60026000541415610adc576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905550610b427f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7389888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b91508682600184510381518110610b5557fe5b60200260200101511015610b7b5760405162461bcd60e51b815260040161044e9061467a565b610b8b868660008181106107ed57fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d98490610bbf9085908a908a906004016145e3565b600060405180830381600087803b158015610bd957600080fd5b505af1158015610bed573d6000803e3d6000fd5b5050505061098e868660018989905003818110610c0657fe5b9050602002016020810190610c1b919061401d565b8584600186510381518110610c2c57fe5b6020026020010151612a48565b60608142811015610c5c5760405162461bcd60e51b815260040161044e906146fd565b60026000541415610ca2576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b031686866000198101818110610cc357fe5b9050602002016020810190610cd8919061401d565b6001600160a01b031614610cfe5760405162461bcd60e51b815260040161044e906146c6565b610d5c7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7389888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b91508682600081518110610d6c57fe5b602002602001015111156107dd5760405162461bcd60e51b815260040161044e90614632565b6002546001600160a01b031681565b6003546000908190610ddf907f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73908e906001600160a01b0316612988565b9050600086610dee578b610df2565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610e2d903390309086908e908d908d908d906004016144cc565b600060405180830381600087803b158015610e4757600080fd5b505af1158015610e5b573d6000803e3d6000fd5b50505050610e6d8d8d8d8d8d8d6117f6565b9d9c50505050505050505050505050565b8042811015610e9f5760405162461bcd60e51b815260040161044e906146fd565b60026000541415610ee5576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905550610f6c85856000818110610efd57fe5b9050602002016020810190610f12919061401d565b33610f667f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7389896000818110610f4457fe5b9050602002016020810190610f59919061401d565b8a8a600181811061085657fe5b8a612dc0565b600254604051636fb0847760e01b81526001600160a01b0390911690636fb0847790610f9e90889088906004016145b4565b600060405180830381600087803b158015610fb857600080fd5b505af1158015610fcc573d6000803e3d6000fd5b505050506000858560018888905003818110610fe457fe5b9050602002016020810190610ff9919061401d565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161102491906144b8565b60206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190614330565b9050868110156110965760405162461bcd60e51b815260040161044e9061467a565b6110c5868660001981018181106110a957fe5b90506020020160208101906110be919061401d565b8583612a48565b50506001600055505050505050565b80428110156110f55760405162461bcd60e51b815260040161044e906146fd565b6002600054141561113b576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000556003546001600160a01b03168585600019810181811061115c57fe5b9050602002016020810190611171919061401d565b6001600160a01b0316146111975760405162461bcd60e51b815260040161044e906146c6565b6111a785856000818110610efd57fe5b600254604051636fb0847760e01b81526001600160a01b0390911690636fb08477906111d990889088906004016145b4565b600060405180830381600087803b1580156111f357600080fd5b505af1158015611207573d6000803e3d6000fd5b50506003546040516370a0823160e01b8152600093506001600160a01b0390911691506370a082319061123e9030906004016144b8565b60206040518083038186803b15801561125657600080fd5b505afa15801561126a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128e9190614330565b9050868110156112b05760405162461bcd60e51b815260040161044e9061467a565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d906112e0908490600401614734565b600060405180830381600087803b1580156112fa57600080fd5b505af115801561130e573d6000803e3d6000fd5b505050506110c58482612b8f565b6060814281101561133f5760405162461bcd60e51b815260040161044e906146fd565b60026000541415611385576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b03169087908790816113a457fe5b90506020020160208101906113b9919061401d565b6001600160a01b0316146113df5760405162461bcd60e51b815260040161044e906146c6565b61143d7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7334888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612c8792505050565b9150868260018451038151811061145057fe5b602002602001015110156114765760405162461bcd60e51b815260040161044e9061467a565b60035482516001600160a01b039091169063d0e30db090849060009061149857fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156114cb57600080fd5b505af11580156114df573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb915061152790507f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738989600081610f4457fe5b8460008151811061153457fe5b60200260200101516040518363ffffffff1660e01b815260040161155992919061459b565b602060405180830381600087803b15801561157357600080fd5b505af1158015611587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ab9190614314565b6115b157fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906115e59085908a908a906004016145e3565b600060405180830381600087803b1580156115ff57600080fd5b505af1158015611613573d6000803e3d6000fd5b5050505061162c868660018989905003818110610c0657fe5b50600160005595945050505050565b6060814281101561165e5760405162461bcd60e51b815260040161044e906146fd565b600260005414156116a4576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260008190555061170a7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7389888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b9150868260008151811061171a57fe5b602002602001015111156117405760405162461bcd60e51b815260040161044e90614632565b611750868660008181106107ed57fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906117849085908a908a906004016145e3565b600060405180830381600087803b15801561179e57600080fd5b505af11580156117b2573d6000803e3d6000fd5b5050505061098e8686600189899050038181106117cb57fe5b90506020020160208101906117e0919061401d565b858a612a48565b6003546001600160a01b031681565b600081428110156118195760405162461bcd60e51b815260040161044e906146fd565b6002600054141561185f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600090815560035461189f907f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73908b906001600160a01b0316612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd906118d290339085908d9060040161450d565b602060405180830381600087803b1580156118ec57600080fd5b505af1158015611900573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119249190614314565b5060025460035460405163e54dc2d760e01b81526001600160a01b039283169263e54dc2d792611962928e929091169086908d908d90600401614531565b6040805180830381600087803b15801561197b57600080fd5b505af115801561198f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b391906143ad565b6040516370a0823160e01b8152909450611a4091508a9087906001600160a01b038316906370a08231906119eb9030906004016144b8565b60206040518083038186803b158015611a0357600080fd5b505afa158015611a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3b9190614330565b612a48565b600354604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d90611a70908690600401614734565b600060405180830381600087803b158015611a8a57600080fd5b505af1158015611a9e573d6000803e3d6000fd5b50505050611aac8584612b8f565b505060016000559695505050505050565b8042811015611ade5760405162461bcd60e51b815260040161044e906146fd565b60026000541415611b24576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b0316908690869081611b4357fe5b9050602002016020810190611b58919061401d565b6001600160a01b031614611b7e5760405162461bcd60e51b815260040161044e906146c6565b60035460408051630d0e30db60e41b8152905134926001600160a01b03169163d0e30db091849160048082019260009290919082900301818588803b158015611bc657600080fd5b505af1158015611bda573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb9150611c2290507f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738989600081610f4457fe5b836040518363ffffffff1660e01b8152600401611c4092919061459b565b602060405180830381600087803b158015611c5a57600080fd5b505af1158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c929190614314565b611c9857fe5b600254604051636fb0847760e01b81526001600160a01b0390911690636fb0847790611cca90899089906004016145b4565b600060405180830381600087803b158015611ce457600080fd5b505af1158015611cf8573d6000803e3d6000fd5b505050506000868660018989905003818110611d1057fe5b9050602002016020810190611d25919061401d565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611d5091906144b8565b60206040518083038186803b158015611d6857600080fd5b505afa158015611d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da09190614330565b905087811015611dc25760405162461bcd60e51b815260040161044e9061467a565b6110c587876000198101818110611dd557fe5b9050602002016020810190611dea919061401d565b8683612a48565b6000808242811015611e155760405162461bcd60e51b815260040161044e906146fd565b60026000541415611e5b576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b60026000908155611e8d7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738c8c612988565b6040516323b872dd60e01b81529091506001600160a01b038216906323b872dd90611ec090339085908e9060040161450d565b602060405180830381600087803b158015611eda57600080fd5b505af1158015611eee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f129190614314565b5060025460405163e54dc2d760e01b81526001600160a01b039091169063e54dc2d790611f4b908e908e9086908e908e90600401614531565b6040805180830381600087803b158015611f6457600080fd5b505af1158015611f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9c91906143ad565b9094509250611fac8b8786612a48565b611fb78a8785612a48565b50506001600055909890975095505050505050565b7f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7381565b60035460009081908190612030907f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73908f906001600160a01b0316612988565b905060008761203f578c612043565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf9061207e903390309086908f908e908e908e906004016144cc565b600060405180830381600087803b15801561209857600080fd5b505af11580156120ac573d6000803e3d6000fd5b505050506120be8e8e8e8e8e8e61042a565b909f909e509c50505050505050505050505050565b600080600083428110156120f95760405162461bcd60e51b815260040161044e906146fd565b6002600054141561213f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905554604051633351733f60e01b81526001600160a01b0390911690633351733f9061217e908f908f908f908f908f908f90600401614565565b6040805180830381600087803b15801561219757600080fd5b505af11580156121ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cf91906143ad565b909450925060006122017f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738e8e612988565b905061220f8d338388612dc0565b61221b8c338387612dc0565b6040516335313c2160e11b81526001600160a01b03821690636a62784290612247908a906004016144b8565b602060405180830381600087803b15801561226157600080fd5b505af1158015612275573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122999190614330565b925050600160008190555050985098509895505050505050565b600080600083428110156122d95760405162461bcd60e51b815260040161044e906146fd565b6002600054141561231f576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b6002600081905554600354604051633351733f60e01b81526001600160a01b0392831692633351733f92612363928f92909116908e9034908f908f90600401614565565b6040805180830381600087803b15801561237c57600080fd5b505af1158015612390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b491906143ad565b60035491955093506000906123f5907f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73908d906001600160a01b0316612988565b90506124038b338388612dc0565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505060035460405163a9059cbb60e01b81526001600160a01b03909116935063a9059cbb925061249e91508490889060040161459b565b602060405180830381600087803b1580156124b857600080fd5b505af11580156124cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f09190614314565b6124f657fe5b6040516335313c2160e11b81526001600160a01b03821690636a62784290612522908a906004016144b8565b602060405180830381600087803b15801561253c57600080fd5b505af1158015612550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125749190614330565b92508334111561258a5761258a33853403612b8f565b5060016000819055505096509650969350505050565b6003546001600160a01b03161580156125c257506002546001600160a01b0316155b6125cb57600080fd5b6001546001600160a01b031633146125f55760405162461bcd60e51b815260040161044e90614613565b600380546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b606081428110156126465760405162461bcd60e51b815260040161044e906146fd565b6002600054141561268c576040805162461bcd60e51b815260206004820152601f60248201526000805160206147b4833981519152604482015290519081900360640190fd5b600260009081556003546001600160a01b03169087908790816126ab57fe5b90506020020160208101906126c0919061401d565b6001600160a01b0316146126e65760405162461bcd60e51b815260040161044e906146c6565b6127447f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7388888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612fa392505050565b9150348260008151811061275457fe5b6020026020010151111561277a5760405162461bcd60e51b815260040161044e90614632565b60035482516001600160a01b039091169063d0e30db090849060009061279c57fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156127cf57600080fd5b505af11580156127e3573d6000803e3d6000fd5b50506003546001600160a01b0316925063a9059cbb915061282b90507f00000000000000000000000045603612891b6406a06854813e18443fc8ec7c738989600081610f4457fe5b8460008151811061283857fe5b60200260200101516040518363ffffffff1660e01b815260040161285d92919061459b565b602060405180830381600087803b15801561287757600080fd5b505af115801561288b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128af9190614314565b6128b557fe5b600254604051631a70b66160e21b81526001600160a01b03909116906369c2d984906128e99085908a908a906004016145e3565b600060405180830381600087803b15801561290357600080fd5b505af1158015612917573d6000803e3d6000fd5b5050505061294c86866001898990500381811061293057fe5b9050602002016020810190612945919061401d565b8589612a48565b8160008151811061295957fe5b602002602001015134111561162c5761162c338360008151811061297957fe5b60200260200101513403612b8f565b600080600061299785856130d5565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501206001600160f81b031960688401529a90941b9093166069840152607d8301989098527ffc84b622ba228c468b74c2d99bfe9454ffac280ac017f05a02feb9f739aeb1e4609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b604051632a4d95e760e21b81526000906001600160a01b037f00000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c1169063a936579c90612a979087906004016144b8565b60206040518083038186803b158015612aaf57600080fd5b505afa158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190614039565b90506001600160a01b038116612b0757612b028484846131b3565b612b89565b60405163f3fef3a360e01b81526001600160a01b0385169063f3fef3a390612b35908690869060040161459b565b602060405180830381600087803b158015612b4f57600080fd5b505af1158015612b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b879190614330565b505b50505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b60208310612bdb5780518252601f199092019160209182019101612bbc565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612c3d576040519150601f19603f3d011682016040523d82523d6000602084013e612c42565b606091505b5050905080612c825760405162461bcd60e51b81526004018080602001828103825260348152602001806148056034913960400191505060405180910390fd5b505050565b6060600282511015612ce0576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a20494e56414c49445f5041544800604482015290519081900360640190fd5b815167ffffffffffffffff81118015612cf857600080fd5b50604051908082528060200260200182016040528015612d22578160200160208202803683370190505b5090508281600081518110612d3357fe5b60200260200101818152505060005b6001835103811015612db857612d96828281518110612d5d57fe5b6020026020010151848381518110612d7157fe5b6020026020010151858460010181518110612d8857fe5b6020026020010151886132ff565b828260010181518110612da557fe5b6020908102919091010152600101612d42565b509392505050565b604051632a4d95e760e21b81526000906001600160a01b037f00000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c1169063a936579c90612e0f9088906004016144b8565b60206040518083038186803b158015612e2757600080fd5b505afa158015612e3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5f9190614039565b90506001600160a01b038116612e8057612e7b85858585613668565b612b87565b604051635ac402df60e11b81526000906001600160a01b0387169063b58805be90612eaf908690600401614734565b602060405180830381600087803b158015612ec957600080fd5b505af1158015612edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f019190614330565b9050612f0f82863084613668565b612f1a8287836137c4565b6040516311f9fbc960e21b81526001600160a01b038716906347e7ef2490612f48908790859060040161459b565b602060405180830381600087803b158015612f6257600080fd5b505af1158015612f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9a9190614330565b50505050505050565b6060600282511015612ffc576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a20494e56414c49445f5041544800604482015290519081900360640190fd5b815167ffffffffffffffff8111801561301457600080fd5b5060405190808252806020026020018201604052801561303e578160200160208202803683370190505b509050828160018351038151811061305257fe5b60209081029190910101528151600019015b8015612db8576130b282828151811061307957fe5b602002602001015184600184038151811061309057fe5b60200260200101518584815181106130a457fe5b602002602001015188613910565b8260018303815181106130c157fe5b602090810291909101015260001901613064565b600080826001600160a01b0316846001600160a01b031614156131295760405162461bcd60e51b81526004018080602001828103825260268152602001806148b56026913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b03161061314957828461314c565b83835b90925090506001600160a01b0382166131ac576040805162461bcd60e51b815260206004820152601f60248201527f496d706f737369626c654c6962726172793a205a45524f5f4144445245535300604482015290519081900360640190fd5b9250929050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b6020831061322f5780518252601f199092019160209182019101613210565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613291576040519150601f19603f3d011682016040523d82523d6000602084013e613296565b606091505b50915091508180156132c45750805115806132c457508080602001905160208110156132c157600080fd5b50515b612b875760405162461bcd60e51b815260040180806020018281038252602d815260200180614888602d913960400191505060405180910390fd5b600080851161333f5760405162461bcd60e51b815260040180806020018281038252602c815260200180614788602c913960400191505060405180910390fd5b6000806000806000806133528a8a6130d5565b509050806001600160a01b03168a6001600160a01b0316149150613377888b8b613c2b565b80955081975082985050505050600080600080856001600160a01b031663e94e3d8d6040518163ffffffff1660e01b815260040160606040518083038186803b1580156133c357600080fd5b505afa1580156133d7573d6000803e3d6000fd5b505050506040513d60608110156133ed57600080fd5b5080516020820151604090920151945061ffff16925090506134148e612710849003613ced565b9650600081600381111561342457fe5b14806134445750600181600381111561343957fe5b148015613444575084155b806134625750600281600381111561345857fe5b1480156134625750845b61349d5760405162461bcd60e51b81526004018080602001828103825260248152602001806148396024913960400191505060405180910390fd5b505080156135f157600080856001600160a01b031663b6b9f61b6040518163ffffffff1660e01b8152600401604080518083038186803b1580156134e057600080fd5b505afa1580156134f4573d6000803e3d6000fd5b505050506040513d604081101561350a57600080fd5b5080516020909101519092509050600061354661354184848961352d578c61352f565b8d5b8a61353a578e61353c565b8d5b613d56565b613de3565b905061355481612710613ced565b61356a6135638c612710613ced565b8a90613e35565b106135d5576135858661357d578261357f565b835b82613e84565b9450808a1080156135965750818314155b156135d0576135a58982613e9b565b9a506135c76135c06127106135ba848e613e9b565b90613ced565b8990613e9b565b97508099508098505b6135ed565b6135ea866135e3578361357f565b8282613e84565b94505b5050505b60006136076136008885613e35565b8790613ced565b905060006136258761361f6127106135ba8d89613e35565b90613e35565b9050600081838161363257fe5b04905088811161364b57613646818c613e35565b613655565b613655898c613e35565b9f9e505050505050505050505050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b178152925182516000948594938a169392918291908083835b602083106136ec5780518252601f1990920191602091820191016136cd565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461374e576040519150601f19603f3d011682016040523d82523d6000602084013e613753565b606091505b5091509150818015613781575080511580613781575080806020019051602081101561377e57600080fd5b50515b6137bc5760405162461bcd60e51b81526004018080602001828103825260318152602001806147d46031913960400191505060405180910390fd5b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1781529251825160009485949389169392918291908083835b602083106138405780518252601f199092019160209182019101613821565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146138a2576040519150601f19603f3d011682016040523d82523d6000602084013e6138a7565b606091505b50915091508180156138d55750805115806138d557508080602001905160208110156138d257600080fd5b50515b612b875760405162461bcd60e51b815260040180806020018281038252602b81526020018061485d602b913960400191505060405180910390fd5b60008085116139505760405162461bcd60e51b815260040180806020018281038252602c815260200180614788602c913960400191505060405180910390fd5b60008060008060008060008060006139688d8d6130d5565b506001600160a01b038e81169116149450600090506139888b8e8e613c2b565b809350819a50829b505050506000816001600160a01b031663e94e3d8d6040518163ffffffff1660e01b815260040160606040518083038186803b1580156139cf57600080fd5b505afa1580156139e3573d6000803e3d6000fd5b505050506040513d60608110156139f957600080fd5b508051602082015160409092015161ffff9091169850955090506000816003811115613a2157fe5b1480613a4157506001816003811115613a3657fe5b148015613a41575085155b80613a5f57506002816003811115613a5557fe5b148015613a5f5750855b613a9a5760405162461bcd60e51b81526004018080602001828103825260248152602001806148396024913960400191505060405180910390fd5b816001600160a01b031663b6b9f61b6040518163ffffffff1660e01b8152600401604080518083038186803b158015613ad257600080fd5b505afa158015613ae6573d6000803e3d6000fd5b505050506040513d6040811015613afc57600080fd5b50805160209091015190945092505083159050613bc0576000613b3b613541848488613b28578b613b2a565b8c5b89613b35578d61353c565b8c613d56565b905080613b518f8a613e9b90919063ffffffff16565b10613b6b57613b64856135e3578361357f565b9650613bbe565b613b798561357d578261357f565b96508088118015613b8a5750818314155b15613bbe57613b9f6127106135ba838c613e9b565b9950613bb5613bae8983613e9b565b8f90613e9b565b9d508097508098505b505b5060009150613bd990506127106135ba8d818a89613e35565b90506000613bf18c613beb8888613e35565b90613e9b565b9050613c1b600161361f8661271003613c15858781613c0c57fe5b8e919004613e35565b90613eeb565b9c9b505050505050505050505050565b600080600080613c3b86866130d5565b509050613c49878787612988565b9150600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401604080518083038186803b158015613c8657600080fd5b505afa158015613c9a573d6000803e3d6000fd5b505050506040513d6040811015613cb057600080fd5b50805160209091015190925090506001600160a01b0388811690841614613cd8578082613cdb565b81815b909a9099509397509295505050505050565b6000811580613d0857505080820282828281613d0557fe5b04145b613d50576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b92915050565b600080828411613d7057613d6b856001613e9b565b613d7b565b613d7b866001613e9b565b90506000613d8f600161361f846002613ced565b90506000613db5613da1836002613ced565b613c15613dae8989613e35565b8690613ced565b9050600281613dd5613dcb85613c158b8b613ced565b6002850a01613de3565b010a98975050505050505050565b60006003821115613e26575080600160028204015b81811015613e2057809150600281828581613e0f57fe5b040181613e1857fe5b049050613df8565b50613e30565b8115613e30575060015b919050565b80820182811015613d50576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fd5b6000613e94600019840183613ced565b9392505050565b80820382811115613d50576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b6000613e9483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183613fb45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613f79578181015183820152602001613f61565b50505050905090810190601f168015613fa65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613fc057fe5b0495945050505050565b60008083601f840112613fdb578182fd5b50813567ffffffffffffffff811115613ff2578182fd5b60208301915083602080830285010111156131ac57600080fd5b803560ff81168114613e3057600080fd5b60006020828403121561402e578081fd5b8135613e9481614761565b60006020828403121561404a578081fd5b8151613e9481614761565b60008060408385031215614067578081fd5b823561407281614761565b9150602083013561408281614761565b809150509250929050565b600080600080600080600060e0888a0312156140a7578283fd5b87356140b281614761565b965060208801356140c281614761565b955060408801359450606088013593506080880135925060a08801356140e781614761565b8092505060c0880135905092959891949750929550565b60008060008060008060008060008060006101608c8e03121561411f578384fd5b8b3561412a81614761565b9a5060208c013561413a81614761565b995060408c0135985060608c0135975060808c0135965060a08c013561415f81614761565b955060c08c0135945060e08c013561417681614779565b93506141856101008d0161400c565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600080600080600080610100898b0312156141c3578384fd5b88356141ce81614761565b975060208901356141de81614761565b965060408901359550606089013594506080890135935060a0890135925060c089013561420a81614761565b8092505060e089013590509295985092959890939650565b60008060008060008060c0878903121561423a578182fd5b863561424581614761565b9550602087013594506040870135935060608701359250608087013561426a81614761565b8092505060a087013590509295509295509295565b6000806000806000806000806000806101408b8d03121561429e578384fd5b8a356142a981614761565b995060208b0135985060408b0135975060608b0135965060808b01356142ce81614761565b955060a08b0135945060c08b01356142e581614779565b93506142f360e08c0161400c565b92506101008b013591506101208b013590509295989b9194979a5092959850565b600060208284031215614325578081fd5b8151613e9481614779565b600060208284031215614341578081fd5b5051919050565b60008060008060006080868803121561435f578283fd5b85359450602086013567ffffffffffffffff81111561437c578384fd5b61438888828901613fca565b909550935050604086013561439c81614761565b949793965091946060013592915050565b600080604083850312156143bf578182fd5b505080516020909101519092909150565b60008060008060008060a087890312156143e8578384fd5b8635955060208701359450604087013567ffffffffffffffff81111561440c578485fd5b61441889828a01613fca565b909550935050606087013561442c81614761565b80925050608087013590509295509295509295565b60008284526020808501945082825b8581101561447e57813561446381614761565b6001600160a01b031687529582019590820190600101614450565b509495945050505050565b6000815180845260208085019450808401835b8381101561447e5781518752958201959082019060010161449c565b6001600160a01b0391909116815260200190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b03929092168252602082015260400190565b6000602082526145c8602083018486614441565b949350505050565b600060208252613e946020830184614489565b6000604082526145f66040830186614489565b8281036020840152614609818587614441565b9695505050505050565b60208082526005908201526449463a203f60d81b604082015260600190565b60208082526028908201527f496d706f737369626c65526f757465723a204558434553534956455f494e50556040820152671517d05353d5539560c21b606082015260800190565b6020808252602c908201527f496d706f737369626c65526f757465723a20494e53554646494349454e545f4f60408201526b155514155517d05353d5539560a21b606082015260800190565b6020808252601e908201527f496d706f737369626c65526f757465723a20494e56414c49445f504154480000604082015260600190565b60208082526019908201527f496d706f737369626c65526f757465723a204558504952454400000000000000604082015260600190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6001600160a01b038116811461477657600080fd5b50565b801515811461477657600080fdfe496d706f737369626c654c6962726172793a20494e53554646494349454e545f494e5055545f414d4f554e545265656e7472616e637947756172643a207265656e7472616e742063616c6c005472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472616e7366657246726f6d206661696c65645472616e7366657248656c7065723a3a736166655472616e736665724554483a20455448207472616e73666572206661696c6564496d706f737369626c654c6962726172793a2054524144455f4e4f545f414c4c4f5745445472616e7366657248656c7065723a3a73616665417070726f76653a20617070726f7665206661696c65645472616e7366657248656c7065723a3a736166655472616e736665723a207472616e73666572206661696c6564496d706f737369626c654c6962726172793a204944454e544943414c5f414444524553534553a26469706673582212201d47bb6aa4c4e5a635ca01716e6be81c6af6f3e867a84fc2495526c9765ca44264736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000045603612891b6406a06854813e18443fc8ec7c7300000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c10000000000000000000000003c9584426432eb851e5689230d5cfc50659103d5
-----Decoded View---------------
Arg [0] : _pairFactory (address): 0x45603612891b6406A06854813e18443fC8ec7C73
Arg [1] : _wrapFactory (address): 0x45a3a315277Fbc1BCe0611c4398b32E0317Fd7c1
Arg [2] : _utilitySettingAdmin (address): 0x3C9584426432eb851e5689230d5cFc50659103D5
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000045603612891b6406a06854813e18443fc8ec7c73
Arg [1] : 00000000000000000000000045a3a315277fbc1bce0611c4398b32e0317fd7c1
Arg [2] : 0000000000000000000000003c9584426432eb851e5689230d5cfc50659103d5
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
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.