Contract Address Details

0xec2f2b94465Ee0a7436beB4E38FC8Cf631ECf7DF

Contract Name
GlideRouter
Creator
0x3ac393–ae476b at 0x1cc9c8–c3e275
Balance
0 ELA
Tokens
Fetching tokens...
Transactions
Transfers
Gas Used
Last Balance Update
27813276
Contract name:
GlideRouter




Optimization enabled
true
Compiler version
v0.6.12+commit.27d51765




Optimization runs
9999
EVM Version
constantinople




Verified at
2021-10-27 06:36:48.456327Z

Constructor Arguments

000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e5000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c4

Arg [0] (address) : 0xaabe38153b25f0d4b2bda620f67059b3a45334e5
Arg [1] (address) : 0x517e9e5d46c1ea8ab6f78677d6114ef47f71f6c4

              

Contract source code

// File: contracts/Swap/interfaces/IWETH.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}
// File: contracts/Swap/interfaces/IERC20.sol
pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
// File: contracts/Swap/libraries/SafeMath.sol
pragma solidity ^0.6.12;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
}
// File: contracts/Swap/libraries/TransferHelper.sol
pragma solidity >=0.6.0;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
// File: contracts/Swap/interfaces/IGlidePair.sol
pragma solidity >=0.6.6;
interface IGlidePair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
// File: contracts/Swap/interfaces/IGlideRouter.sol
pragma solidity >=0.6.2;
interface IGlideRouter {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
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,
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 swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external view returns (uint256 amountB);
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) external view returns (uint256 amountOut);
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) external view returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
// File: contracts/Swap/interfaces/IGlideFactory.sol
pragma solidity >=0.6.6;
interface IGlideFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function sortTokens(address tokenA, address tokenB) external pure returns (address token0, address token1);
function pairFor(address tokenA, address tokenB) external view returns (address pair);
function getReserves(address tokenA, address tokenB) external view returns (uint256 reserveA, uint256 reserveB);
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB);
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) external view returns (uint256 amountOut);
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) external view returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
}
// File: contracts/Swap/GlideRouter.sol
pragma solidity =0.6.12;
contract GlideRouter is IGlideRouter {
using SafeMath for uint;
address public immutable override factory;
address public immutable override WETH;
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'GlideRouter: EXPIRED');
_;
}
constructor(address _factory, address _WETH) public {
factory = _factory;
WETH = _WETH;
}
receive() external payable {
assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract
}
// **** ADD LIQUIDITY ****
function _addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal virtual returns (uint amountA, uint amountB) {
// create the pair if it doesn't exist yet
if (IGlideFactory(factory).getPair(tokenA, tokenB) == address(0)) {
IGlideFactory(factory).createPair(tokenA, tokenB);
}
(uint reserveA, uint reserveB) = IGlideFactory(factory).getReserves(tokenA, tokenB);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint amountBOptimal = IGlideFactory(factory).quote(amountADesired, reserveA, reserveB);
if (amountBOptimal <= amountBDesired) {
require(amountBOptimal >= amountBMin, 'GlideRouter: INSUFFICIENT_B_AMOUNT');
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint amountAOptimal = IGlideFactory(factory).quote(amountBDesired, reserveB, reserveA);
assert(amountAOptimal <= amountADesired);
require(amountAOptimal >= amountAMin, 'GlideRouter: INSUFFICIENT_A_AMOUNT');
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
(amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
address pair = IGlideFactory(factory).pairFor(tokenA, tokenB);
TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
liquidity = IGlidePair(pair).mint(to);
}
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
(amountToken, amountETH) = _addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = IGlideFactory(factory).pairFor(token, WETH);
TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IGlidePair(pair).mint(to);
// refund dust eth, if any
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
// **** REMOVE LIQUIDITY ****
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountA, uint amountB) {
address pair = IGlideFactory(factory).pairFor(tokenA, tokenB);
IGlidePair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(uint amount0, uint amount1) = IGlidePair(pair).burn(to);
(address token0,) = IGlideFactory(factory).sortTokens(tokenA, tokenB);
(amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
require(amountA >= amountAMin, 'GlideRouter: INSUFFICIENT_A_AMOUNT');
require(amountB >= amountBMin, 'GlideRouter: INSUFFICIENT_B_AMOUNT');
}
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountToken, uint amountETH) {
(amountToken, amountETH) = removeLiquidity(
token,
WETH,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
TransferHelper.safeTransfer(token, to, amountToken);
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external virtual override returns (uint amountA, uint amountB) {
address pair = IGlideFactory(factory).pairFor(tokenA, tokenB);
uint value = approveMax ? uint(-1) : liquidity;
IGlidePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(amountA, amountB) = removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline);
}
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external virtual override returns (uint amountToken, uint amountETH) {
address pair = IGlideFactory(factory).pairFor(token, WETH);
uint value = approveMax ? uint(-1) : liquidity;
IGlidePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline);
}
// **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) ****
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountETH) {
(, amountETH) = removeLiquidity(
token,
WETH,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
TransferHelper.safeTransfer(token, to, IERC20(token).balanceOf(address(this)));
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external virtual override returns (uint amountETH) {
address pair = IGlideFactory(factory).pairFor(token, WETH);
uint value = approveMax ? uint(-1) : liquidity;
IGlidePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
amountETH = removeLiquidityETHSupportingFeeOnTransferTokens(
token, liquidity, amountTokenMin, amountETHMin, to, deadline
);
}
// **** SWAP ****
// requires the initial amount to have already been sent to the first pair
function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = IGlideFactory(factory).sortTokens(input, output);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
address to = i < path.length - 2 ? IGlideFactory(factory).pairFor(output, path[i + 2]) : _to;
IGlidePair(IGlideFactory(factory).pairFor(input, output)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = IGlideFactory(factory).getAmountsOut(amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = IGlideFactory(factory).getAmountsIn(amountOut, path);
require(amounts[0] <= amountInMax, 'GlideRouter: EXCESSIVE_INPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
virtual
override
payable
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[0] == WETH, 'GlideRouter: INVALID_PATH');
amounts = IGlideFactory(factory).getAmountsOut(msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
}
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
virtual
override
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[path.length - 1] == WETH, 'GlideRouter: INVALID_PATH');
amounts = IGlideFactory(factory).getAmountsIn(amountOut, path);
require(amounts[0] <= amountInMax, 'GlideRouter: EXCESSIVE_INPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]
);
_swap(amounts, path, address(this));
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
virtual
override
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[path.length - 1] == WETH, 'GlideRouter: INVALID_PATH');
amounts = IGlideFactory(factory).getAmountsOut(amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]
);
_swap(amounts, path, address(this));
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
virtual
override
payable
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[0] == WETH, 'GlideRouter: INVALID_PATH');
amounts = IGlideFactory(factory).getAmountsIn(amountOut, path);
require(amounts[0] <= msg.value, 'GlideRouter: EXCESSIVE_INPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(IGlideFactory(factory).pairFor(path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
// refund dust eth, if any
if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
}
// **** SWAP (supporting fee-on-transfer tokens) ****
// requires the initial amount to have already been sent to the first pair
function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = IGlideFactory(factory).sortTokens(input, output);
IGlidePair pair = IGlidePair(IGlideFactory(factory).pairFor(input, output));
uint amountInput;
uint amountOutput;
{ // scope to avoid stack too deep errors
(uint reserve0, uint reserve1,) = pair.getReserves();
(uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
amountInput = IERC20(input).balanceOf(address(pair)).sub(reserveInput);
amountOutput = IGlideFactory(factory).getAmountOut(amountInput, reserveInput, reserveOutput);
}
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
address to = i < path.length - 2 ? IGlideFactory(factory).pairFor(output, path[i + 2]) : _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) {
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amountIn
);
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
virtual
override
payable
ensure(deadline)
{
require(path[0] == WETH, 'GlideRouter: INVALID_PATH');
uint amountIn = msg.value;
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(IGlideFactory(factory).pairFor(path[0], path[1]), amountIn));
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
virtual
override
ensure(deadline)
{
require(path[path.length - 1] == WETH, 'GlideRouter: INVALID_PATH');
TransferHelper.safeTransferFrom(
path[0], msg.sender, IGlideFactory(factory).pairFor(path[0], path[1]), amountIn
);
_swapSupportingFeeOnTransferTokens(path, address(this));
uint amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, 'GlideRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).withdraw(amountOut);
TransferHelper.safeTransferETH(to, amountOut);
}
// **** LIBRARY FUNCTIONS ****
function quote(uint amountA, uint reserveA, uint reserveB) public view virtual override returns (uint amountB) {
return IGlideFactory(factory).quote(amountA, reserveA, reserveB);
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
public
view
virtual
override
returns (uint amountOut)
{
return IGlideFactory(factory).getAmountOut(amountIn, reserveIn, reserveOut);
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
public
view
virtual
override
returns (uint amountIn)
{
return IGlideFactory(factory).getAmountIn(amountOut, reserveIn, reserveOut);
}
function getAmountsOut(uint amountIn, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return IGlideFactory(factory).getAmountsOut(amountIn, path);
}
function getAmountsIn(uint amountOut, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return IGlideFactory(factory).getAmountsIn(amountOut, path);
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_WETH","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WETH","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidity","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"amountADesired","internalType":"uint256"},{"type":"uint256","name":"amountBDesired","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidityETH","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountTokenDesired","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"}],"name":"getAmountIn","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"reserveIn","internalType":"uint256"},{"type":"uint256","name":"reserveOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"getAmountOut","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"reserveIn","internalType":"uint256"},{"type":"uint256","name":"reserveOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"getAmountsIn","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"getAmountsOut","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"quote","inputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"reserveA","internalType":"uint256"},{"type":"uint256","name":"reserveB","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidity","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETH","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermit","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidityWithPermit","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapETHForExactTokens","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactETHForTokens","inputs":[{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForETH","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactETH","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactTokens","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
            

Deployed ByteCode

0x60806040526004361061018f5760003560e01c80638803dbee116100d6578063c45a01551161007f578063e8e3370011610059578063e8e3370014610ba1578063f305d71914610c21578063fb3bdb4114610c67576101c8565b8063c45a015514610a62578063d06ca61f14610a77578063ded9382a14610b2e576101c8565b8063af2979eb116100b0578063af2979eb1461092c578063b6f9de951461097f578063baa2abde14610a05576101c8565b80638803dbee1461082d578063ad5c4648146108c5578063ad615dec146108f6576101c8565b80634a25d94a11610138578063791ac94711610112578063791ac947146106d95780637ff36ab51461077157806385f8c259146107f7576101c8565b80634a25d94a146105365780635b0d5984146105ce5780635c11d79514610641576101c8565b80631f00ca74116101695780631f00ca74146103695780632195995c1461042057806338ed17391461049e576101c8565b806302751cec146101cd578063054d50d41461023957806318cbafe514610281576101c8565b366101c857336001600160a01b037f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c416146101c657fe5b005b600080fd5b3480156101d957600080fd5b50610220600480360360c08110156101f057600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135610ced565b6040805192835260208301919091528051918290030190f35b34801561024557600080fd5b5061026f6004803603606081101561025c57600080fd5b5080359060208101359060400135610e19565b60408051918252519081900360200190f35b34801561028d57600080fd5b50610319600480360360a08110156102a457600080fd5b8135916020810135918101906060810160408201356401000000008111156102cb57600080fd5b8201836020820111156102dd57600080fd5b803590602001918460208302840111640100000000831117156102ff57600080fd5b91935091506001600160a01b038135169060200135610ec3565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561035557818101518382015260200161033d565b505050509050019250505060405180910390f35b34801561037557600080fd5b506103196004803603604081101561038c57600080fd5b813591908101906040810160208201356401000000008111156103ae57600080fd5b8201836020820111156103c057600080fd5b803590602001918460208302840111640100000000831117156103e257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506113b2945050505050565b34801561042c57600080fd5b50610220600480360361016081101561044457600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c08101359060e081013515159060ff6101008201351690610120810135906101400135611549565b3480156104aa57600080fd5b50610319600480360360a08110156104c157600080fd5b8135916020810135918101906060810160408201356401000000008111156104e857600080fd5b8201836020820111156104fa57600080fd5b8035906020019184602083028401116401000000008311171561051c57600080fd5b91935091506001600160a01b0381351690602001356116db565b34801561054257600080fd5b50610319600480360360a081101561055957600080fd5b81359160208101359181019060608101604082013564010000000081111561058057600080fd5b82018360208201111561059257600080fd5b803590602001918460208302840111640100000000831117156105b457600080fd5b91935091506001600160a01b038135169060200135611957565b3480156105da57600080fd5b5061026f60048036036101408110156105f257600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e08201351690610100810135906101200135611c26565b34801561064d57600080fd5b506101c6600480360360a081101561066457600080fd5b81359160208101359181019060608101604082013564010000000081111561068b57600080fd5b82018360208201111561069d57600080fd5b803590602001918460208302840111640100000000831117156106bf57600080fd5b91935091506001600160a01b038135169060200135611dcc565b3480156106e557600080fd5b506101c6600480360360a08110156106fc57600080fd5b81359160208101359181019060608101604082013564010000000081111561072357600080fd5b82018360208201111561073557600080fd5b8035906020019184602083028401116401000000008311171561075757600080fd5b91935091506001600160a01b0381351690602001356120ef565b6103196004803603608081101561078757600080fd5b813591908101906040810160208201356401000000008111156107a957600080fd5b8201836020820111156107bb57600080fd5b803590602001918460208302840111640100000000831117156107dd57600080fd5b91935091506001600160a01b03813516906020013561239c565b34801561080357600080fd5b5061026f6004803603606081101561081a57600080fd5b50803590602081013590604001356128db565b34801561083957600080fd5b50610319600480360360a081101561085057600080fd5b81359160208101359181019060608101604082013564010000000081111561087757600080fd5b82018360208201111561088957600080fd5b803590602001918460208302840111640100000000831117156108ab57600080fd5b91935091506001600160a01b038135169060200135612951565b3480156108d157600080fd5b506108da612b7b565b604080516001600160a01b039092168252519081900360200190f35b34801561090257600080fd5b5061026f6004803603606081101561091957600080fd5b5080359060208101359060400135612b9f565b34801561093857600080fd5b5061026f600480360360c081101561094f57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135612c15565b6101c66004803603608081101561099557600080fd5b813591908101906040810160208201356401000000008111156109b757600080fd5b8201836020820111156109c957600080fd5b803590602001918460208302840111640100000000831117156109eb57600080fd5b91935091506001600160a01b038135169060200135612dad565b348015610a1157600080fd5b50610220600480360360e0811015610a2857600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c00135613212565b348015610a6e57600080fd5b506108da6135c2565b348015610a8357600080fd5b5061031960048036036040811015610a9a57600080fd5b81359190810190604081016020820135640100000000811115610abc57600080fd5b820183602082011115610ace57600080fd5b80359060200191846020830284011164010000000083111715610af057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506135e6945050505050565b348015610b3a57600080fd5b506102206004803603610140811015610b5257600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e08201351690610100810135906101200135613684565b348015610bad57600080fd5b50610c036004803603610100811015610bc557600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359160c0820135169060e00135613830565b60408051938452602084019290925282820152519081900360600190f35b610c03600480360360c0811015610c3757600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a001356139f7565b61031960048036036080811015610c7d57600080fd5b81359190810190604081016020820135640100000000811115610c9f57600080fd5b820183602082011115610cb157600080fd5b80359060200191846020830284011164010000000083111715610cd357600080fd5b91935091506001600160a01b038135169060200135613d1e565b6000808242811015610d46576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b610d75897f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c48a8a8a308a613212565b9093509150610d8589868561428b565b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015610deb57600080fd5b505af1158015610dff573d6000803e3d6000fd5b50505050610e0d8583614423565b50965096945050505050565b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663054d50d48585856040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015610e8f57600080fd5b505afa158015610ea3573d6000803e3d6000fd5b505050506040513d6020811015610eb957600080fd5b5051949350505050565b60608142811015610f1b576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c41686866000198101818110610f5557fe5b905060200201356001600160a01b03166001600160a01b031614610fc0576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b604080517fd06ca61f000000000000000000000000000000000000000000000000000000008152600481018a815260248201928352604482018890526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e5169263d06ca61f928c928b928b92606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b15801561107457600080fd5b505afa158015611088573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156110b157600080fd5b81019080805160405193929190846401000000008211156110d157600080fd5b9083019060208201858111156110e657600080fd5b825186602082028301116401000000008211171561110357600080fd5b82525081516020918201928201910280838360005b83811015611130578181015183820152602001611118565b505050509050016040525050509150868260018451038151811061115057fe5b602002602001015110156111955760405162461bcd60e51b81526004018080602001828103825260278152602001806154d06027913960400191505060405180910390fd5b6112b2868660008181106111a557fe5b905060200201356001600160a01b0316337f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98a8a60008181106111f257fe5b905060200201356001600160a01b03168b8b600181811061120f57fe5b905060200201356001600160a01b03166040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561126c57600080fd5b505afa158015611280573d6000803e3d6000fd5b505050506040513d602081101561129657600080fd5b5051855186906000906112a557fe5b602002602001015161451b565b6112f1828787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152503092506146a6915050565b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b0316632e1a7d4d8360018551038151811061133057fe5b60200260200101516040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561136e57600080fd5b505af1158015611382573d6000803e3d6000fd5b505050506113a7848360018551038151811061139a57fe5b6020026020010151614423565b509695505050505050565b604080517f1f00ca7400000000000000000000000000000000000000000000000000000000815260048101848152602482019283528351604483015283516060936001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e51693631f00ca7493889388939192606401906020808601910280838360005b8381101561145357818101518382015260200161143b565b50505050905001935050505060006040518083038186803b15801561147757600080fd5b505afa15801561148b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156114b457600080fd5b81019080805160405193929190846401000000008211156114d457600080fd5b9083019060208201858111156114e957600080fd5b825186602082028301116401000000008211171561150657600080fd5b82525081516020918201928201910280838360005b8381101561153357818101518382015260200161151b565b5050505090500160405250505090505b92915050565b60008060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98f8f6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156115cc57600080fd5b505afa1580156115e0573d6000803e3d6000fd5b505050506040513d60208110156115f657600080fd5b50519050600087611607578c61160b565b6000195b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b15801561169a57600080fd5b505af11580156116ae573d6000803e3d6000fd5b505050506116c18f8f8f8f8f8f8f613212565b809450819550505050509b509b9950505050505050505050565b60608142811015611733576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b604080517fd06ca61f000000000000000000000000000000000000000000000000000000008152600481018a815260248201928352604482018890526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e5169263d06ca61f928c928b928b92606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b1580156117e757600080fd5b505afa1580156117fb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561182457600080fd5b810190808051604051939291908464010000000082111561184457600080fd5b90830190602082018581111561185957600080fd5b825186602082028301116401000000008211171561187657600080fd5b82525081516020918201928201910280838360005b838110156118a357818101518382015260200161188b565b50505050905001604052505050915086826001845103815181106118c357fe5b602002602001015110156119085760405162461bcd60e51b81526004018080602001828103825260278152602001806154d06027913960400191505060405180910390fd5b611918868660008181106111a557fe5b6113a7828787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508992506146a6915050565b606081428110156119af576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c416868660001981018181106119e957fe5b905060200201356001600160a01b03166001600160a01b031614611a54576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b604080517f1f00ca74000000000000000000000000000000000000000000000000000000008152600481018a815260248201928352604482018890526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e51692631f00ca74928c928b928b92606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b158015611b0857600080fd5b505afa158015611b1c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611b4557600080fd5b8101908080516040519392919084640100000000821115611b6557600080fd5b908301906020820185811115611b7a57600080fd5b8251866020820283011164010000000082111715611b9757600080fd5b82525081516020918201928201910280838360005b83811015611bc4578181015183820152602001611bac565b5050505090500160405250505091508682600081518110611be157fe5b602002602001015111156111955760405162461bcd60e51b81526004018080602001828103825260238152602001806154f76023913960400191505060405180910390fd5b6000807f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98d7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611cc757600080fd5b505afa158015611cdb573d6000803e3d6000fd5b505050506040513d6020811015611cf157600080fd5b50519050600086611d02578b611d06565b6000195b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018b905260ff8916608482015260a4810188905260c4810187905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b158015611d9557600080fd5b505af1158015611da9573d6000803e3d6000fd5b50505050611dbb8d8d8d8d8d8d612c15565b9d9c50505050505050505050505050565b8042811015611e22576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b611f2b85856000818110611e3257fe5b905060200201356001600160a01b0316337f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f989896000818110611e7f57fe5b905060200201356001600160a01b03168a8a6001818110611e9c57fe5b905060200201356001600160a01b03166040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015611ef957600080fd5b505afa158015611f0d573d6000803e3d6000fd5b505050506040513d6020811015611f2357600080fd5b50518a61451b565b600085856000198101818110611f3d57fe5b905060200201356001600160a01b03166001600160a01b03166370a08231856040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015611f9957600080fd5b505afa158015611fad573d6000803e3d6000fd5b505050506040513d6020811015611fc357600080fd5b50516040805160208881028281018201909352888252929350612005929091899189918291850190849080828437600092019190915250889250614a84915050565b866120a8828888600019810181811061201a57fe5b905060200201356001600160a01b03166001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561207657600080fd5b505afa15801561208a573d6000803e3d6000fd5b505050506040513d60208110156120a057600080fd5b505190615016565b10156120e55760405162461bcd60e51b81526004018080602001828103825260278152602001806154d06027913960400191505060405180910390fd5b5050505050505050565b8042811015612145576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c4168585600019810181811061217f57fe5b905060200201356001600160a01b03166001600160a01b0316146121ea576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b6121fa85856000818110611e3257fe5b612238858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250614a84915050565b60007f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156122a757600080fd5b505afa1580156122bb573d6000803e3d6000fd5b505050506040513d60208110156122d157600080fd5b50519050868110156123145760405162461bcd60e51b81526004018080602001828103825260278152602001806154d06027913960400191505060405180910390fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561237a57600080fd5b505af115801561238e573d6000803e3d6000fd5b505050506120e58482614423565b606081428110156123f4576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b03168686600081811061242b57fe5b905060200201356001600160a01b03166001600160a01b031614612496576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b604080517fd06ca61f000000000000000000000000000000000000000000000000000000008152346004820181815260248301938452604483018990526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e5169363d06ca61f938b928b929091606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b15801561254b57600080fd5b505afa15801561255f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561258857600080fd5b81019080805160405193929190846401000000008211156125a857600080fd5b9083019060208201858111156125bd57600080fd5b82518660208202830111640100000000821117156125da57600080fd5b82525081516020918201928201910280838360005b838110156126075781810151838201526020016125ef565b505050509050016040525050509150868260018451038151811061262757fe5b6020026020010151101561266c5760405162461bcd60e51b81526004018080602001828103825260278152602001806154d06027913960400191505060405180910390fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663d0e30db0836000815181106126a857fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156126db57600080fd5b505af11580156126ef573d6000803e3d6000fd5b50505050507f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663a9059cbb7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98989600081811061275f57fe5b905060200201356001600160a01b03168a8a600181811061277c57fe5b905060200201356001600160a01b03166040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156127d957600080fd5b505afa1580156127ed573d6000803e3d6000fd5b505050506040513d602081101561280357600080fd5b50518451859060009061281257fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561286057600080fd5b505af1158015612874573d6000803e3d6000fd5b505050506040513d602081101561288a57600080fd5b505161289257fe5b6128d1828787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508992506146a6915050565b5095945050505050565b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166385f8c2598585856040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015610e8f57600080fd5b606081428110156129a9576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b604080517f1f00ca74000000000000000000000000000000000000000000000000000000008152600481018a815260248201928352604482018890526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e51692631f00ca74928c928b928b92606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b158015612a5d57600080fd5b505afa158015612a71573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612a9a57600080fd5b8101908080516040519392919084640100000000821115612aba57600080fd5b908301906020820185811115612acf57600080fd5b8251866020820283011164010000000082111715612aec57600080fd5b82525081516020918201928201910280838360005b83811015612b19578181015183820152602001612b01565b5050505090500160405250505091508682600081518110612b3657fe5b602002602001015111156119085760405162461bcd60e51b81526004018080602001828103825260238152602001806154f76023913960400191505060405180910390fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c481565b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663ad615dec8585856040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015610e8f57600080fd5b60008142811015612c6d576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b612c9c887f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c48989893089613212565b905080925050612d2588858a6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612cf457600080fd5b505afa158015612d08573d6000803e3d6000fd5b505050506040513d6020811015612d1e57600080fd5b505161428b565b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612d8b57600080fd5b505af1158015612d9f573d6000803e3d6000fd5b505050506113a78483614423565b8042811015612e03576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031685856000818110612e3a57fe5b905060200201356001600160a01b03166001600160a01b031614612ea5576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b60003490507f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f0557600080fd5b505af1158015612f19573d6000803e3d6000fd5b50505050507f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663a9059cbb7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f989896000818110612f8957fe5b905060200201356001600160a01b03168a8a6001818110612fa657fe5b905060200201356001600160a01b03166040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561300357600080fd5b505afa158015613017573d6000803e3d6000fd5b505050506040513d602081101561302d57600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482018590525160448083019260209291908290030181600087803b15801561309557600080fd5b505af11580156130a9573d6000803e3d6000fd5b505050506040513d60208110156130bf57600080fd5b50516130c757fe5b6000868660001981018181106130d957fe5b905060200201356001600160a01b03166001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561313557600080fd5b505afa158015613149573d6000803e3d6000fd5b505050506040513d602081101561315f57600080fd5b505160408051602089810282810182019093528982529293506131a19290918a918a918291850190849080828437600092019190915250899250614a84915050565b876120a882898960001981018181106131b657fe5b905060200201356001600160a01b03166001600160a01b03166370a08231896040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561207657600080fd5b600080824281101561326b576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98c8c6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156132eb57600080fd5b505afa1580156132ff573d6000803e3d6000fd5b505050506040513d602081101561331557600080fd5b5051604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03831660248201819052604482018d9052915192935090916323b872dd916064808201926020929091908290030181600087803b15801561338b57600080fd5b505af115801561339f573d6000803e3d6000fd5b505050506040513d60208110156133b557600080fd5b5050604080517f89afcb440000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015282516000938493928616926389afcb44926024808301939282900301818787803b15801561341b57600080fd5b505af115801561342f573d6000803e3d6000fd5b505050506040513d604081101561344557600080fd5b8101908080519060200190929190805190602001909291905050509150915060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663544caa568f8f6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050604080518083038186803b1580156134e357600080fd5b505afa1580156134f7573d6000803e3d6000fd5b505050506040513d604081101561350d57600080fd5b505190506001600160a01b038e81169082161461352b57818361352e565b82825b90975095508a8710156135725760405162461bcd60e51b81526004018080602001828103825260228152602001806154ae6022913960400191505060405180910390fd5b898610156135b15760405162461bcd60e51b815260040180806020018281038252602281526020018061551a6022913960400191505060405180910390fd5b505050505097509795505050505050565b7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e581565b604080517fd06ca61f00000000000000000000000000000000000000000000000000000000815260048101848152602482019283528351604483015283516060937f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03169363d06ca61f9388938893919260640190602080860191028083836000831561145357818101518382015260200161143b565b60008060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98e7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561372757600080fd5b505afa15801561373b573d6000803e3d6000fd5b505050506040513d602081101561375157600080fd5b50519050600087613762578c613766565b6000195b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156137f557600080fd5b505af1158015613809573d6000803e3d6000fd5b5050505061381b8e8e8e8e8e8e610ced565b909f909e509c50505050505050505050505050565b6000806000834281101561388b576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b6138998c8c8c8c8c8c61506e565b809450819550505060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98e8e6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561392157600080fd5b505afa158015613935573d6000803e3d6000fd5b505050506040513d602081101561394b57600080fd5b5051905061395b8d33838861451b565b6139678c33838761451b565b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b1580156139b657600080fd5b505af11580156139ca573d6000803e3d6000fd5b505050506040513d60208110156139e057600080fd5b5051949d939c50939a509198505050505050505050565b60008060008342811015613a52576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b613a808a7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c48b348c8c61506e565b809450819550505060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f98c7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015613b2857600080fd5b505afa158015613b3c573d6000803e3d6000fd5b505050506040513d6020811015613b5257600080fd5b50519050613b628b33838861451b565b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015613bbd57600080fd5b505af1158015613bd1573d6000803e3d6000fd5b50505050507f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663a9059cbb82866040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015613c4d57600080fd5b505af1158015613c61573d6000803e3d6000fd5b505050506040513d6020811015613c7757600080fd5b5051613c7f57fe5b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b158015613cce57600080fd5b505af1158015613ce2573d6000803e3d6000fd5b505050506040513d6020811015613cf857600080fd5b5051925034841015613d1057613d1033853403614423565b505096509650969350505050565b60608142811015613d76576040805162461bcd60e51b815260206004820152601460248201527f476c696465526f757465723a2045585049524544000000000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031686866000818110613dad57fe5b905060200201356001600160a01b03166001600160a01b031614613e18576040805162461bcd60e51b815260206004820152601960248201527f476c696465526f757465723a20494e56414c49445f5041544800000000000000604482015290519081900360640190fd5b604080517f1f00ca740000000000000000000000000000000000000000000000000000000081526004810189815260248201928352604482018890526001600160a01b037f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e51692631f00ca74928b928b928b92606401846020850280828437600081840152601f19601f82011690508083019250505094505050505060006040518083038186803b158015613ecc57600080fd5b505afa158015613ee0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613f0957600080fd5b8101908080516040519392919084640100000000821115613f2957600080fd5b908301906020820185811115613f3e57600080fd5b8251866020820283011164010000000082111715613f5b57600080fd5b82525081516020918201928201910280838360005b83811015613f88578181015183820152602001613f70565b5050505090500160405250505091503482600081518110613fa557fe5b60200260200101511115613fea5760405162461bcd60e51b81526004018080602001828103825260238152602001806154f76023913960400191505060405180910390fd5b7f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663d0e30db08360008151811061402657fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561405957600080fd5b505af115801561406d573d6000803e3d6000fd5b50505050507f000000000000000000000000517e9e5d46c1ea8ab6f78677d6114ef47f71f6c46001600160a01b031663a9059cbb7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f9898960008181106140dd57fe5b905060200201356001600160a01b03168a8a60018181106140fa57fe5b905060200201356001600160a01b03166040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561415757600080fd5b505afa15801561416b573d6000803e3d6000fd5b505050506040513d602081101561418157600080fd5b50518451859060009061419057fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156141de57600080fd5b505af11580156141f2573d6000803e3d6000fd5b505050506040513d602081101561420857600080fd5b505161421057fe5b61424f828787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508992506146a6915050565b8160008151811061425c57fe5b60200260200101513411156128d1576128d1338360008151811061427c57fe5b60200260200101513403614423565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000178152925182516000946060949389169392918291908083835b602083106143365780518252601f199092019160209182019101614317565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614398576040519150601f19603f3d011682016040523d82523d6000602084013e61439d565b606091505b50915091508180156143cb5750805115806143cb57508080602001905160208110156143c857600080fd5b50515b61441c576040805162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604482015290519081900360640190fd5b5050505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b6020831061446f5780518252601f199092019160209182019101614450565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146144d1576040519150601f19603f3d011682016040523d82523d6000602084013e6144d6565b606091505b50509050806145165760405162461bcd60e51b815260040180806020018281038252602381526020018061553c6023913960400191505060405180910390fd5b505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017815292518251600094606094938a169392918291908083835b602083106145ce5780518252601f1990920191602091820191016145af565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614630576040519150601f19603f3d011682016040523d82523d6000602084013e614635565b606091505b5091509150818015614663575080511580614663575080806020019051602081101561466057600080fd5b50515b61469e5760405162461bcd60e51b815260040180806020018281038252602481526020018061555f6024913960400191505060405180910390fd5b505050505050565b60005b6001835103811015614a7e576000808483815181106146c457fe5b60200260200101518584600101815181106146db57fe5b60200260200101519150915060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663544caa5684846040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050604080518083038186803b15801561476657600080fd5b505afa15801561477a573d6000803e3d6000fd5b505050506040513d604081101561479057600080fd5b505187519091506000908890600187019081106147a957fe5b60200260200101519050600080836001600160a01b0316866001600160a01b0316146147d7578260006147db565b6000835b91509150600060028a510388106147f257886148b3565b7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f9878c8b6002018151811061483157fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561488657600080fd5b505afa15801561489a573d6000803e3d6000fd5b505050506040513d60208110156148b057600080fd5b50515b90507f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f988886040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b15801561493357600080fd5b505afa158015614947573d6000803e3d6000fd5b505050506040513d602081101561495d57600080fd5b50516001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561499c576020820181803683370190505b506040518563ffffffff1660e01b815260040180858152602001848152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614a045781810151838201526020016149ec565b50505050905090810190601f168015614a315780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015614a5357600080fd5b505af1158015614a67573d6000803e3d6000fd5b5050600190990198506146a9975050505050505050565b50505050565b60005b600183510381101561451657600080848381518110614aa257fe5b6020026020010151858460010181518110614ab957fe5b60200260200101519150915060007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663544caa5684846040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050604080518083038186803b158015614b4457600080fd5b505afa158015614b58573d6000803e3d6000fd5b505050506040513d6040811015614b6e57600080fd5b5051604080517f96ed28f90000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152858116602483015291519293506000927f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e5909216916396ed28f991604480820192602092909190829003018186803b158015614c0257600080fd5b505afa158015614c16573d6000803e3d6000fd5b505050506040513d6020811015614c2c57600080fd5b5051604080517f0902f1ac00000000000000000000000000000000000000000000000000000000815290519192506000918291829182916001600160a01b03871691630902f1ac91600480820192606092909190829003018186803b158015614c9457600080fd5b505afa158015614ca8573d6000803e3d6000fd5b505050506040513d6060811015614cbe57600080fd5b5080516020909101516dffffffffffffffffffffffffffff91821693501690506000806001600160a01b038a811690891614614cfb578284614cfe565b83835b91509150614d53828b6001600160a01b03166370a082318a6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561207657600080fd5b95507f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663054d50d48784846040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015614dc957600080fd5b505afa158015614ddd573d6000803e3d6000fd5b505050506040513d6020811015614df357600080fd5b505194506000935083925050506001600160a01b0388811690871614614e1b57826000614e1f565b6000835b91509150600060028c51038a10614e36578a614ef7565b7f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b03166396ed28f9898e8d60020181518110614e7557fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b158015614eca57600080fd5b505afa158015614ede573d6000803e3d6000fd5b505050506040513d6020811015614ef457600080fd5b50515b60408051600080825260208201928390527f022c0d9f00000000000000000000000000000000000000000000000000000000835260248201878152604483018790526001600160a01b038086166064850152608060848501908152845160a48601819052969750908c169563022c0d9f958a958a958a9591949193919260c486019290918190849084905b83811015614f9a578181015183820152602001614f82565b50505050905090810190601f168015614fc75780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015614fe957600080fd5b505af1158015614ffd573d6000803e3d6000fd5b50506001909b019a50614a879950505050505050505050565b80820382811115611543576040805162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b60008060006001600160a01b03167f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663e6a439058a8a6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b031681526020019250505060206040518083038186803b1580156150fa57600080fd5b505afa15801561510e573d6000803e3d6000fd5b505050506040513d602081101561512457600080fd5b50516001600160a01b031614156151e2577f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663c9c6539689896040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050602060405180830381600087803b1580156151b557600080fd5b505af11580156151c9573d6000803e3d6000fd5b505050506040513d60208110156151df57600080fd5b50505b6000807f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663d52bb6f48b8b6040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050604080518083038186803b15801561526257600080fd5b505afa158015615276573d6000803e3d6000fd5b505050506040513d604081101561528c57600080fd5b5080516020909101519092509050811580156152a6575080155b156152b6578793508692506154a0565b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663ad615dec8a85856040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561532c57600080fd5b505afa158015615340573d6000803e3d6000fd5b505050506040513d602081101561535657600080fd5b505190508781116153ab57858110156153a05760405162461bcd60e51b815260040180806020018281038252602281526020018061551a6022913960400191505060405180910390fd5b88945092508261549e565b60007f000000000000000000000000aabe38153b25f0d4b2bda620f67059b3a45334e56001600160a01b031663ad615dec8a85876040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561542157600080fd5b505afa158015615435573d6000803e3d6000fd5b505050506040513d602081101561544b57600080fd5b505190508981111561545957fe5b878110156154985760405162461bcd60e51b81526004018080602001828103825260228152602001806154ae6022913960400191505060405180910390fd5b94508793505b505b505096509694505050505056fe476c696465526f757465723a20494e53554646494349454e545f415f414d4f554e54476c696465526f757465723a20494e53554646494349454e545f4f55545055545f414d4f554e54476c696465526f757465723a204558434553534956455f494e5055545f414d4f554e54476c696465526f757465723a20494e53554646494349454e545f425f414d4f554e545472616e7366657248656c7065723a204554485f5452414e534645525f4641494c45445472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c4544a26469706673582212207e3ab33d014b400428439757932242a66427ad7f7f33390109e0132c0df2dfe764736f6c634300060c0033