Source Code
Overview
ETH Balance
ETH Value
$0.00Latest 25 from a total of 102 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Remove Liquidity... | 944956 | 796 days ago | IN | 0 ETH | 0.00037444 | ||||
| Swap Exact Token... | 659584 | 808 days ago | IN | 0 ETH | 0.00032498 | ||||
| Swap Exact ETH F... | 504899 | 814 days ago | IN | 0.000001 ETH | 0.0004439 | ||||
| Swap Exact ETH F... | 504889 | 814 days ago | IN | 0.000001 ETH | 0.00023273 | ||||
| Swap Exact Token... | 420142 | 817 days ago | IN | 0 ETH | 0.00041141 | ||||
| Swap Exact Token... | 392834 | 818 days ago | IN | 0 ETH | 0.0002802 | ||||
| Swap Exact Token... | 107890 | 829 days ago | IN | 0 ETH | 0.00024141 | ||||
| Swap Exact Token... | 103248 | 829 days ago | IN | 0 ETH | 0.00016239 | ||||
| Swap Exact Token... | 103179 | 829 days ago | IN | 0 ETH | 0.00019418 | ||||
| Swap Exact Token... | 91956 | 830 days ago | IN | 0 ETH | 0.00019916 | ||||
| Swap Exact Token... | 84507 | 830 days ago | IN | 0 ETH | 0.00018065 | ||||
| Swap Exact Token... | 84483 | 830 days ago | IN | 0 ETH | 0.00018484 | ||||
| Swap Exact Token... | 84076 | 830 days ago | IN | 0 ETH | 0.00024336 | ||||
| Swap Exact Token... | 83028 | 830 days ago | IN | 0 ETH | 0.00022275 | ||||
| Swap Exact ETH F... | 82938 | 830 days ago | IN | 0.002 ETH | 0.00018498 | ||||
| Swap Exact ETH F... | 82916 | 830 days ago | IN | 0.1 ETH | 0.00018846 | ||||
| Swap Exact Token... | 82815 | 830 days ago | IN | 0 ETH | 0.00023111 | ||||
| Swap Exact Token... | 82772 | 830 days ago | IN | 0 ETH | 0.00024339 | ||||
| Swap Exact Token... | 82574 | 830 days ago | IN | 0 ETH | 0.00025736 | ||||
| Swap Exact Token... | 82571 | 830 days ago | IN | 0 ETH | 0.00025736 | ||||
| Swap Exact Token... | 82525 | 830 days ago | IN | 0 ETH | 0.00025239 | ||||
| Swap Exact ETH F... | 82499 | 830 days ago | IN | 0.07 ETH | 0.0002507 | ||||
| Swap Exact ETH F... | 82427 | 830 days ago | IN | 0.01 ETH | 0.00019166 | ||||
| Swap Exact Token... | 82418 | 830 days ago | IN | 0 ETH | 0.00019367 | ||||
| Swap Exact Token... | 82392 | 830 days ago | IN | 0 ETH | 0.0002721 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 944956 | 796 days ago | 1.00741078 ETH | ||||
| 944956 | 796 days ago | 1.00741078 ETH | ||||
| 659584 | 808 days ago | 0.01505191 ETH | ||||
| 659584 | 808 days ago | 0.01505191 ETH | ||||
| 504899 | 814 days ago | 0.000001 ETH | ||||
| 420142 | 817 days ago | 0.00584843 ETH | ||||
| 420142 | 817 days ago | 0.00584843 ETH | ||||
| 392834 | 818 days ago | 0.00245724 ETH | ||||
| 392834 | 818 days ago | 0.00245724 ETH | ||||
| 107890 | 829 days ago | 0.00648613 ETH | ||||
| 107890 | 829 days ago | 0.00648613 ETH | ||||
| 103248 | 829 days ago | 0.06792116 ETH | ||||
| 103248 | 829 days ago | 0.06792116 ETH | ||||
| 103179 | 829 days ago | 0.02416829 ETH | ||||
| 103179 | 829 days ago | 0.02416829 ETH | ||||
| 91956 | 830 days ago | 0.04481419 ETH | ||||
| 91956 | 830 days ago | 0.04481419 ETH | ||||
| 84507 | 830 days ago | 0.08099881 ETH | ||||
| 84507 | 830 days ago | 0.08099881 ETH | ||||
| 84483 | 830 days ago | 0.00566353 ETH | ||||
| 84483 | 830 days ago | 0.00566353 ETH | ||||
| 84076 | 830 days ago | 0.13214416 ETH | ||||
| 84076 | 830 days ago | 0.13214416 ETH | ||||
| 83028 | 830 days ago | 0.00870044 ETH | ||||
| 83028 | 830 days ago | 0.00870044 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Router01
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "../../lib/Math.sol";
import "../../lib/SafeERC20.sol";
import "../../interface/IERC20.sol";
import "../../interface/IWETH.sol";
import "../../interface/IPair.sol";
import "../../interface/IRouter.sol";
import "../../interface/IFactory.sol";
contract Router01 {
using SafeERC20 for IERC20;
struct Route {
address from;
address to;
bool stable;
}
address public immutable factory;
address public immutable weth;
uint internal constant MINIMUM_LIQUIDITY = 10 ** 3;
bytes32 immutable pairCodeHash;
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, "Router: EXPIRED");
_;
}
constructor(address _factory, address _weth) {
factory = address(_factory);
pairCodeHash = IFactory(_factory).pairCodeHash();
weth = address(_weth);
}
receive() external payable {
// only accept ETH via fallback from the WETH contract
require(msg.sender == address(weth), "Router: NOT_weth");
}
function sortTokens(
address tokenA,
address tokenB
) external pure returns (address token0, address token1) {
return _sortTokens(tokenA, tokenB);
}
function _sortTokens(
address tokenA,
address tokenB
) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, "Router: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB
? (tokenA, tokenB)
: (tokenB, tokenA);
require(token0 != address(0), "Router: ZERO_ADDRESS");
}
function pairFor(
address tokenA,
address tokenB,
bool stable
) external view returns (address pair) {
return _pairFor(tokenA, tokenB, stable);
}
/// @dev Calculates the CREATE2 address for a pair without making any external calls.
function _pairFor(
address tokenA,
address tokenB,
bool stable
) internal view returns (address pair) {
(address token0, address token1) = _sortTokens(tokenA, tokenB);
pair = address(
uint160(
uint(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encodePacked(token0, token1, stable)),
pairCodeHash // init code hash
)
)
)
)
);
}
function quoteLiquidity(
uint amountA,
uint reserveA,
uint reserveB
) external pure returns (uint amountB) {
return _quoteLiquidity(amountA, reserveA, reserveB);
}
/// @dev Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset.
function _quoteLiquidity(
uint amountA,
uint reserveA,
uint reserveB
) internal pure returns (uint amountB) {
require(amountA > 0, "Router: INSUFFICIENT_AMOUNT");
require(reserveA > 0 && reserveB > 0, "Router: INSUFFICIENT_LIQUIDITY");
amountB = (amountA * reserveB) / reserveA;
}
function getReserves(
address tokenA,
address tokenB,
bool stable
) external view returns (uint reserveA, uint reserveB) {
return _getReserves(tokenA, tokenB, stable);
}
/// @dev Fetches and sorts the reserves for a pair.
function _getReserves(
address tokenA,
address tokenB,
bool stable
) internal view returns (uint reserveA, uint reserveB) {
(address token0, ) = _sortTokens(tokenA, tokenB);
(uint reserve0, uint reserve1, ) = IPair(
_pairFor(tokenA, tokenB, stable)
).getReserves();
(reserveA, reserveB) = tokenA == token0
? (reserve0, reserve1)
: (reserve1, reserve0);
}
/// @dev Performs chained getAmountOut calculations on any number of pairs.
function getAmountOut(
uint amountIn,
address tokenIn,
address tokenOut
) external view returns (uint amount, bool stable) {
address pair = _pairFor(tokenIn, tokenOut, true);
uint amountStable;
uint amountVolatile;
if (IFactory(factory).isPair(pair)) {
amountStable = IPair(pair).getAmountOut(amountIn, tokenIn);
}
pair = _pairFor(tokenIn, tokenOut, false);
if (IFactory(factory).isPair(pair)) {
amountVolatile = IPair(pair).getAmountOut(amountIn, tokenIn);
}
return
amountStable > amountVolatile
? (amountStable, true)
: (amountVolatile, false);
}
function getExactAmountOut(
uint amountIn,
address tokenIn,
address tokenOut,
bool stable
) external view returns (uint) {
address pair = _pairFor(tokenIn, tokenOut, stable);
if (IFactory(factory).isPair(pair)) {
return IPair(pair).getAmountOut(amountIn, tokenIn);
}
return 0;
}
/// @dev Performs chained getAmountOut calculations on any number of pairs.
function getAmountsOut(
uint amountIn,
Route[] memory routes
) external view returns (uint[] memory amounts) {
return _getAmountsOut(amountIn, routes);
}
function _getAmountsOut(
uint amountIn,
Route[] memory routes
) internal view returns (uint[] memory amounts) {
require(routes.length >= 1, "Router: INVALID_PATH");
amounts = new uint[](routes.length + 1);
amounts[0] = amountIn;
for (uint i = 0; i < routes.length; i++) {
address pair = _pairFor(
routes[i].from,
routes[i].to,
routes[i].stable
);
if (IFactory(factory).isPair(pair)) {
amounts[i + 1] = IPair(pair).getAmountOut(
amounts[i],
routes[i].from
);
}
}
}
function isPair(address pair) external view returns (bool) {
return IFactory(factory).isPair(pair);
}
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired
) external view returns (uint amountA, uint amountB, uint liquidity) {
// create the pair if it doesn't exist yet
address _pair = IFactory(factory).getPair(tokenA, tokenB, stable);
(uint reserveA, uint reserveB) = (0, 0);
uint _totalSupply = 0;
if (_pair != address(0)) {
_totalSupply = IERC20(_pair).totalSupply();
(reserveA, reserveB) = _getReserves(tokenA, tokenB, stable);
}
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
liquidity = Math.sqrt(amountA * amountB) - MINIMUM_LIQUIDITY;
} else {
uint amountBOptimal = _quoteLiquidity(
amountADesired,
reserveA,
reserveB
);
if (amountBOptimal <= amountBDesired) {
(amountA, amountB) = (amountADesired, amountBOptimal);
liquidity = Math.min(
(amountA * _totalSupply) / reserveA,
(amountB * _totalSupply) / reserveB
);
} else {
uint amountAOptimal = _quoteLiquidity(
amountBDesired,
reserveB,
reserveA
);
(amountA, amountB) = (amountAOptimal, amountBDesired);
liquidity = Math.min(
(amountA * _totalSupply) / reserveA,
(amountB * _totalSupply) / reserveB
);
}
}
}
function quoteRemoveLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity
) external view returns (uint amountA, uint amountB) {
// create the pair if it doesn't exist yet
address _pair = IFactory(factory).getPair(tokenA, tokenB, stable);
if (_pair == address(0)) {
return (0, 0);
}
(uint reserveA, uint reserveB) = _getReserves(tokenA, tokenB, stable);
uint _totalSupply = IERC20(_pair).totalSupply();
// using balances ensures pro-rata distribution
amountA = (liquidity * reserveA) / _totalSupply;
// using balances ensures pro-rata distribution
amountB = (liquidity * reserveB) / _totalSupply;
}
function _addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal returns (uint amountA, uint amountB) {
require(amountADesired >= amountAMin, "Router: DESIRED_A_AMOUNT");
require(amountBDesired >= amountBMin, "Router: DESIRED_B_AMOUNT");
// create the pair if it doesn't exist yet
address _pair = IFactory(factory).getPair(tokenA, tokenB, stable);
if (_pair == address(0)) {
_pair = IFactory(factory).createPair(tokenA, tokenB, stable);
}
(uint reserveA, uint reserveB) = _getReserves(tokenA, tokenB, stable);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint amountBOptimal = _quoteLiquidity(
amountADesired,
reserveA,
reserveB
);
if (amountBOptimal <= amountBDesired) {
require(
amountBOptimal >= amountBMin,
"Router: INSUFFICIENT_B_AMOUNT"
);
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint amountAOptimal = _quoteLiquidity(
amountBDesired,
reserveB,
reserveA
);
assert(amountAOptimal <= amountADesired);
require(
amountAOptimal >= amountAMin,
"Router: INSUFFICIENT_A_AMOUNT"
);
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
)
external
ensure(deadline)
returns (uint amountA, uint amountB, uint liquidity)
{
(amountA, amountB) = _addLiquidity(
tokenA,
tokenB,
stable,
amountADesired,
amountBDesired,
amountAMin,
amountBMin
);
address pair = _pairFor(tokenA, tokenB, stable);
SafeERC20.safeTransferFrom(IERC20(tokenA), msg.sender, pair, amountA);
SafeERC20.safeTransferFrom(IERC20(tokenB), msg.sender, pair, amountB);
liquidity = IPair(pair).mint(to);
}
function addLiquidityETH(
address token,
bool stable,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
)
external
payable
ensure(deadline)
returns (uint amountToken, uint amountETH, uint liquidity)
{
(amountToken, amountETH) = _addLiquidity(
token,
address(weth),
stable,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = _pairFor(token, address(weth), stable);
IERC20(token).safeTransferFrom(msg.sender, pair, amountToken);
IWETH(weth).deposit{value: amountETH}();
assert(IWETH(weth).transfer(pair, amountETH));
liquidity = IPair(pair).mint(to);
// refund dust eth, if any
if (msg.value > amountETH)
_safeTransferETH(msg.sender, msg.value - amountETH);
}
// **** REMOVE LIQUIDITY ****
function removeLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB) {
return
_removeLiquidity(
tokenA,
tokenB,
stable,
liquidity,
amountAMin,
amountBMin,
to,
deadline
);
}
function _removeLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) internal ensure(deadline) returns (uint amountA, uint amountB) {
address pair = _pairFor(tokenA, tokenB, stable);
IERC20(pair).safeTransferFrom(msg.sender, pair, liquidity);
// send liquidity to pair
(uint amount0, uint amount1) = IPair(pair).burn(to);
(address token0, ) = _sortTokens(tokenA, tokenB);
(amountA, amountB) = tokenA == token0
? (amount0, amount1)
: (amount1, amount0);
require(amountA >= amountAMin, "Router: INSUFFICIENT_A_AMOUNT");
require(amountB >= amountBMin, "Router: INSUFFICIENT_B_AMOUNT");
}
function removeLiquidityETH(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH) {
return
_removeLiquidityETH(
token,
stable,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
function _removeLiquidityETH(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) internal ensure(deadline) returns (uint amountToken, uint amountETH) {
(amountToken, amountETH) = _removeLiquidity(
token,
address(weth),
stable,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
IERC20(token).safeTransfer(to, amountToken);
IWETH(weth).withdraw(amountETH);
_safeTransferETH(to, amountETH);
}
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountA, uint amountB) {
address pair = _pairFor(tokenA, tokenB, stable);
{
uint value = approveMax ? type(uint).max : liquidity;
IPair(pair).permit(
msg.sender,
address(this),
value,
deadline,
v,
r,
s
);
}
(amountA, amountB) = _removeLiquidity(
tokenA,
tokenB,
stable,
liquidity,
amountAMin,
amountBMin,
to,
deadline
);
}
function removeLiquidityETHWithPermit(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH) {
address pair = _pairFor(token, address(weth), stable);
uint value = approveMax ? type(uint).max : liquidity;
IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(amountToken, amountETH) = _removeLiquidityETH(
token,
stable,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH) {
return
_removeLiquidityETHSupportingFeeOnTransferTokens(
token,
stable,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
function _removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) internal ensure(deadline) returns (uint amountToken, uint amountETH) {
(amountToken, amountETH) = _removeLiquidity(
token,
address(weth),
stable,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
IERC20(token).safeTransfer(to, IERC20(token).balanceOf(address(this)));
IWETH(weth).withdraw(amountETH);
_safeTransferETH(to, amountETH);
}
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH) {
address pair = _pairFor(token, address(weth), stable);
uint value = approveMax ? type(uint).max : liquidity;
IPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(
amountToken,
amountETH
) = _removeLiquidityETHSupportingFeeOnTransferTokens(
token,
stable,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
// **** SWAP ****
// requires the initial amount to have already been sent to the first pair
function _swap(
uint[] memory amounts,
Route[] memory routes,
address _to
) internal virtual {
for (uint i = 0; i < routes.length; i++) {
(address token0, ) = _sortTokens(routes[i].from, routes[i].to);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = routes[i].from == token0
? (uint(0), amountOut)
: (amountOut, uint(0));
address to = i < routes.length - 1
? _pairFor(
routes[i + 1].from,
routes[i + 1].to,
routes[i + 1].stable
)
: _to;
IPair(_pairFor(routes[i].from, routes[i].to, routes[i].stable))
.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function _swapSupportingFeeOnTransferTokens(
Route[] memory routes,
address _to
) internal virtual {
for (uint i; i < routes.length; i++) {
(address input, address output) = (routes[i].from, routes[i].to);
(address token0, ) = _sortTokens(input, output);
IPair pair = IPair(
_pairFor(routes[i].from, routes[i].to, routes[i].stable)
);
uint amountInput;
uint amountOutput;
{
// scope to avoid stack too deep errors
(uint reserve0, uint reserve1, ) = pair.getReserves();
uint reserveInput = input == token0 ? reserve0 : reserve1;
amountInput =
IERC20(input).balanceOf(address(pair)) -
reserveInput;
//(amountOutput,) = getAmountOut(amountInput, input, output, stable);
amountOutput = pair.getAmountOut(amountInput, input);
}
(uint amount0Out, uint amount1Out) = input == token0
? (uint(0), amountOutput)
: (amountOutput, uint(0));
address to = i < routes.length - 1
? _pairFor(
routes[i + 1].from,
routes[i + 1].to,
routes[i + 1].stable
)
: _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function swapExactTokensForTokensSimple(
uint amountIn,
uint amountOutMin,
address tokenFrom,
address tokenTo,
bool stable,
address to,
uint deadline
) external ensure(deadline) returns (uint[] memory amounts) {
Route[] memory routes = new Route[](1);
routes[0].from = tokenFrom;
routes[0].to = tokenTo;
routes[0].stable = stable;
amounts = _getAmountsOut(amountIn, routes);
require(
amounts[amounts.length - 1] >= amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amounts[0]
);
_swap(amounts, routes, to);
}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external ensure(deadline) returns (uint[] memory amounts) {
amounts = _getAmountsOut(amountIn, routes);
require(
amounts[amounts.length - 1] >= amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amounts[0]
);
_swap(amounts, routes, to);
}
function swapExactETHForTokens(
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external payable ensure(deadline) returns (uint[] memory amounts) {
require(routes[0].from == address(weth), "Router: INVALID_PATH");
amounts = _getAmountsOut(msg.value, routes);
require(
amounts[amounts.length - 1] >= amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
IWETH(weth).deposit{value: amounts[0]}();
assert(
IWETH(weth).transfer(
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amounts[0]
)
);
_swap(amounts, routes, to);
}
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external ensure(deadline) returns (uint[] memory amounts) {
require(
routes[routes.length - 1].to == address(weth),
"Router: INVALID_PATH"
);
amounts = _getAmountsOut(amountIn, routes);
require(
amounts[amounts.length - 1] >= amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amounts[0]
);
_swap(amounts, routes, address(this));
IWETH(weth).withdraw(amounts[amounts.length - 1]);
_safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external ensure(deadline) {
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amountIn
);
uint balanceBefore = IERC20(routes[routes.length - 1].to).balanceOf(to);
_swapSupportingFeeOnTransferTokens(routes, to);
require(
IERC20(routes[routes.length - 1].to).balanceOf(to) -
balanceBefore >=
amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external payable ensure(deadline) {
require(routes[0].from == address(weth), "Router: INVALID_PATH");
uint amountIn = msg.value;
IWETH(weth).deposit{value: amountIn}();
assert(
IWETH(weth).transfer(
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amountIn
)
);
uint balanceBefore = IERC20(routes[routes.length - 1].to).balanceOf(to);
_swapSupportingFeeOnTransferTokens(routes, to);
require(
IERC20(routes[routes.length - 1].to).balanceOf(to) -
balanceBefore >=
amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external ensure(deadline) {
require(
routes[routes.length - 1].to == address(weth),
"Router: INVALID_PATH"
);
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amountIn
);
_swapSupportingFeeOnTransferTokens(routes, address(this));
uint amountOut = IERC20(address(weth)).balanceOf(address(this));
require(
amountOut >= amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
IWETH(weth).withdraw(amountOut);
_safeTransferETH(to, amountOut);
}
function UNSAFE_swapExactTokensForTokens(
uint[] memory amounts,
Route[] calldata routes,
address to,
uint deadline
) external ensure(deadline) returns (uint[] memory) {
IERC20(routes[0].from).safeTransferFrom(
msg.sender,
_pairFor(routes[0].from, routes[0].to, routes[0].stable),
amounts[0]
);
_swap(amounts, routes, to);
return amounts;
}
function _safeTransferETH(address to, uint value) internal {
(bool success, ) = payable(to).call{value: value}(new bytes(0));
require(success, "Router: ETH_TRANSFER_FAILED");
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IFactory {
function SWAP_FEE() external view returns (uint256);
function TREASURY_FEE() external view returns (uint256);
function DOMINATOR() external view returns (uint256);
function treasury() external view returns (address);
function isPair(address pair) external view returns (bool);
function getInitializable() external view returns (address, address, bool);
function isPaused() external view returns (bool);
function pairCodeHash() external pure returns (bytes32);
function getPair(
address tokenA,
address token,
bool stable
) external view returns (address);
function createPair(
address tokenA,
address tokenB,
bool stable
) external returns (address pair);
function updateFees(
uint256 _swap_fee,
uint256 _treasury_fee,
uint256 _dominator
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IPair {
// Structure to capture time period obervations every 30 minutes, used for local oracles
struct Observation {
uint timestamp;
uint reserve0Cumulative;
uint reserve1Cumulative;
}
function permit(
address owner,
address spender,
uint value,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
function burn(address to) external returns (uint amount0, uint amount1);
function mint(address to) external returns (uint liquidity);
function getReserves()
external
view
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
);
function getAmountOut(uint, address) external view returns (uint);
function claimFees() external returns (uint, uint);
function tokens() external view returns (address, address);
function token0() external view returns (address);
function token1() external view returns (address);
function stable() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IRouter {
struct Route {
address from;
address to;
bool stable;
}
function factory() external view returns (address);
function weth() external view returns (address);
function sortTokens(
address tokenA,
address tokenB
) external view returns (address token0, address token1);
function pairFor(
address tokenA,
address tokenB,
bool stable
) external view returns (address pair);
function quoteLiquidity(
uint amountA,
uint reserveA,
uint reserveB
) external view returns (uint amountB);
function getReserves(
address tokenA,
address tokenB,
bool stable
) external view returns (uint reserveA, uint reserveB);
/// @dev Performs chained getAmountOut calculations on any number of pairs.
function getAmountOut(
uint amountIn,
address tokenIn,
address tokenOut
) external view returns (uint amount, bool stable);
function getExactAmountOut(
uint amountIn,
address tokenIn,
address tokenOut,
bool stable
) external view returns (uint);
/// @dev Performs chained getAmountOut calculations on any number of pairs.
function getAmountsOut(
uint amountIn,
Route[] memory routes
) external view returns (uint[] memory amounts);
function isPair(address pair) external view returns (bool);
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired
) external view returns (uint amountA, uint amountB, uint liquidity);
function quoteRemoveLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity
) external view returns (uint amountA, uint amountB);
function addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
bool stable,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
)
external
payable
returns (uint amountToken, uint amountETH, uint liquidity);
// **** REMOVE LIQUIDITY ****
function removeLiquidity(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
bool stable,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
bool stable,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokensSimple(
uint amountIn,
uint amountOutMin,
address tokenFrom,
address tokenTo,
bool stable,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
Route[] calldata routes,
address to,
uint deadline
) external;
function UNSAFE_swapExactTokensForTokens(
uint[] memory amounts,
Route[] calldata routes,
address to,
uint deadline
) external returns (uint[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IWETH {
function name() external view returns (string memory);
function approve(address guy, uint256 wad) external returns (bool);
function totalSupply() external view returns (uint256);
function transferFrom(
address src,
address dst,
uint256 wad
) external returns (bool);
function withdraw(uint256 wad) external;
function decimals() external view returns (uint8);
function balanceOf(address) external view returns (uint256);
function symbol() external view returns (string memory);
function transfer(address dst, uint256 wad) external returns (bool);
function deposit() external payable;
function allowance(address, address) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.13;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
library Math {
function positiveInt128(int128 value) internal pure returns (int128) {
return value < 0 ? int128(0) : value;
}
function closeTo(uint a, uint b, uint target) internal pure returns (bool) {
if (a > b) {
if (a - b <= target) {
return true;
}
} else {
if (b - a <= target) {
return true;
}
}
return false;
}
// function sqrt(uint y) internal pure returns (uint z) {
// if (y > 3) {
// z = y;
// uint x = y / 2 + 1;
// while (x < z) {
// z = x;
// x = (y / x + x) / 2;
// }
// } else if (y != 0) {
// z = 1;
// }
// }
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(
uint256 a,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return
result +
(rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return
result +
(rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return
result +
(rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return
result +
(rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.13;
import "../interface/IERC20.sol";
import "./Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint value) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transfer.selector, to, value)
);
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint value
) internal {
uint newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(
data,
"SafeERC20: low-level call failed"
);
if (returndata.length > 0) {
// Return data is optional
require(
abi.decode(returndata, (bool)),
"SafeERC20: ERC20 operation did not succeed"
);
}
}
}{
"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":"_factory","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"UNSAFE_swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"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":"bool","name":"stable","type":"bool"},{"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":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"name":"getExactAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"name":"getReserves","outputs":[{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isPair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"name":"pairFor","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"}],"name":"quoteAddLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quoteLiquidity","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"name":"quoteRemoveLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"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":"bool","name":"stable","type":"bool"},{"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":"bool","name":"stable","type":"bool"},{"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":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"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":"bool","name":"stable","type":"bool"},{"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":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"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":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"sortTokens","outputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"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"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"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"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"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"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"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"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"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":"tokenFrom","type":"address"},{"internalType":"address","name":"tokenTo","type":"address"},{"internalType":"bool","name":"stable","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSimple","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct Router01.Route[]","name":"routes","type":"tuple[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e06040523480156200001157600080fd5b5060405162004cee38038062004cee8339810160408190526200003491620000d8565b6001600160a01b038216608081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa1580156200007f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a5919062000110565b60c0526001600160a01b031660a052506200012a565b80516001600160a01b0381168114620000d357600080fd5b919050565b60008060408385031215620000ec57600080fd5b620000f783620000bb565b91506200010760208401620000bb565b90509250929050565b6000602082840312156200012357600080fd5b5051919050565b60805160a05160c051614abb620002336000396000612b2f0152600081816101cb015281816102d0015281816108dd01528181610b3a01528181610d8b015281816111fc0152818161130f0152818161139d0152818161182a015281816118a80152818161191c01528181611b6d01528181611c7501528181611d20015281816121b7015281816121ed0152818161222b015281816122c0015281816124020152818161302b015281816130840152613a4901526000818161059301528181610c2001528181610fa1015281816110b501528181611da201528181612092015281816124d80152818161294101528181612af40152818161329501526133360152614abb6000f3fe6080604052600436106101bb5760003560e01c806376c72751116100ec578063b7e0d4c01161008a578063e2d9d4dc11610064578063e2d9d4dc146105d5578063e5e31b13146105f5578063f41766d814610625578063fe411f141461064557600080fd5b8063b7e0d4c01461056e578063c45a015514610581578063d7b0e0a5146105b557600080fd5b806398a0fb3c116100c657806398a0fb3c146104e0578063a32b1fcd14610500578063ae56886814610520578063b6710cb91461054e57600080fd5b806376c727511461048d5780637af728c8146104a05780639881fcb4146104c057600080fd5b8063544caa56116101595780635e60dab5116101335780635e60dab51461041a57806367ffb66a1461043a5780636cc1ae131461044d5780637301e3c81461046d57600080fd5b8063544caa561461036a5780635a47ddc3146103aa5780635e1e6325146103e557600080fd5b80633fc8cef3116101955780633fc8cef3146102be5780634386e63c1461030a578063448725b41461032a5780634c1ee03e1461034a57600080fd5b80630dede6c41461023757806313dcfc591461027157806318a130861461029e57600080fd5b3661023257336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146102305760405162461bcd60e51b815260206004820152601060248201526f0a4deeae8cae474409c9ea8beeecae8d60831b60448201526064015b60405180910390fd5b005b600080fd5b34801561024357600080fd5b50610257610252366004613dcc565b610665565b604080519283526020830191909152015b60405180910390f35b34801561027d57600080fd5b5061029161028c366004613e51565b610689565b6040516102689190613ecc565b3480156102aa57600080fd5b506102916102b9366004613f55565b6108b0565b3480156102ca57600080fd5b506102f27f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610268565b34801561031657600080fd5b50610257610325366004613fc8565b610c19565b34801561033657600080fd5b5061025761034536600461402a565b610d80565b34801561035657600080fd5b506102f26103653660046140d4565b610e59565b34801561037657600080fd5b5061038a61038536600461411f565b610e70565b604080516001600160a01b03938416815292909116602083015201610268565b3480156103b657600080fd5b506103ca6103c5366004614158565b610e89565b60408051938452602084019290925290820152606001610268565b3480156103f157600080fd5b506104056104003660046141e7565b610f69565b60408051928352901515602083015201610268565b34801561042657600080fd5b506102576104353660046140d4565b6111bd565b61029161044836600461421e565b6111d7565b34801561045957600080fd5b50610230610468366004613f55565b6114e2565b34801561047957600080fd5b506102916104883660046142f0565b61175a565b61023061049b36600461421e565b611807565b3480156104ac57600080fd5b506102306104bb366004613f55565b611b42565b3480156104cc57600080fd5b506102916104db366004614432565b611d8e565b3480156104ec57600080fd5b506103ca6104fb3660046144d8565b611d9a565b34801561050c57600080fd5b5061025761051b366004614533565b611f9a565b34801561052c57600080fd5b5061054061053b3660046145ef565b612055565b604051908152602001610268565b34801561055a57600080fd5b5061054061056936600461461b565b612062565b6103ca61057c36600461466e565b61218b565b34801561058d57600080fd5b506102f27f000000000000000000000000000000000000000000000000000000000000000081565b3480156105c157600080fd5b506102576105d036600461466e565b6123d5565b3480156105e157600080fd5b506102576105f036600461402a565b6123f7565b34801561060157600080fd5b506106156106103660046146c9565b6124b6565b6040519015158152602001610268565b34801561063157600080fd5b50610291610640366004613f55565b61254b565b34801561065157600080fd5b5061025761066036600461466e565b612674565b6000806106788a8a8a8a8a8a8a8a612686565b915091509850989650505050505050565b606081428110156106ac5760405162461bcd60e51b8152600401610227906146e6565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816106c357905050905087816000815181106107065761070661470f565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061073e5761073e61470f565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107765761077661470f565b60209081029190910101519015156040909101526107948a8261282b565b92508883600185516107a6919061473b565b815181106107b6576107b661470f565b602002602001015110156107dc5760405162461bcd60e51b815260040161022790614752565b61089833610845836000815181106107f6576107f661470f565b602002602001015160000151846000815181106108155761081561470f565b602002602001015160200151856000815181106108345761083461470f565b602002602001015160400151612aad565b856000815181106108585761085861470f565b6020026020010151846000815181106108735761087361470f565b6020026020010151600001516001600160a01b0316612bb5909392919063ffffffff16565b6108a3838287612c26565b5050979650505050505050565b606081428110156108d35760405162461bcd60e51b8152600401610227906146e6565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016868661090a60018261473b565b8181106109195761091961470f565b905060600201602001602081019061093191906146c9565b6001600160a01b0316146109575760405162461bcd60e51b815260040161022790614794565b6109b3888787808060200260200160405190810160405280939291908181526020016000905b828210156109a95761099a606083028601368190038101906147c2565b8152602001906001019061097d565b505050505061282b565b91508682600184516109c5919061473b565b815181106109d5576109d561470f565b602002602001015110156109fb5760405162461bcd60e51b815260040161022790614752565b610adb33610a8688886000818110610a1557610a1561470f565b610a2b92602060609092020190810191506146c9565b89896000818110610a3e57610a3e61470f565b9050606002016020016020810190610a5691906146c9565b8a8a6000818110610a6957610a6961470f565b9050606002016040016020810190610a8191906147de565b612aad565b84600081518110610a9957610a9961470f565b602002602001015189896000818110610ab457610ab461470f565b610aca92602060609092020190810191506146c9565b6001600160a01b0316929190612bb5565b610b38828787808060200260200160405190810160405280939291908181526020016000905b82821015610b2d57610b1e606083028601368190038101906147c2565b81526020019060010190610b01565b505050505030612c26565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610b76919061473b565b81518110610b8657610b8661470f565b60200260200101516040518263ffffffff1660e01b8152600401610bac91815260200190565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b50505050610c0e848360018551610bf1919061473b565b81518110610c0157610c0161470f565b6020026020010151612e75565b509695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c6e939291906147fb565b602060405180830381865afa158015610c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caf919061481f565b90506001600160a01b038116610ccc576000809250925050610d77565b600080610cda898989612f37565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d42919061483c565b905080610d4f8489614855565b610d59919061488a565b955080610d668389614855565b610d70919061488a565b9450505050505b94509492505050565b6000806000610db08e7f00000000000000000000000000000000000000000000000000000000000000008f612aad565b9050600087610dbf578c610dc3565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610dfe903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b158015610e1857600080fd5b505af1158015610e2c573d6000803e3d6000fd5b50505050610e3f8f8f8f8f8f8f8f613001565b809450819550505050509b509b9950505050505050505050565b6000610e66848484612aad565b90505b9392505050565b600080610e7d84846130ff565b915091505b9250929050565b60008060008342811015610eaf5760405162461bcd60e51b8152600401610227906146e6565b610ebe8d8d8d8d8d8d8d6131d8565b90945092506000610ed08e8e8e612aad565b9050610ede8e338388612bb5565b610eea8d338387612bb5565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061483c565b9250505099509950999650505050505050565b6000806000610f7a85856001612aad565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa158015610fea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100e91906148ed565b15611087576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611060573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611084919061483c565b91505b61109387876000612aad565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156110fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112291906148ed565b1561119b576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061483c565b90505b8082116111aa578060006111ae565b8160015b94509450505050935093915050565b6000806111cb858585612f37565b91509150935093915050565b606081428110156111fa5760405162461bcd60e51b8152600401610227906146e6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316868660008181106112375761123761470f565b61124d92602060609092020190810191506146c9565b6001600160a01b0316146112735760405162461bcd60e51b815260040161022790614794565b6112c5348787808060200260200160405190810160405280939291908181526020016000905b828210156109a9576112b6606083028601368190038101906147c2565b81526020019060010190611299565b91508682600184516112d7919061473b565b815181106112e7576112e761470f565b6020026020010151101561130d5760405162461bcd60e51b815260040161022790614752565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08360008151811061134f5761134f61470f565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561138257600080fd5b505af1158015611396573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6113e088886000818110610a1557610a1561470f565b846000815181106113f3576113f361470f565b60200260200101516040518363ffffffff1660e01b815260040161142c9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561144b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146f91906148ed565b61147b5761147b61490a565b6114d8828787808060200260200160405190810160405280939291908181526020016000905b828210156114cd576114be606083028601368190038101906147c2565b815260200190600101906114a1565b505050505086612c26565b5095945050505050565b80428110156115035760405162461bcd60e51b8152600401610227906146e6565b611585336115718787600081811061151d5761151d61470f565b61153392602060609092020190810191506146c9565b888860008181106115465761154661470f565b905060600201602001602081019061155e91906146c9565b89896000818110610a6957610a6961470f565b8988886000818110610ab457610ab461470f565b6000858561159460018261473b565b8181106115a3576115a361470f565b90506060020160200160208101906115bb91906146c9565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa158015611603573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611627919061483c565b90506116858686808060200260200160405190810160405280939291908181526020016000905b8282101561167a5761166b606083028601368190038101906147c2565b8152602001906001019061164e565b5050505050856134dc565b8681878761169460018261473b565b8181106116a3576116a361470f565b90506060020160200160208101906116bb91906146c9565b6040516370a0823160e01b81526001600160a01b03888116600483015291909116906370a08231906024015b602060405180830381865afa158015611704573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611728919061483c565b611732919061473b565b10156117505760405162461bcd60e51b815260040161022790614752565b5050505050505050565b6060814281101561177d5760405162461bcd60e51b8152600401610227906146e6565b6117aa3361179788886000818110610a1557610a1561470f565b89600081518110610a9957610a9961470f565b6117fc878787808060200260200160405190810160405280939291908181526020016000905b828210156114cd576117ed606083028601368190038101906147c2565b815260200190600101906117d0565b509495945050505050565b80428110156118285760405162461bcd60e51b8152600401610227906146e6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316858560008181106118655761186561470f565b61187b92602060609092020190810191506146c9565b6001600160a01b0316146118a15760405162461bcd60e51b815260040161022790614794565b60003490507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561190157600080fd5b505af1158015611915573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb61195f88886000818110610a1557610a1561470f565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156119ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d091906148ed565b6119dc576119dc61490a565b600086866119eb60018261473b565b8181106119fa576119fa61470f565b9050606002016020016020810190611a1291906146c9565b6040516370a0823160e01b81526001600160a01b03878116600483015291909116906370a0823190602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e919061483c565b9050611adc8787808060200260200160405190810160405280939291908181526020016000905b82821015611ad157611ac2606083028601368190038101906147c2565b81526020019060010190611aa5565b5050505050866134dc565b87818888611aeb60018261473b565b818110611afa57611afa61470f565b9050606002016020016020810190611b1291906146c9565b6040516370a0823160e01b81526001600160a01b03898116600483015291909116906370a08231906024016116e7565b8042811015611b635760405162461bcd60e51b8152600401610227906146e6565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168585611b9a60018261473b565b818110611ba957611ba961470f565b9050606002016020016020810190611bc191906146c9565b6001600160a01b031614611be75760405162461bcd60e51b815260040161022790614794565b611c01336115718787600081811061151d5761151d61470f565b611c5d8585808060200260200160405190810160405280939291908181526020016000905b82821015611c5257611c43606083028601368190038101906147c2565b81526020019060010190611c26565b5050505050306134dc565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce8919061483c565b905086811015611d0a5760405162461bcd60e51b815260040161022790614752565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050506117508482612e75565b6060610e69838361282b565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611df0939291906147fb565b602060405180830381865afa158015611e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e31919061481f565b9050600080806001600160a01b03841615611ebb57836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea8919061483c565b9050611eb58c8c8c612f37565b90935091505b82158015611ec7575081155b15611ef8578896508795506103e8611ee7611ee2888a614855565b61385f565b611ef1919061473b565b9450611f8b565b6000611f058a8585613947565b9050888111611f4d57899750955085611f4684611f22848b614855565b611f2c919061488a565b84611f37858b614855565b611f41919061488a565b613a09565b9550611f89565b6000611f5a8a8587613947565b9850899750889050611f8585611f708584614855565b611f7a919061488a565b85611f37868c614855565b9650505b505b50505050955095509592505050565b6000806000611faa8f8f8f612aad565b9050600087611fb9578c611fbd565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611ff8903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b15801561201257600080fd5b505af1158015612026573d6000803e3d6000fd5b505050505061203b8f8f8f8f8f8f8f8f612686565b8093508194505050509c509c9a5050505050505050505050565b6000610e66848484613947565b600080612070858585612aad565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156120db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ff91906148ed565b1561217d576040516378a051ad60e11b8152600481018790526001600160a01b03868116602483015282169063f140a35a90604401602060405180830381865afa158015612151573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612175919061483c565b915050612183565b60009150505b949350505050565b600080600083428110156121b15760405162461bcd60e51b8152600401610227906146e6565b6121e08b7f00000000000000000000000000000000000000000000000000000000000000008c8c348d8d6131d8565b909450925060006122128c7f00000000000000000000000000000000000000000000000000000000000000008d612aad565b90506122296001600160a01b038d16338388612bb5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561228457600080fd5b505af1158015612298573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af115801561230d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233191906148ed565b61233d5761233d61490a565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015612385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a9919061483c565b9250833411156123c6576123c6336123c1863461473b565b612e75565b50509750975097945050505050565b6000806123e789898989898989613001565b9150915097509795505050505050565b60008060006124278e7f00000000000000000000000000000000000000000000000000000000000000008f612aad565b9050600087612436578c61243a565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90612475903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b15801561248f57600080fd5b505af11580156124a3573d6000803e3d6000fd5b50505050610e3f8f8f8f8f8f8f8f613a1f565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa158015612521573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254591906148ed565b92915050565b6060814281101561256e5760405162461bcd60e51b8152600401610227906146e6565b6125c0888787808060200260200160405190810160405280939291908181526020016000905b828210156109a9576125b1606083028601368190038101906147c2565b81526020019060010190612594565b91508682600184516125d2919061473b565b815181106125e2576125e261470f565b602002602001015110156126085760405162461bcd60e51b815260040161022790614752565b61262233610a8688886000818110610a1557610a1561470f565b610c0e828787808060200260200160405190810160405280939291908181526020016000905b828210156114cd57612665606083028601368190038101906147c2565b81526020019060010190612648565b6000806123e789898989898989613a1f565b60008082428110156126aa5760405162461bcd60e51b8152600401610227906146e6565b60006126b78c8c8c612aad565b90506126ce6001600160a01b03821633838c612bb5565b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af115801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190614920565b91509150600061274e8f8f6130ff565b509050806001600160a01b03168f6001600160a01b031614612771578183612774565b82825b90975095508a8710156127c95760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e540000006044820152606401610227565b898610156128195760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e540000006044820152606401610227565b50505050509850989650505050505050565b606060018251101561284f5760405162461bcd60e51b815260040161022790614794565b815161285c906001614944565b67ffffffffffffffff81111561287457612874614285565b60405190808252806020026020018201604052801561289d578160200160208202803683370190505b50905082816000815181106128b4576128b461470f565b60200260200101818152505060005b8251811015612aa657600061291f8483815181106128e3576128e361470f565b6020026020010151600001518584815181106129015761290161470f565b6020026020010151602001518685815181106108345761083461470f565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561298a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ae91906148ed565b15612a9357806001600160a01b031663f140a35a8484815181106129d4576129d461470f565b60200260200101518685815181106129ee576129ee61470f565b6020026020010151600001516040518363ffffffff1660e01b8152600401612a299291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a919061483c565b83612a76846001614944565b81518110612a8657612a8661470f565b6020026020010181815250505b5080612a9e8161495c565b9150506128c3565b5092915050565b6000806000612abc86866130ff565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001612b93939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052612c209085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613af7565b50505050565b60005b8251811015612c20576000612c78848381518110612c4957612c4961470f565b602002602001015160000151858481518110612c6757612c6761470f565b6020026020010151602001516130ff565b509050600085612c89846001614944565b81518110612c9957612c9961470f565b60200260200101519050600080836001600160a01b0316878681518110612cc257612cc261470f565b6020026020010151600001516001600160a01b031614612ce457826000612ce8565b6000835b91509150600060018851612cfc919061473b565b8610612d085786612d7b565b612d7b88612d17886001614944565b81518110612d2757612d2761470f565b60200260200101516000015189886001612d419190614944565b81518110612d5157612d5161470f565b6020026020010151602001518a896001612d6b9190614944565b815181106108345761083461470f565b9050612dce888781518110612d9257612d9261470f565b602002602001015160000151898881518110612db057612db061470f565b6020026020010151602001518a89815181106108345761083461470f565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612e0b576020820181803683370190505b506040518563ffffffff1660e01b8152600401612e2b94939291906149cd565b600060405180830381600087803b158015612e4557600080fd5b505af1158015612e59573d6000803e3d6000fd5b5050505050505050508080612e6d9061495c565b915050612c29565b604080516000808252602082019092526001600160a01b038416908390604051612e9f91906149fa565b60006040518083038185875af1925050503d8060008114612edc576040519150601f19603f3d011682016040523d82523d6000602084013e612ee1565b606091505b5050905080612f325760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204554485f5452414e534645525f4641494c454400000000006044820152606401610227565b505050565b6000806000612f4686866130ff565b509050600080612f57888888612aad565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb89190614a2d565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b031614612fef578082612ff2565b81815b90999098509650505050505050565b60008082428110156130255760405162461bcd60e51b8152600401610227906146e6565b6130558a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b612686565b909350915061306e6001600160a01b038b168685613bc9565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156130d057600080fd5b505af11580156130e4573d6000803e3d6000fd5b505050506130f28583612e75565b5097509795505050505050565b600080826001600160a01b0316846001600160a01b0316036131635760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f41444452455353455300000000006044820152606401610227565b826001600160a01b0316846001600160a01b031610613183578284613186565b83835b90925090506001600160a01b038216610e825760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b6044820152606401610227565b6000808386101561322b5760405162461bcd60e51b815260206004820152601860248201527f526f757465723a20444553495245445f415f414d4f554e5400000000000000006044820152606401610227565b8285101561327b5760405162461bcd60e51b815260206004820152601860248201527f526f757465723a20444553495245445f425f414d4f554e5400000000000000006044820152606401610227565b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636801cc30906132ce908d908d908d906004016147fb565b602060405180830381865afa1580156132eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330f919061481f565b90506001600160a01b0381166133b5576040516320b7f73960e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906382dfdce49061336f908d908d908d906004016147fb565b6020604051808303816000875af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b2919061481f565b90505b6000806133c38c8c8c612f37565b915091508160001480156133d5575080155b156133e5578894508793506134cd565b60006133f28a8484613947565b9050888111613456578681101561344b5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e540000006044820152606401610227565b8995509350836134cb565b60006134638a8486613947565b90508a8111156134755761347561490a565b888110156134c55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e540000006044820152606401610227565b95508894505b505b50505097509795505050505050565b60005b8251811015612f32576000808483815181106134fd576134fd61470f565b60200260200101516000015185848151811061351b5761351b61470f565b60200260200101516020015191509150600061353783836130ff565b509050600061358d8786815181106135515761355161470f565b60200260200101516000015188878151811061356f5761356f61470f565b6020026020010151602001518988815181106108345761083461470f565b9050600080600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156135d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f79190614a2d565b506001600160701b031691506001600160701b031691506000866001600160a01b0316896001600160a01b03161461362f5781613631565b825b6040516370a0823160e01b81526001600160a01b03888116600483015291925082918b16906370a0823190602401602060405180830381865afa15801561367c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a0919061483c565b6136aa919061473b565b6040516378a051ad60e11b8152600481018290526001600160a01b038b811660248301529196509087169063f140a35a90604401602060405180830381865afa1580156136fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371f919061483c565b9350505050600080856001600160a01b0316886001600160a01b0316146137485782600061374c565b6000835b91509150600060018c51613760919061473b565b8a1061376c578a6137cf565b6137cf8c61377b8c6001614944565b8151811061378b5761378b61470f565b6020026020010151600001518d8c60016137a59190614944565b815181106137b5576137b561470f565b6020026020010151602001518e8d6001612d6b9190614944565b6040805160008152602081019182905263022c0d9f60e01b9091529091506001600160a01b0387169063022c0d9f9061381190869086908690602481016149cd565b600060405180830381600087803b15801561382b57600080fd5b505af115801561383f573d6000803e3d6000fd5b5050505050505050505050505080806138579061495c565b9150506134df565b60008160000361387157506000919050565b6000600161387e84613bf9565b901c6001901b9050600181848161389757613897614874565b048201901c905060018184816138af576138af614874565b048201901c905060018184816138c7576138c7614874565b048201901c905060018184816138df576138df614874565b048201901c905060018184816138f7576138f7614874565b048201901c9050600181848161390f5761390f614874565b048201901c9050600181848161392757613927614874565b048201901c9050610e698182858161394157613941614874565b04613a09565b60008084116139985760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e5400000000006044820152606401610227565b6000831180156139a85750600082115b6139f45760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c495155494449545900006044820152606401610227565b826139ff8386614855565b610e66919061488a565b6000818310613a185781610e69565b5090919050565b6000808242811015613a435760405162461bcd60e51b8152600401610227906146e6565b613a738a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b8b308b612686565b6040516370a0823160e01b8152306004820152919450925061306e9086906001600160a01b038d16906370a0823190602401602060405180830381865afa158015613ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae6919061483c565b6001600160a01b038d169190613bc9565b6000613b4c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613c8d9092919063ffffffff16565b805190915015612f325780806020019051810190613b6a91906148ed565b612f325760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610227565b6040516001600160a01b038316602482015260448101829052612f3290849063a9059cbb60e01b90606401612be9565b600080608083901c15613c0e57608092831c92015b604083901c15613c2057604092831c92015b602083901c15613c3257602092831c92015b601083901c15613c4457601092831c92015b600883901c15613c5657600892831c92015b600483901c15613c6857600492831c92015b600283901c15613c7a57600292831c92015b600183901c156125455760010192915050565b60606001600160a01b0384163b613ce65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610227565b600080856001600160a01b031685604051613d0191906149fa565b6000604051808303816000865af19150503d8060008114613d3e576040519150601f19603f3d011682016040523d82523d6000602084013e613d43565b606091505b5091509150613d53828286613d5d565b9695505050505050565b60608315613d6c575081610e69565b825115613d7c5782518084602001fd5b8160405162461bcd60e51b81526004016102279190614a72565b6001600160a01b0381168114613dab57600080fd5b50565b8035613db981613d96565b919050565b8015158114613dab57600080fd5b600080600080600080600080610100898b031215613de957600080fd5b8835613df481613d96565b97506020890135613e0481613d96565b96506040890135613e1481613dbe565b9550606089013594506080890135935060a0890135925060c0890135613e3981613d96565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215613e6c57600080fd5b87359650602088013595506040880135613e8581613d96565b94506060880135613e9581613d96565b93506080880135613ea581613dbe565b925060a0880135613eb581613d96565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015613f0457835183529284019291840191600101613ee8565b50909695505050505050565b60008083601f840112613f2257600080fd5b50813567ffffffffffffffff811115613f3a57600080fd5b602083019150836020606083028501011115610e8257600080fd5b60008060008060008060a08789031215613f6e57600080fd5b8635955060208701359450604087013567ffffffffffffffff811115613f9357600080fd5b613f9f89828a01613f10565b9095509350506060870135613fb381613d96565b80925050608087013590509295509295509295565b60008060008060808587031215613fde57600080fd5b8435613fe981613d96565b93506020850135613ff981613d96565b9250604085013561400981613dbe565b9396929550929360600135925050565b803560ff81168114613db957600080fd5b60008060008060008060008060008060006101608c8e03121561404c57600080fd5b8b3561405781613d96565b9a5060208c013561406781613dbe565b995060408c0135985060608c0135975060808c0135965060a08c013561408c81613d96565b955060c08c0135945060e08c01356140a381613dbe565b93506140b26101008d01614019565b92506101208c013591506101408c013590509295989b509295989b9093969950565b6000806000606084860312156140e957600080fd5b83356140f481613d96565b9250602084013561410481613d96565b9150604084013561411481613dbe565b809150509250925092565b6000806040838503121561413257600080fd5b823561413d81613d96565b9150602083013561414d81613d96565b809150509250929050565b60008060008060008060008060006101208a8c03121561417757600080fd5b893561418281613d96565b985060208a013561419281613d96565b975060408a01356141a281613dbe565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356141ce81613d96565b809250506101008a013590509295985092959850929598565b6000806000606084860312156141fc57600080fd5b83359250602084013561420e81613d96565b9150604084013561411481613d96565b60008060008060006080868803121561423657600080fd5b85359450602086013567ffffffffffffffff81111561425457600080fd5b61426088828901613f10565b909550935050604086013561427481613d96565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156142c4576142c4614285565b604052919050565b600067ffffffffffffffff8211156142e6576142e6614285565b5060051b60200190565b60008060008060006080868803121561430857600080fd5b853567ffffffffffffffff8082111561432057600080fd5b818801915088601f83011261433457600080fd5b81356020614349614344836142cc565b61429b565b82815260059290921b8401810191818101908c84111561436857600080fd5b948201945b838610156143865785358252948201949082019061436d565b9950508901359250508082111561439c57600080fd5b506143a988828901613f10565b9095509350614274905060408701613dae565b6000606082840312156143ce57600080fd5b6040516060810181811067ffffffffffffffff821117156143f1576143f1614285565b604052905080823561440281613d96565b8152602083013561441281613d96565b6020820152604083013561442581613dbe565b6040919091015292915050565b6000806040838503121561444557600080fd5b8235915060208084013567ffffffffffffffff81111561446457600080fd5b8401601f8101861361447557600080fd5b8035614483614344826142cc565b818152606091820283018401918482019190898411156144a257600080fd5b938501935b838510156144c8576144b98a866143bc565b835293840193918501916144a7565b5080955050505050509250929050565b600080600080600060a086880312156144f057600080fd5b85356144fb81613d96565b9450602086013561450b81613d96565b9350604086013561451b81613dbe565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561455657600080fd5b8c3561456181613d96565b9b5060208d013561457181613d96565b9a5060408d013561458181613dbe565b995060608d0135985060808d0135975060a08d0135965060c08d01356145a681613d96565b955060e08d013594506101008d01356145be81613dbe565b93506145cd6101208e01614019565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008060006060848603121561460457600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561463157600080fd5b84359350602085013561464381613d96565b9250604085013561465381613d96565b9150606085013561466381613dbe565b939692955090935050565b600080600080600080600060e0888a03121561468957600080fd5b873561469481613d96565b965060208801356146a481613dbe565b955060408801359450606088013593506080880135925060a0880135613eb581613d96565b6000602082840312156146db57600080fd5b8135610e6981613d96565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008282101561474d5761474d614725565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b6000606082840312156147d457600080fd5b610e6983836143bc565b6000602082840312156147f057600080fd5b8135610e6981613dbe565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006020828403121561483157600080fd5b8151610e6981613d96565b60006020828403121561484e57600080fd5b5051919050565b600081600019048311821515161561486f5761486f614725565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826148a757634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000602082840312156148ff57600080fd5b8151610e6981613dbe565b634e487b7160e01b600052600160045260246000fd5b6000806040838503121561493357600080fd5b505080516020909101519092909150565b6000821982111561495757614957614725565b500190565b60006001820161496e5761496e614725565b5060010190565b60005b83811015614990578181015183820152602001614978565b83811115612c205750506000910152565b600081518084526149b9816020860160208601614975565b601f01601f19169290920160200192915050565b84815283602082015260018060a01b0383166040820152608060608201526000613d5360808301846149a1565b60008251614a0c818460208701614975565b9190910192915050565b80516001600160701b0381168114613db957600080fd5b600080600060608486031215614a4257600080fd5b614a4b84614a16565b9250614a5960208501614a16565b9150604084015163ffffffff8116811461411457600080fd5b602081526000610e6960208301846149a156fea2646970667358221220af615a075db703e4cceab696c74e0b376e8734bad94c3100c2660089869070a864736f6c634300080d003300000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8140000000000000000000000005300000000000000000000000000000000000004
Deployed Bytecode
0x6080604052600436106101bb5760003560e01c806376c72751116100ec578063b7e0d4c01161008a578063e2d9d4dc11610064578063e2d9d4dc146105d5578063e5e31b13146105f5578063f41766d814610625578063fe411f141461064557600080fd5b8063b7e0d4c01461056e578063c45a015514610581578063d7b0e0a5146105b557600080fd5b806398a0fb3c116100c657806398a0fb3c146104e0578063a32b1fcd14610500578063ae56886814610520578063b6710cb91461054e57600080fd5b806376c727511461048d5780637af728c8146104a05780639881fcb4146104c057600080fd5b8063544caa56116101595780635e60dab5116101335780635e60dab51461041a57806367ffb66a1461043a5780636cc1ae131461044d5780637301e3c81461046d57600080fd5b8063544caa561461036a5780635a47ddc3146103aa5780635e1e6325146103e557600080fd5b80633fc8cef3116101955780633fc8cef3146102be5780634386e63c1461030a578063448725b41461032a5780634c1ee03e1461034a57600080fd5b80630dede6c41461023757806313dcfc591461027157806318a130861461029e57600080fd5b3661023257336001600160a01b037f000000000000000000000000530000000000000000000000000000000000000416146102305760405162461bcd60e51b815260206004820152601060248201526f0a4deeae8cae474409c9ea8beeecae8d60831b60448201526064015b60405180910390fd5b005b600080fd5b34801561024357600080fd5b50610257610252366004613dcc565b610665565b604080519283526020830191909152015b60405180910390f35b34801561027d57600080fd5b5061029161028c366004613e51565b610689565b6040516102689190613ecc565b3480156102aa57600080fd5b506102916102b9366004613f55565b6108b0565b3480156102ca57600080fd5b506102f27f000000000000000000000000530000000000000000000000000000000000000481565b6040516001600160a01b039091168152602001610268565b34801561031657600080fd5b50610257610325366004613fc8565b610c19565b34801561033657600080fd5b5061025761034536600461402a565b610d80565b34801561035657600080fd5b506102f26103653660046140d4565b610e59565b34801561037657600080fd5b5061038a61038536600461411f565b610e70565b604080516001600160a01b03938416815292909116602083015201610268565b3480156103b657600080fd5b506103ca6103c5366004614158565b610e89565b60408051938452602084019290925290820152606001610268565b3480156103f157600080fd5b506104056104003660046141e7565b610f69565b60408051928352901515602083015201610268565b34801561042657600080fd5b506102576104353660046140d4565b6111bd565b61029161044836600461421e565b6111d7565b34801561045957600080fd5b50610230610468366004613f55565b6114e2565b34801561047957600080fd5b506102916104883660046142f0565b61175a565b61023061049b36600461421e565b611807565b3480156104ac57600080fd5b506102306104bb366004613f55565b611b42565b3480156104cc57600080fd5b506102916104db366004614432565b611d8e565b3480156104ec57600080fd5b506103ca6104fb3660046144d8565b611d9a565b34801561050c57600080fd5b5061025761051b366004614533565b611f9a565b34801561052c57600080fd5b5061054061053b3660046145ef565b612055565b604051908152602001610268565b34801561055a57600080fd5b5061054061056936600461461b565b612062565b6103ca61057c36600461466e565b61218b565b34801561058d57600080fd5b506102f27f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b81481565b3480156105c157600080fd5b506102576105d036600461466e565b6123d5565b3480156105e157600080fd5b506102576105f036600461402a565b6123f7565b34801561060157600080fd5b506106156106103660046146c9565b6124b6565b6040519015158152602001610268565b34801561063157600080fd5b50610291610640366004613f55565b61254b565b34801561065157600080fd5b5061025761066036600461466e565b612674565b6000806106788a8a8a8a8a8a8a8a612686565b915091509850989650505050505050565b606081428110156106ac5760405162461bcd60e51b8152600401610227906146e6565b604080516001808252818301909252600091816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816106c357905050905087816000815181106107065761070661470f565b6020026020010151600001906001600160a01b031690816001600160a01b031681525050868160008151811061073e5761073e61470f565b6020026020010151602001906001600160a01b031690816001600160a01b03168152505085816000815181106107765761077661470f565b60209081029190910101519015156040909101526107948a8261282b565b92508883600185516107a6919061473b565b815181106107b6576107b661470f565b602002602001015110156107dc5760405162461bcd60e51b815260040161022790614752565b61089833610845836000815181106107f6576107f661470f565b602002602001015160000151846000815181106108155761081561470f565b602002602001015160200151856000815181106108345761083461470f565b602002602001015160400151612aad565b856000815181106108585761085861470f565b6020026020010151846000815181106108735761087361470f565b6020026020010151600001516001600160a01b0316612bb5909392919063ffffffff16565b6108a3838287612c26565b5050979650505050505050565b606081428110156108d35760405162461bcd60e51b8152600401610227906146e6565b6001600160a01b037f000000000000000000000000530000000000000000000000000000000000000416868661090a60018261473b565b8181106109195761091961470f565b905060600201602001602081019061093191906146c9565b6001600160a01b0316146109575760405162461bcd60e51b815260040161022790614794565b6109b3888787808060200260200160405190810160405280939291908181526020016000905b828210156109a95761099a606083028601368190038101906147c2565b8152602001906001019061097d565b505050505061282b565b91508682600184516109c5919061473b565b815181106109d5576109d561470f565b602002602001015110156109fb5760405162461bcd60e51b815260040161022790614752565b610adb33610a8688886000818110610a1557610a1561470f565b610a2b92602060609092020190810191506146c9565b89896000818110610a3e57610a3e61470f565b9050606002016020016020810190610a5691906146c9565b8a8a6000818110610a6957610a6961470f565b9050606002016040016020810190610a8191906147de565b612aad565b84600081518110610a9957610a9961470f565b602002602001015189896000818110610ab457610ab461470f565b610aca92602060609092020190810191506146c9565b6001600160a01b0316929190612bb5565b610b38828787808060200260200160405190810160405280939291908181526020016000905b82821015610b2d57610b1e606083028601368190038101906147c2565b81526020019060010190610b01565b505050505030612c26565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b0316632e1a7d4d8360018551610b76919061473b565b81518110610b8657610b8661470f565b60200260200101516040518263ffffffff1660e01b8152600401610bac91815260200190565b600060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b50505050610c0e848360018551610bf1919061473b565b81518110610c0157610c0161470f565b6020026020010151612e75565b509695505050505050565b60008060007f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8146001600160a01b0316636801cc308888886040518463ffffffff1660e01b8152600401610c6e939291906147fb565b602060405180830381865afa158015610c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caf919061481f565b90506001600160a01b038116610ccc576000809250925050610d77565b600080610cda898989612f37565b915091506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d42919061483c565b905080610d4f8489614855565b610d59919061488a565b955080610d668389614855565b610d70919061488a565b9450505050505b94509492505050565b6000806000610db08e7f00000000000000000000000053000000000000000000000000000000000000048f612aad565b9050600087610dbf578c610dc3565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90610dfe903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b158015610e1857600080fd5b505af1158015610e2c573d6000803e3d6000fd5b50505050610e3f8f8f8f8f8f8f8f613001565b809450819550505050509b509b9950505050505050505050565b6000610e66848484612aad565b90505b9392505050565b600080610e7d84846130ff565b915091505b9250929050565b60008060008342811015610eaf5760405162461bcd60e51b8152600401610227906146e6565b610ebe8d8d8d8d8d8d8d6131d8565b90945092506000610ed08e8e8e612aad565b9050610ede8e338388612bb5565b610eea8d338387612bb5565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015610f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f56919061483c565b9250505099509950999650505050505050565b6000806000610f7a85856001612aad565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8149091169063e5e31b1390602401602060405180830381865afa158015610fea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100e91906148ed565b15611087576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611060573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611084919061483c565b91505b61109387876000612aad565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8149091169063e5e31b1390602401602060405180830381865afa1580156110fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112291906148ed565b1561119b576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061483c565b90505b8082116111aa578060006111ae565b8160015b94509450505050935093915050565b6000806111cb858585612f37565b91509150935093915050565b606081428110156111fa5760405162461bcd60e51b8152600401610227906146e6565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b0316868660008181106112375761123761470f565b61124d92602060609092020190810191506146c9565b6001600160a01b0316146112735760405162461bcd60e51b815260040161022790614794565b6112c5348787808060200260200160405190810160405280939291908181526020016000905b828210156109a9576112b6606083028601368190038101906147c2565b81526020019060010190611299565b91508682600184516112d7919061473b565b815181106112e7576112e761470f565b6020026020010151101561130d5760405162461bcd60e51b815260040161022790614752565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031663d0e30db08360008151811061134f5761134f61470f565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561138257600080fd5b505af1158015611396573d6000803e3d6000fd5b50505050507f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031663a9059cbb6113e088886000818110610a1557610a1561470f565b846000815181106113f3576113f361470f565b60200260200101516040518363ffffffff1660e01b815260040161142c9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561144b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146f91906148ed565b61147b5761147b61490a565b6114d8828787808060200260200160405190810160405280939291908181526020016000905b828210156114cd576114be606083028601368190038101906147c2565b815260200190600101906114a1565b505050505086612c26565b5095945050505050565b80428110156115035760405162461bcd60e51b8152600401610227906146e6565b611585336115718787600081811061151d5761151d61470f565b61153392602060609092020190810191506146c9565b888860008181106115465761154661470f565b905060600201602001602081019061155e91906146c9565b89896000818110610a6957610a6961470f565b8988886000818110610ab457610ab461470f565b6000858561159460018261473b565b8181106115a3576115a361470f565b90506060020160200160208101906115bb91906146c9565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa158015611603573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611627919061483c565b90506116858686808060200260200160405190810160405280939291908181526020016000905b8282101561167a5761166b606083028601368190038101906147c2565b8152602001906001019061164e565b5050505050856134dc565b8681878761169460018261473b565b8181106116a3576116a361470f565b90506060020160200160208101906116bb91906146c9565b6040516370a0823160e01b81526001600160a01b03888116600483015291909116906370a08231906024015b602060405180830381865afa158015611704573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611728919061483c565b611732919061473b565b10156117505760405162461bcd60e51b815260040161022790614752565b5050505050505050565b6060814281101561177d5760405162461bcd60e51b8152600401610227906146e6565b6117aa3361179788886000818110610a1557610a1561470f565b89600081518110610a9957610a9961470f565b6117fc878787808060200260200160405190810160405280939291908181526020016000905b828210156114cd576117ed606083028601368190038101906147c2565b815260200190600101906117d0565b509495945050505050565b80428110156118285760405162461bcd60e51b8152600401610227906146e6565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b0316858560008181106118655761186561470f565b61187b92602060609092020190810191506146c9565b6001600160a01b0316146118a15760405162461bcd60e51b815260040161022790614794565b60003490507f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561190157600080fd5b505af1158015611915573d6000803e3d6000fd5b50505050507f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031663a9059cbb61195f88886000818110610a1557610a1561470f565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156119ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119d091906148ed565b6119dc576119dc61490a565b600086866119eb60018261473b565b8181106119fa576119fa61470f565b9050606002016020016020810190611a1291906146c9565b6040516370a0823160e01b81526001600160a01b03878116600483015291909116906370a0823190602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e919061483c565b9050611adc8787808060200260200160405190810160405280939291908181526020016000905b82821015611ad157611ac2606083028601368190038101906147c2565b81526020019060010190611aa5565b5050505050866134dc565b87818888611aeb60018261473b565b818110611afa57611afa61470f565b9050606002016020016020810190611b1291906146c9565b6040516370a0823160e01b81526001600160a01b03898116600483015291909116906370a08231906024016116e7565b8042811015611b635760405162461bcd60e51b8152600401610227906146e6565b6001600160a01b037f0000000000000000000000005300000000000000000000000000000000000004168585611b9a60018261473b565b818110611ba957611ba961470f565b9050606002016020016020810190611bc191906146c9565b6001600160a01b031614611be75760405162461bcd60e51b815260040161022790614794565b611c01336115718787600081811061151d5761151d61470f565b611c5d8585808060200260200160405190810160405280939291908181526020016000905b82821015611c5257611c43606083028601368190038101906147c2565b81526020019060010190611c26565b5050505050306134dc565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000053000000000000000000000000000000000000046001600160a01b0316906370a0823190602401602060405180830381865afa158015611cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce8919061483c565b905086811015611d0a5760405162461bcd60e51b815260040161022790614752565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050506117508482612e75565b6060610e69838361282b565b6000806000807f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8146001600160a01b0316636801cc308a8a8a6040518463ffffffff1660e01b8152600401611df0939291906147fb565b602060405180830381865afa158015611e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e31919061481f565b9050600080806001600160a01b03841615611ebb57836001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea8919061483c565b9050611eb58c8c8c612f37565b90935091505b82158015611ec7575081155b15611ef8578896508795506103e8611ee7611ee2888a614855565b61385f565b611ef1919061473b565b9450611f8b565b6000611f058a8585613947565b9050888111611f4d57899750955085611f4684611f22848b614855565b611f2c919061488a565b84611f37858b614855565b611f41919061488a565b613a09565b9550611f89565b6000611f5a8a8587613947565b9850899750889050611f8585611f708584614855565b611f7a919061488a565b85611f37868c614855565b9650505b505b50505050955095509592505050565b6000806000611faa8f8f8f612aad565b9050600087611fb9578c611fbd565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90611ff8903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b15801561201257600080fd5b505af1158015612026573d6000803e3d6000fd5b505050505061203b8f8f8f8f8f8f8f8f612686565b8093508194505050509c509c9a5050505050505050505050565b6000610e66848484613947565b600080612070858585612aad565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8149091169063e5e31b1390602401602060405180830381865afa1580156120db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ff91906148ed565b1561217d576040516378a051ad60e11b8152600481018790526001600160a01b03868116602483015282169063f140a35a90604401602060405180830381865afa158015612151573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612175919061483c565b915050612183565b60009150505b949350505050565b600080600083428110156121b15760405162461bcd60e51b8152600401610227906146e6565b6121e08b7f00000000000000000000000053000000000000000000000000000000000000048c8c348d8d6131d8565b909450925060006122128c7f00000000000000000000000053000000000000000000000000000000000000048d612aad565b90506122296001600160a01b038d16338388612bb5565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561228457600080fd5b505af1158015612298573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018990527f000000000000000000000000530000000000000000000000000000000000000416935063a9059cbb925060440190506020604051808303816000875af115801561230d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061233191906148ed565b61233d5761233d61490a565b6040516335313c2160e11b81526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015612385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a9919061483c565b9250833411156123c6576123c6336123c1863461473b565b612e75565b50509750975097945050505050565b6000806123e789898989898989613001565b9150915097509795505050505050565b60008060006124278e7f00000000000000000000000053000000000000000000000000000000000000048f612aad565b9050600087612436578c61243a565b6000195b60405163d505accf60e01b81529091506001600160a01b0383169063d505accf90612475903390309086908f908e908e908e906004016148ac565b600060405180830381600087803b15801561248f57600080fd5b505af11580156124a3573d6000803e3d6000fd5b50505050610e3f8f8f8f8f8f8f8f613a1f565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8149091169063e5e31b1390602401602060405180830381865afa158015612521573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254591906148ed565b92915050565b6060814281101561256e5760405162461bcd60e51b8152600401610227906146e6565b6125c0888787808060200260200160405190810160405280939291908181526020016000905b828210156109a9576125b1606083028601368190038101906147c2565b81526020019060010190612594565b91508682600184516125d2919061473b565b815181106125e2576125e261470f565b602002602001015110156126085760405162461bcd60e51b815260040161022790614752565b61262233610a8688886000818110610a1557610a1561470f565b610c0e828787808060200260200160405190810160405280939291908181526020016000905b828210156114cd57612665606083028601368190038101906147c2565b81526020019060010190612648565b6000806123e789898989898989613a1f565b60008082428110156126aa5760405162461bcd60e51b8152600401610227906146e6565b60006126b78c8c8c612aad565b90506126ce6001600160a01b03821633838c612bb5565b60405163226bf2d160e21b81526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af115801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190614920565b91509150600061274e8f8f6130ff565b509050806001600160a01b03168f6001600160a01b031614612771578183612774565b82825b90975095508a8710156127c95760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e540000006044820152606401610227565b898610156128195760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e540000006044820152606401610227565b50505050509850989650505050505050565b606060018251101561284f5760405162461bcd60e51b815260040161022790614794565b815161285c906001614944565b67ffffffffffffffff81111561287457612874614285565b60405190808252806020026020018201604052801561289d578160200160208202803683370190505b50905082816000815181106128b4576128b461470f565b60200260200101818152505060005b8251811015612aa657600061291f8483815181106128e3576128e361470f565b6020026020010151600001518584815181106129015761290161470f565b6020026020010151602001518685815181106108345761083461470f565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8149091169063e5e31b1390602401602060405180830381865afa15801561298a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ae91906148ed565b15612a9357806001600160a01b031663f140a35a8484815181106129d4576129d461470f565b60200260200101518685815181106129ee576129ee61470f565b6020026020010151600001516040518363ffffffff1660e01b8152600401612a299291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a919061483c565b83612a76846001614944565b81518110612a8657612a8661470f565b6020026020010181815250505b5080612a9e8161495c565b9150506128c3565b5092915050565b6000806000612abc86866130ff565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b81490604901604051602081830303815290604052805190602001207f43405ab97cbbd5cdca8cbbb9180ca5a664ac8e3cef567bc5bbabf6924fbea207604051602001612b93939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052612c209085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613af7565b50505050565b60005b8251811015612c20576000612c78848381518110612c4957612c4961470f565b602002602001015160000151858481518110612c6757612c6761470f565b6020026020010151602001516130ff565b509050600085612c89846001614944565b81518110612c9957612c9961470f565b60200260200101519050600080836001600160a01b0316878681518110612cc257612cc261470f565b6020026020010151600001516001600160a01b031614612ce457826000612ce8565b6000835b91509150600060018851612cfc919061473b565b8610612d085786612d7b565b612d7b88612d17886001614944565b81518110612d2757612d2761470f565b60200260200101516000015189886001612d419190614944565b81518110612d5157612d5161470f565b6020026020010151602001518a896001612d6b9190614944565b815181106108345761083461470f565b9050612dce888781518110612d9257612d9261470f565b602002602001015160000151898881518110612db057612db061470f565b6020026020010151602001518a89815181106108345761083461470f565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612e0b576020820181803683370190505b506040518563ffffffff1660e01b8152600401612e2b94939291906149cd565b600060405180830381600087803b158015612e4557600080fd5b505af1158015612e59573d6000803e3d6000fd5b5050505050505050508080612e6d9061495c565b915050612c29565b604080516000808252602082019092526001600160a01b038416908390604051612e9f91906149fa565b60006040518083038185875af1925050503d8060008114612edc576040519150601f19603f3d011682016040523d82523d6000602084013e612ee1565b606091505b5050905080612f325760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204554485f5452414e534645525f4641494c454400000000006044820152606401610227565b505050565b6000806000612f4686866130ff565b509050600080612f57888888612aad565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb89190614a2d565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b031614612fef578082612ff2565b81815b90999098509650505050505050565b60008082428110156130255760405162461bcd60e51b8152600401610227906146e6565b6130558a7f00000000000000000000000053000000000000000000000000000000000000048b8b8b8b308b612686565b909350915061306e6001600160a01b038b168685613bc9565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156130d057600080fd5b505af11580156130e4573d6000803e3d6000fd5b505050506130f28583612e75565b5097509795505050505050565b600080826001600160a01b0316846001600160a01b0316036131635760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a204944454e544943414c5f41444452455353455300000000006044820152606401610227565b826001600160a01b0316846001600160a01b031610613183578284613186565b83835b90925090506001600160a01b038216610e825760405162461bcd60e51b8152602060048201526014602482015273526f757465723a205a45524f5f4144445245535360601b6044820152606401610227565b6000808386101561322b5760405162461bcd60e51b815260206004820152601860248201527f526f757465723a20444553495245445f415f414d4f554e5400000000000000006044820152606401610227565b8285101561327b5760405162461bcd60e51b815260206004820152601860248201527f526f757465723a20444553495245445f425f414d4f554e5400000000000000006044820152606401610227565b6040516306801cc360e41b81526000906001600160a01b037f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8141690636801cc30906132ce908d908d908d906004016147fb565b602060405180830381865afa1580156132eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330f919061481f565b90506001600160a01b0381166133b5576040516320b7f73960e21b81526001600160a01b037f00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b81416906382dfdce49061336f908d908d908d906004016147fb565b6020604051808303816000875af115801561338e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b2919061481f565b90505b6000806133c38c8c8c612f37565b915091508160001480156133d5575080155b156133e5578894508793506134cd565b60006133f28a8484613947565b9050888111613456578681101561344b5760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f425f414d4f554e540000006044820152606401610227565b8995509350836134cb565b60006134638a8486613947565b90508a8111156134755761347561490a565b888110156134c55760405162461bcd60e51b815260206004820152601d60248201527f526f757465723a20494e53554646494349454e545f415f414d4f554e540000006044820152606401610227565b95508894505b505b50505097509795505050505050565b60005b8251811015612f32576000808483815181106134fd576134fd61470f565b60200260200101516000015185848151811061351b5761351b61470f565b60200260200101516020015191509150600061353783836130ff565b509050600061358d8786815181106135515761355161470f565b60200260200101516000015188878151811061356f5761356f61470f565b6020026020010151602001518988815181106108345761083461470f565b9050600080600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156135d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f79190614a2d565b506001600160701b031691506001600160701b031691506000866001600160a01b0316896001600160a01b03161461362f5781613631565b825b6040516370a0823160e01b81526001600160a01b03888116600483015291925082918b16906370a0823190602401602060405180830381865afa15801561367c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a0919061483c565b6136aa919061473b565b6040516378a051ad60e11b8152600481018290526001600160a01b038b811660248301529196509087169063f140a35a90604401602060405180830381865afa1580156136fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371f919061483c565b9350505050600080856001600160a01b0316886001600160a01b0316146137485782600061374c565b6000835b91509150600060018c51613760919061473b565b8a1061376c578a6137cf565b6137cf8c61377b8c6001614944565b8151811061378b5761378b61470f565b6020026020010151600001518d8c60016137a59190614944565b815181106137b5576137b561470f565b6020026020010151602001518e8d6001612d6b9190614944565b6040805160008152602081019182905263022c0d9f60e01b9091529091506001600160a01b0387169063022c0d9f9061381190869086908690602481016149cd565b600060405180830381600087803b15801561382b57600080fd5b505af115801561383f573d6000803e3d6000fd5b5050505050505050505050505080806138579061495c565b9150506134df565b60008160000361387157506000919050565b6000600161387e84613bf9565b901c6001901b9050600181848161389757613897614874565b048201901c905060018184816138af576138af614874565b048201901c905060018184816138c7576138c7614874565b048201901c905060018184816138df576138df614874565b048201901c905060018184816138f7576138f7614874565b048201901c9050600181848161390f5761390f614874565b048201901c9050600181848161392757613927614874565b048201901c9050610e698182858161394157613941614874565b04613a09565b60008084116139985760405162461bcd60e51b815260206004820152601b60248201527f526f757465723a20494e53554646494349454e545f414d4f554e5400000000006044820152606401610227565b6000831180156139a85750600082115b6139f45760405162461bcd60e51b815260206004820152601e60248201527f526f757465723a20494e53554646494349454e545f4c495155494449545900006044820152606401610227565b826139ff8386614855565b610e66919061488a565b6000818310613a185781610e69565b5090919050565b6000808242811015613a435760405162461bcd60e51b8152600401610227906146e6565b613a738a7f00000000000000000000000053000000000000000000000000000000000000048b8b8b8b308b612686565b6040516370a0823160e01b8152306004820152919450925061306e9086906001600160a01b038d16906370a0823190602401602060405180830381865afa158015613ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae6919061483c565b6001600160a01b038d169190613bc9565b6000613b4c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613c8d9092919063ffffffff16565b805190915015612f325780806020019051810190613b6a91906148ed565b612f325760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610227565b6040516001600160a01b038316602482015260448101829052612f3290849063a9059cbb60e01b90606401612be9565b600080608083901c15613c0e57608092831c92015b604083901c15613c2057604092831c92015b602083901c15613c3257602092831c92015b601083901c15613c4457601092831c92015b600883901c15613c5657600892831c92015b600483901c15613c6857600492831c92015b600283901c15613c7a57600292831c92015b600183901c156125455760010192915050565b60606001600160a01b0384163b613ce65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610227565b600080856001600160a01b031685604051613d0191906149fa565b6000604051808303816000865af19150503d8060008114613d3e576040519150601f19603f3d011682016040523d82523d6000602084013e613d43565b606091505b5091509150613d53828286613d5d565b9695505050505050565b60608315613d6c575081610e69565b825115613d7c5782518084602001fd5b8160405162461bcd60e51b81526004016102279190614a72565b6001600160a01b0381168114613dab57600080fd5b50565b8035613db981613d96565b919050565b8015158114613dab57600080fd5b600080600080600080600080610100898b031215613de957600080fd5b8835613df481613d96565b97506020890135613e0481613d96565b96506040890135613e1481613dbe565b9550606089013594506080890135935060a0890135925060c0890135613e3981613d96565b8092505060e089013590509295985092959890939650565b600080600080600080600060e0888a031215613e6c57600080fd5b87359650602088013595506040880135613e8581613d96565b94506060880135613e9581613d96565b93506080880135613ea581613dbe565b925060a0880135613eb581613d96565b8092505060c0880135905092959891949750929550565b6020808252825182820181905260009190848201906040850190845b81811015613f0457835183529284019291840191600101613ee8565b50909695505050505050565b60008083601f840112613f2257600080fd5b50813567ffffffffffffffff811115613f3a57600080fd5b602083019150836020606083028501011115610e8257600080fd5b60008060008060008060a08789031215613f6e57600080fd5b8635955060208701359450604087013567ffffffffffffffff811115613f9357600080fd5b613f9f89828a01613f10565b9095509350506060870135613fb381613d96565b80925050608087013590509295509295509295565b60008060008060808587031215613fde57600080fd5b8435613fe981613d96565b93506020850135613ff981613d96565b9250604085013561400981613dbe565b9396929550929360600135925050565b803560ff81168114613db957600080fd5b60008060008060008060008060008060006101608c8e03121561404c57600080fd5b8b3561405781613d96565b9a5060208c013561406781613dbe565b995060408c0135985060608c0135975060808c0135965060a08c013561408c81613d96565b955060c08c0135945060e08c01356140a381613dbe565b93506140b26101008d01614019565b92506101208c013591506101408c013590509295989b509295989b9093969950565b6000806000606084860312156140e957600080fd5b83356140f481613d96565b9250602084013561410481613d96565b9150604084013561411481613dbe565b809150509250925092565b6000806040838503121561413257600080fd5b823561413d81613d96565b9150602083013561414d81613d96565b809150509250929050565b60008060008060008060008060006101208a8c03121561417757600080fd5b893561418281613d96565b985060208a013561419281613d96565b975060408a01356141a281613dbe565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356141ce81613d96565b809250506101008a013590509295985092959850929598565b6000806000606084860312156141fc57600080fd5b83359250602084013561420e81613d96565b9150604084013561411481613d96565b60008060008060006080868803121561423657600080fd5b85359450602086013567ffffffffffffffff81111561425457600080fd5b61426088828901613f10565b909550935050604086013561427481613d96565b949793965091946060013592915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156142c4576142c4614285565b604052919050565b600067ffffffffffffffff8211156142e6576142e6614285565b5060051b60200190565b60008060008060006080868803121561430857600080fd5b853567ffffffffffffffff8082111561432057600080fd5b818801915088601f83011261433457600080fd5b81356020614349614344836142cc565b61429b565b82815260059290921b8401810191818101908c84111561436857600080fd5b948201945b838610156143865785358252948201949082019061436d565b9950508901359250508082111561439c57600080fd5b506143a988828901613f10565b9095509350614274905060408701613dae565b6000606082840312156143ce57600080fd5b6040516060810181811067ffffffffffffffff821117156143f1576143f1614285565b604052905080823561440281613d96565b8152602083013561441281613d96565b6020820152604083013561442581613dbe565b6040919091015292915050565b6000806040838503121561444557600080fd5b8235915060208084013567ffffffffffffffff81111561446457600080fd5b8401601f8101861361447557600080fd5b8035614483614344826142cc565b818152606091820283018401918482019190898411156144a257600080fd5b938501935b838510156144c8576144b98a866143bc565b835293840193918501916144a7565b5080955050505050509250929050565b600080600080600060a086880312156144f057600080fd5b85356144fb81613d96565b9450602086013561450b81613d96565b9350604086013561451b81613dbe565b94979396509394606081013594506080013592915050565b6000806000806000806000806000806000806101808d8f03121561455657600080fd5b8c3561456181613d96565b9b5060208d013561457181613d96565b9a5060408d013561458181613dbe565b995060608d0135985060808d0135975060a08d0135965060c08d01356145a681613d96565b955060e08d013594506101008d01356145be81613dbe565b93506145cd6101208e01614019565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008060006060848603121561460457600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561463157600080fd5b84359350602085013561464381613d96565b9250604085013561465381613d96565b9150606085013561466381613dbe565b939692955090935050565b600080600080600080600060e0888a03121561468957600080fd5b873561469481613d96565b965060208801356146a481613dbe565b955060408801359450606088013593506080880135925060a0880135613eb581613d96565b6000602082840312156146db57600080fd5b8135610e6981613d96565b6020808252600f908201526e149bdd5d195c8e8811561412549151608a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008282101561474d5761474d614725565b500390565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f55604082015261139560f21b606082015260800190565b6020808252601490820152730a4deeae8cae47440929cac82989288bea082a8960631b604082015260600190565b6000606082840312156147d457600080fd5b610e6983836143bc565b6000602082840312156147f057600080fd5b8135610e6981613dbe565b6001600160a01b039384168152919092166020820152901515604082015260600190565b60006020828403121561483157600080fd5b8151610e6981613d96565b60006020828403121561484e57600080fd5b5051919050565b600081600019048311821515161561486f5761486f614725565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826148a757634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6000602082840312156148ff57600080fd5b8151610e6981613dbe565b634e487b7160e01b600052600160045260246000fd5b6000806040838503121561493357600080fd5b505080516020909101519092909150565b6000821982111561495757614957614725565b500190565b60006001820161496e5761496e614725565b5060010190565b60005b83811015614990578181015183820152602001614978565b83811115612c205750506000910152565b600081518084526149b9816020860160208601614975565b601f01601f19169290920160200192915050565b84815283602082015260018060a01b0383166040820152608060608201526000613d5360808301846149a1565b60008251614a0c818460208701614975565b9190910192915050565b80516001600160701b0381168114613db957600080fd5b600080600060608486031215614a4257600080fd5b614a4b84614a16565b9250614a5960208501614a16565b9150604084015163ffffffff8116811461411457600080fd5b602081526000610e6960208301846149a156fea2646970667358221220af615a075db703e4cceab696c74e0b376e8734bad94c3100c2660089869070a864736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b8140000000000000000000000005300000000000000000000000000000000000004
-----Decoded View---------------
Arg [0] : _factory (address): 0x98FE34c3BF6784D3F3a698525693D1d3fbE2b814
Arg [1] : _weth (address): 0x5300000000000000000000000000000000000004
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000098fe34c3bf6784d3f3a698525693d1d3fbe2b814
Arg [1] : 0000000000000000000000005300000000000000000000000000000000000004
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
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.