Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ColdfiRouter
- Optimization enabled
- true
- Compiler version
- v0.6.6+commit.6c089d02
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-11-17T13:10:41.049517Z
Constructor Arguments
0x0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a
Arg [0] (address) : 0x1e1ca2eaffafadd63f8a833704ad39a0ee847fdc
Arg [1] (address) : 0xf5ad6f6edec824c7fd54a66d241a227f6503ad3a
Contract source code
// File: @uniswap/lib/contracts/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,
uint256 value
) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeApprove: approve failed'
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeTransfer: transfer failed'
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::transferFrom: transferFrom failed'
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
}
}
// File: contracts/contracts/interfaces/IColdfiRouter01.sol
pragma solidity >=0.6.2;
interface IColdfiRouter01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure 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/contracts/interfaces/IColdfiRouter02.sol
pragma solidity >=0.6.2;
interface IColdfiRouter02 is IColdfiRouter01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
// File: contracts/contracts/interfaces/IColdfiFactory.sol
pragma solidity >=0.5.0;
interface IColdfiFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
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(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function INIT_CODE_PAIR_HASH() external view returns (bytes32);
}
// File: contracts/contracts/libraries/SafeMath.sol
pragma solidity >=0.5.0 <0.7.0;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
}
// File: contracts/contracts/interfaces/IColdfiPair.sol
pragma solidity >=0.5.0;
interface IColdfiPair {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 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 (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
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 (uint256);
function price1CumulativeLast() external view returns (uint256);
function kLast() external view returns (uint256);
function mint(address to) external returns (uint256 liquidity);
function burn(address to) external returns (uint256 amount0, uint256 amount1);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
// File: contracts/contracts/libraries/ColdfiLibrary.sol
pragma solidity >=0.5.0;
library ColdfiLibrary {
using SafeMath for uint256;
// returns sorted token addresses, used to handle return values from pairs sorted in this order
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, "ColdfiLibrary: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), "ColdfiLibrary: ZERO_ADDRESS");
}
// calculates the CREATE2 address for a pair without making any external calls
function pairFor(
address factory,
address tokenA,
address tokenB
) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encodePacked(token0, token1)),
hex"a5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0" // init code hash
)
)
)
);
}
// fetches and sorts the reserves for a pair
function getReserves(
address factory,
address tokenA,
address tokenB
) internal view returns (uint256 reserveA, uint256 reserveB) {
(address token0, ) = sortTokens(tokenA, tokenB);
pairFor(factory, tokenA, tokenB);
(uint256 reserve0, uint256 reserve1, ) = IColdfiPair(pairFor(factory, tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
// given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) internal pure returns (uint256 amountB) {
require(amountA > 0, "ColdfiLibrary: INSUFFICIENT_AMOUNT");
require(reserveA > 0 && reserveB > 0, "ColdfiLibrary: INSUFFICIENT_LIQUIDITY");
amountB = amountA.mul(reserveB) / reserveA;
}
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountOut) {
require(amountIn > 0, "ColdfiLibrary: INSUFFICIENT_INPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "ColdfiLibrary: INSUFFICIENT_LIQUIDITY");
uint256 amountInWithFee = amountIn.mul(9975);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(10000).add(amountInWithFee);
amountOut = numerator / denominator;
}
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountIn) {
require(amountOut > 0, "ColdfiLibrary: INSUFFICIENT_OUTPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "ColdfiLibrary: INSUFFICIENT_LIQUIDITY");
uint256 numerator = reserveIn.mul(amountOut).mul(10000);
uint256 denominator = reserveOut.sub(amountOut).mul(9975);
amountIn = (numerator / denominator).add(1);
}
// performs chained getAmountOut calculations on any number of pairs
function getAmountsOut(
address factory,
uint256 amountIn,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, "ColdfiLibrary: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
// performs chained getAmountIn calculations on any number of pairs
function getAmountsIn(
address factory,
uint256 amountOut,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, "ColdfiLibrary: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}
// File: contracts/contracts/interfaces/IERC20.sol
pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
// File: contracts/contracts/interfaces/IWETH.sol
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}
// File: contracts/contracts/ColdfiRouter.sol
pragma solidity =0.6.6;
contract ColdfiRouter is IColdfiRouter02 {
using SafeMath for uint256;
address public immutable override factory;
address public immutable override WETH;
modifier ensure(uint256 deadline) {
require(deadline >= block.timestamp, "CFT: E");
_;
}
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,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin
) internal virtual returns (uint256 amountA, uint256 amountB) {
// create the pair if it doesn't exist yet
if (IColdfiFactory(factory).getPair(tokenA, tokenB) == address(0)) {
IColdfiFactory(factory).createPair(tokenA, tokenB);
}
(uint256 reserveA, uint256 reserveB) = ColdfiLibrary.getReserves(factory, tokenA, tokenB);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint256 amountBOptimal = ColdfiLibrary.quote(amountADesired, reserveA, reserveB);
if (amountBOptimal <= amountBDesired) {
require(amountBOptimal >= amountBMin, "CFT: IBA");
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint256 amountAOptimal = ColdfiLibrary.quote(amountBDesired, reserveB, reserveA);
assert(amountAOptimal <= amountADesired);
require(amountAOptimal >= amountAMin, "CFT: IAA");
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
virtual
override
ensure(deadline)
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
)
{
(amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
address pair = ColdfiLibrary.pairFor(factory, tokenA, tokenB);
TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
liquidity = IColdfiPair(pair).mint(to);
}
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
virtual
override
ensure(deadline)
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
)
{
(amountToken, amountETH) = _addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = ColdfiLibrary.pairFor(factory, token, WETH);
TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IColdfiPair(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,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) returns (uint256 amountA, uint256 amountB) {
address pair = ColdfiLibrary.pairFor(factory, tokenA, tokenB);
IColdfiPair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(uint256 amount0, uint256 amount1) = IColdfiPair(pair).burn(to);
(address token0, ) = ColdfiLibrary.sortTokens(tokenA, tokenB);
(amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
require(amountA >= amountAMin, "CFT: IAA");
require(amountB >= amountBMin, "CFT: IBA");
}
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) returns (uint256 amountToken, uint256 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,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountA, uint256 amountB) {
address pair = ColdfiLibrary.pairFor(factory, tokenA, tokenB);
uint256 value = approveMax ? uint256(-1) : liquidity;
IColdfiPair(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,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountToken, uint256 amountETH) {
address pair = ColdfiLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IColdfiPair(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,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) returns (uint256 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,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountETH) {
address pair = ColdfiLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IColdfiPair(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(
uint256[] memory amounts,
address[] memory path,
address _to
) internal virtual {
for (uint256 i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0, ) = ColdfiLibrary.sortTokens(input, output);
uint256 amountOut = amounts[i + 1];
(uint256 amount0Out, uint256 amount1Out) =
input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0));
address to = i < path.length - 2 ? ColdfiLibrary.pairFor(factory, output, path[i + 2]) : _to;
IColdfiPair(ColdfiLibrary.pairFor(factory, input, output)).swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
amounts = ColdfiLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, "CFT: INSUFFICIENT_OUTPUT_AMOUNT");
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, path[0], path[1]),
amounts[0]
);
_swap(amounts, path, to);
}
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
amounts = ColdfiLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, "CFT: EIA");
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, path[0], path[1]),
amounts[0]
);
_swap(amounts, path, to);
}
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) {
require(path[0] == WETH, "CFT: WP");
amounts = ColdfiLibrary.getAmountsOut(factory, msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, "CFT: IOA");
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ColdfiLibrary.pairFor(factory, path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
}
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, "CFT: WP");
amounts = ColdfiLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, "CFT: EIA");
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, 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(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, "CFT: WP");
amounts = ColdfiLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, "CFT: IOA");
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, 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(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) {
require(path[0] == WETH, "CFT: WP");
amounts = ColdfiLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= msg.value, "CFT: EIA");
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ColdfiLibrary.pairFor(factory, 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 (uint256 i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0, ) = ColdfiLibrary.sortTokens(input, output);
IColdfiPair pair = IColdfiPair(ColdfiLibrary.pairFor(factory, input, output));
uint256 amountInput;
uint256 amountOutput;
{
// scope to avoid stack too deep errors
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
(uint256 reserveInput, uint256 reserveOutput) =
input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
amountInput = IERC20(input).balanceOf(address(pair)).sub(reserveInput);
amountOutput = ColdfiLibrary.getAmountOut(amountInput, reserveInput, reserveOutput);
}
(uint256 amount0Out, uint256 amount1Out) =
input == token0 ? (uint256(0), amountOutput) : (amountOutput, uint256(0));
address to = i < path.length - 2 ? ColdfiLibrary.pairFor(factory, output, path[i + 2]) : _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) {
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, path[0], path[1]),
amountIn
);
uint256 balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
"CFT: IOA"
);
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) {
require(path[0] == WETH, "CFT: WP");
uint256 amountIn = msg.value;
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(ColdfiLibrary.pairFor(factory, path[0], path[1]), amountIn));
uint256 balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
"CFT: IOA"
);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) {
require(path[path.length - 1] == WETH, "CFT: WP");
TransferHelper.safeTransferFrom(
path[0],
msg.sender,
ColdfiLibrary.pairFor(factory, path[0], path[1]),
amountIn
);
_swapSupportingFeeOnTransferTokens(path, address(this));
uint256 amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, "CFT: IOA");
IWETH(WETH).withdraw(amountOut);
TransferHelper.safeTransferETH(to, amountOut);
}
// **** LIBRARY FUNCTIONS ****
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) public pure virtual override returns (uint256 amountB) {
return ColdfiLibrary.quote(amountA, reserveA, reserveB);
}
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) public pure virtual override returns (uint256 amountOut) {
return ColdfiLibrary.getAmountOut(amountIn, reserveIn, reserveOut);
}
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) public pure virtual override returns (uint256 amountIn) {
return ColdfiLibrary.getAmountIn(amountOut, reserveIn, reserveOut);
}
function getAmountsOut(uint256 amountIn, address[] memory path)
public
view
virtual
override
returns (uint256[] memory amounts)
{
return ColdfiLibrary.getAmountsOut(factory, amountIn, path);
}
function getAmountsIn(uint256 amountOut, address[] memory path)
public
view
virtual
override
returns (uint256[] memory amounts)
{
return ColdfiLibrary.getAmountsIn(factory, 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":"pure","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":"pure","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":"pure","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"}]
Contract Creation Code
0x60c060405234801561001057600080fd5b506040516200467f3803806200467f8339818101604052604081101561003557600080fd5b5080516020909101516001600160601b0319606092831b8116608052911b1660a05260805160601c60a05160601c6144fa620001856000398061015f5280610cdf5280610d1a5280610e0c528061102752806113bd528061152052806118de52806119d45280611a8b5280611b545280611c975280611d1f5280611f605280611fd65280612085528061214c52806121dd5280612251528061274c52806129b55280612a0b5280612a3f5280612ab35280612c4e5280612d8e5280612e16525080610e965280610f6e52806110ed5280611126528061125c528061144752806114fe52806116695280611be35280611d515280611eaf528061228352806124d752806126d152806126fa528061272a528061289252806129e95280612cdd5280612e4852806136d9528061371c52806139ff5280613b7e5280613fae528061405c52806140dc52506144fa6000f3fe60806040526004361061014f5760003560e01c80638803dbee116100b6578063c45a01551161006f578063c45a015514610a10578063d06ca61f14610a25578063ded9382a14610ada578063e8e3370014610b4d578063f305d71914610bcd578063fb3bdb4114610c1357610188565b80638803dbee146107df578063ad5c464814610875578063ad615dec146108a6578063af2979eb146108dc578063b6f9de951461092f578063baa2abde146109b357610188565b80634a25d94a116101085780634a25d94a146104f05780635b0d5984146105865780635c11d795146105f9578063791ac9471461068f5780637ff36ab51461072557806385f8c259146107a957610188565b806302751cec1461018d578063054d50d4146101f957806318cbafe5146102415780631f00ca74146103275780632195995c146103dc57806338ed17391461045a57610188565b3661018857336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461018657fe5b005b600080fd5b34801561019957600080fd5b506101e0600480360360c08110156101b057600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135610c97565b6040805192835260208301919091528051918290030190f35b34801561020557600080fd5b5061022f6004803603606081101561021c57600080fd5b5080359060208101359060400135610dac565b60408051918252519081900360200190f35b34801561024d57600080fd5b506102d7600480360360a081101561026457600080fd5b813591602081013591810190606081016040820135600160201b81111561028a57600080fd5b82018360208201111561029c57600080fd5b803590602001918460208302840111600160201b831117156102bd57600080fd5b91935091506001600160a01b038135169060200135610dc1565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103135781810151838201526020016102fb565b505050509050019250505060405180910390f35b34801561033357600080fd5b506102d76004803603604081101561034a57600080fd5b81359190810190604081016020820135600160201b81111561036b57600080fd5b82018360208201111561037d57600080fd5b803590602001918460208302840111600160201b8311171561039e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506110e6945050505050565b3480156103e857600080fd5b506101e0600480360361016081101561040057600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c08101359060e081013515159060ff610100820135169061012081013590610140013561111c565b34801561046657600080fd5b506102d7600480360360a081101561047d57600080fd5b813591602081013591810190606081016040820135600160201b8111156104a357600080fd5b8201836020820111156104b557600080fd5b803590602001918460208302840111600160201b831117156104d657600080fd5b91935091506001600160a01b038135169060200135611216565b3480156104fc57600080fd5b506102d7600480360360a081101561051357600080fd5b813591602081013591810190606081016040820135600160201b81111561053957600080fd5b82018360208201111561054b57600080fd5b803590602001918460208302840111600160201b8311171561056c57600080fd5b91935091506001600160a01b038135169060200135611372565b34801561059257600080fd5b5061022f60048036036101408110156105aa57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e082013516906101008101359061012001356114f6565b34801561060557600080fd5b50610186600480360360a081101561061c57600080fd5b813591602081013591810190606081016040820135600160201b81111561064257600080fd5b82018360208201111561065457600080fd5b803590602001918460208302840111600160201b8311171561067557600080fd5b91935091506001600160a01b038135169060200135611604565b34801561069b57600080fd5b50610186600480360360a08110156106b257600080fd5b813591602081013591810190606081016040820135600160201b8111156106d857600080fd5b8201836020820111156106ea57600080fd5b803590602001918460208302840111600160201b8311171561070b57600080fd5b91935091506001600160a01b038135169060200135611895565b6102d76004803603608081101561073b57600080fd5b81359190810190604081016020820135600160201b81111561075c57600080fd5b82018360208201111561076e57600080fd5b803590602001918460208302840111600160201b8311171561078f57600080fd5b91935091506001600160a01b038135169060200135611b11565b3480156107b557600080fd5b5061022f600480360360608110156107cc57600080fd5b5080359060208101359060400135611e5c565b3480156107eb57600080fd5b506102d7600480360360a081101561080257600080fd5b813591602081013591810190606081016040820135600160201b81111561082857600080fd5b82018360208201111561083a57600080fd5b803590602001918460208302840111600160201b8311171561085b57600080fd5b91935091506001600160a01b038135169060200135611e69565b34801561088157600080fd5b5061088a611f5e565b604080516001600160a01b039092168252519081900360200190f35b3480156108b257600080fd5b5061022f600480360360608110156108c957600080fd5b5080359060208101359060400135611f82565b3480156108e857600080fd5b5061022f600480360360c08110156108ff57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135611f8f565b6101866004803603608081101561094557600080fd5b81359190810190604081016020820135600160201b81111561096657600080fd5b82018360208201111561097857600080fd5b803590602001918460208302840111600160201b8311171561099957600080fd5b91935091506001600160a01b03813516906020013561210b565b3480156109bf57600080fd5b506101e0600480360360e08110156109d657600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c0013561248e565b348015610a1c57600080fd5b5061088a6126cf565b348015610a3157600080fd5b506102d760048036036040811015610a4857600080fd5b81359190810190604081016020820135600160201b811115610a6957600080fd5b820183602082011115610a7b57600080fd5b803590602001918460208302840111600160201b83111715610a9c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506126f3945050505050565b348015610ae657600080fd5b506101e06004803603610140811015610afe57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e08201351690610100810135906101200135612720565b348015610b5957600080fd5b50610baf6004803603610100811015610b7157600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359160c0820135169060e00135612834565b60408051938452602084019290925282820152519081900360600190f35b610baf600480360360c0811015610be357600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a0013561296b565b6102d760048036036080811015610c2957600080fd5b81359190810190604081016020820135600160201b811115610c4a57600080fd5b820183602082011115610c5c57600080fd5b803590602001918460208302840111600160201b83111715610c7d57600080fd5b91935091506001600160a01b038135169060200135612c0b565b6000808242811015610cd9576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b610d08897f00000000000000000000000000000000000000000000000000000000000000008a8a8a308a61248e565b9093509150610d18898685612f85565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015610d7e57600080fd5b505af1158015610d92573d6000803e3d6000fd5b50505050610da085836130d9565b50965096945050505050565b6000610db98484846131d1565b949350505050565b60608142811015610e02576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001686866000198101818110610e3c57fe5b905060200201356001600160a01b03166001600160a01b031614610e91576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b610eef7f0000000000000000000000000000000000000000000000000000000000000000898888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b91508682600184510381518110610f0257fe5b60200260200101511015610f48576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b610fe686866000818110610f5857fe5b905060200201356001600160a01b031633610fcc7f00000000000000000000000000000000000000000000000000000000000000008a8a6000818110610f9a57fe5b905060200201356001600160a01b03168b8b6001818110610fb757fe5b905060200201356001600160a01b031661340d565b85600081518110610fd957fe5b60200260200101516134cd565b6110258287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525030925061362a915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551038151811061106457fe5b60200260200101516040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156110a257600080fd5b505af11580156110b6573d6000803e3d6000fd5b505050506110db84836001855103815181106110ce57fe5b60200260200101516130d9565b509695505050505050565b60606111137f00000000000000000000000000000000000000000000000000000000000000008484613870565b90505b92915050565b600080600061114c7f00000000000000000000000000000000000000000000000000000000000000008f8f61340d565b905060008761115b578c61115f565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156111d557600080fd5b505af11580156111e9573d6000803e3d6000fd5b505050506111fc8f8f8f8f8f8f8f61248e565b809450819550505050509b509b9950505050505050505050565b60608142811015611257576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6112b57f0000000000000000000000000000000000000000000000000000000000000000898888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b915086826001845103815181106112c857fe5b60200260200101511015611323576040805162461bcd60e51b815260206004820152601f60248201527f4346543a20494e53554646494349454e545f4f55545055545f414d4f554e5400604482015290519081900360640190fd5b61133386866000818110610f5857fe5b6110db8287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b606081428110156113b3576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016868660001981018181106113ed57fe5b905060200201356001600160a01b03166001600160a01b031614611442576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b6114a07f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b915086826000815181106114b057fe5b60200260200101511115610f48576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b6000806115447f00000000000000000000000000000000000000000000000000000000000000008d7f000000000000000000000000000000000000000000000000000000000000000061340d565b9050600086611553578b611557565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018b905260ff8916608482015260a4810188905260c4810187905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156115cd57600080fd5b505af11580156115e1573d6000803e3d6000fd5b505050506115f38d8d8d8d8d8d611f8f565b9d9c50505050505050505050505050565b8042811015611643576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6116b88585600081811061165357fe5b905060200201356001600160a01b0316336116b27f00000000000000000000000000000000000000000000000000000000000000008989600081811061169557fe5b905060200201356001600160a01b03168a8a6001818110610fb757fe5b8a6134cd565b6000858560001981018181106116ca57fe5b905060200201356001600160a01b03166001600160a01b03166370a08231856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561172f57600080fd5b505afa158015611743573d6000803e3d6000fd5b505050506040513d602081101561175957600080fd5b5051604080516020888102828101820190935288825292935061179b9290918991899182918501908490808284376000920191909152508892506139a8915050565b8661184d82888860001981018181106117b057fe5b905060200201356001600160a01b03166001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b505afa158015611829573d6000803e3d6000fd5b505050506040513d602081101561183f57600080fd5b50519063ffffffff613cb316565b101561188b576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b5050505050505050565b80428110156118d4576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168585600019810181811061190e57fe5b905060200201356001600160a01b03166001600160a01b031614611963576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b6119738585600081811061165357fe5b6119b18585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152503092506139a8915050565b604080516370a0823160e01b815230600482015290516000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916370a0823191602480820192602092909190829003018186803b158015611a1b57600080fd5b505afa158015611a2f573d6000803e3d6000fd5b505050506040513d6020811015611a4557600080fd5b5051905086811015611a89576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611aef57600080fd5b505af1158015611b03573d6000803e3d6000fd5b5050505061188b84826130d9565b60608142811015611b52576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031686866000818110611b8957fe5b905060200201356001600160a01b03166001600160a01b031614611bde576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b611c3c7f0000000000000000000000000000000000000000000000000000000000000000348888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b91508682600184510381518110611c4f57fe5b60200260200101511015611c95576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db083600081518110611cd157fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d0457600080fd5b505af1158015611d18573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb611d7d7f00000000000000000000000000000000000000000000000000000000000000008989600081811061169557fe5b84600081518110611d8a57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611de157600080fd5b505af1158015611df5573d6000803e3d6000fd5b505050506040513d6020811015611e0b57600080fd5b5051611e1357fe5b611e528287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b5095945050505050565b6000610db9848484613d03565b60608142811015611eaa576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b611f087f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b91508682600081518110611f1857fe5b60200260200101511115611323576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610db9848484613df3565b60008142811015611fd0576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b611fff887f0000000000000000000000000000000000000000000000000000000000000000898989308961248e565b604080516370a0823160e01b8152306004820152905191945061208392508a9187916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b5051612f85565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156120e957600080fd5b505af11580156120fd573d6000803e3d6000fd5b505050506110db84836130d9565b804281101561214a576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168585600081811061218157fe5b905060200201356001600160a01b03166001600160a01b0316146121d6576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b60003490507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561223657600080fd5b505af115801561224a573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6122af7f00000000000000000000000000000000000000000000000000000000000000008989600081811061169557fe5b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156122ff57600080fd5b505af1158015612313573d6000803e3d6000fd5b505050506040513d602081101561232957600080fd5b505161233157fe5b60008686600019810181811061234357fe5b905060200201356001600160a01b03166001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123a857600080fd5b505afa1580156123bc573d6000803e3d6000fd5b505050506040513d60208110156123d257600080fd5b505160408051602089810282810182019093528982529293506124149290918a918a9182918501908490808284376000920191909152508992506139a8915050565b8761184d828989600019810181811061242957fe5b905060200201356001600160a01b03166001600160a01b03166370a08231896040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b60008082428110156124d0576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b60006124fd7f00000000000000000000000000000000000000000000000000000000000000008c8c61340d565b604080516323b872dd60e01b81523360048201526001600160a01b03831660248201819052604482018d9052915192935090916323b872dd916064808201926020929091908290030181600087803b15801561255857600080fd5b505af115801561256c573d6000803e3d6000fd5b505050506040513d602081101561258257600080fd5b50506040805163226bf2d160e21b81526001600160a01b03888116600483015282516000938493928616926389afcb44926024808301939282900301818787803b1580156125cf57600080fd5b505af11580156125e3573d6000803e3d6000fd5b505050506040513d60408110156125f957600080fd5b508051602090910151909250905060006126138e8e613e9f565b509050806001600160a01b03168e6001600160a01b031614612636578183612639565b82825b90975095508a87101561267e576040805162461bcd60e51b81526020600482015260086024820152674346543a2049414160c01b604482015290519081900360640190fd5b898610156126be576040805162461bcd60e51b81526020600482015260086024820152674346543a2049424160c01b604482015290519081900360640190fd5b505050505097509795505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60606111137f000000000000000000000000000000000000000000000000000000000000000084846132c1565b60008060006127707f00000000000000000000000000000000000000000000000000000000000000008e7f000000000000000000000000000000000000000000000000000000000000000061340d565b905060008761277f578c612783565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156127f957600080fd5b505af115801561280d573d6000803e3d6000fd5b5050505061281f8e8e8e8e8e8e610c97565b909f909e509c50505050505050505050505050565b60008060008342811015612878576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6128868c8c8c8c8c8c613f7d565b909450925060006128b87f00000000000000000000000000000000000000000000000000000000000000008e8e61340d565b90506128c68d3383886134cd565b6128d28c3383876134cd565b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561292a57600080fd5b505af115801561293e573d6000803e3d6000fd5b505050506040513d602081101561295457600080fd5b5051949d939c50939a509198505050505050505050565b600080600083428110156129af576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6129dd8a7f00000000000000000000000000000000000000000000000000000000000000008b348c8c613f7d565b90945092506000612a2f7f00000000000000000000000000000000000000000000000000000000000000008c7f000000000000000000000000000000000000000000000000000000000000000061340d565b9050612a3d8b3383886134cd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612a9857600080fd5b505af1158015612aac573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb82866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612b3157600080fd5b505af1158015612b45573d6000803e3d6000fd5b505050506040513d6020811015612b5b57600080fd5b5051612b6357fe5b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b158015612bbb57600080fd5b505af1158015612bcf573d6000803e3d6000fd5b505050506040513d6020811015612be557600080fd5b5051925034841015612bfd57612bfd338534036130d9565b505096509650969350505050565b60608142811015612c4c576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031686866000818110612c8357fe5b905060200201356001600160a01b03166001600160a01b031614612cd8576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b612d367f00000000000000000000000000000000000000000000000000000000000000008888888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b91503482600081518110612d4657fe5b60200260200101511115612d8c576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db083600081518110612dc857fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015612dfb57600080fd5b505af1158015612e0f573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb612e747f00000000000000000000000000000000000000000000000000000000000000008989600081811061169557fe5b84600081518110612e8157fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612ed857600080fd5b505af1158015612eec573d6000803e3d6000fd5b505050506040513d6020811015612f0257600080fd5b5051612f0a57fe5b612f498287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b81600081518110612f5657fe5b6020026020010151341115611e5257611e523383600081518110612f7657fe5b602002602001015134036130d9565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b178152925182516000946060949389169392918291908083835b602083106130025780518252601f199092019160209182019101612fe3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613064576040519150601f19603f3d011682016040523d82523d6000602084013e613069565b606091505b5091509150818015613097575080511580613097575080806020019051602081101561309457600080fd5b50515b6130d25760405162461bcd60e51b815260040180806020018281038252602d815260200180614498602d913960400191505060405180910390fd5b5050505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106131255780518252601f199092019160209182019101613106565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613187576040519150601f19603f3d011682016040523d82523d6000602084013e61318c565b606091505b50509050806131cc5760405162461bcd60e51b81526004018080602001828103825260348152602001806143f56034913960400191505060405180910390fd5b505050565b60008084116132115760405162461bcd60e51b81526004018080602001828103825260288152602001806144296028913960400191505060405180910390fd5b6000831180156132215750600082115b61325c5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b6000613270856126f763ffffffff6141f316565b90506000613284828563ffffffff6141f316565b905060006132aa8361329e8861271063ffffffff6141f316565b9063ffffffff61425616565b90508082816132b557fe5b04979650505050505050565b606060028251101561331a576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a20494e56414c49445f504154480000000000604482015290519081900360640190fd5b815167ffffffffffffffff8111801561333257600080fd5b5060405190808252806020026020018201604052801561335c578160200160208202803683370190505b509050828160008151811061336d57fe5b60200260200101818152505060005b6001835103811015613405576000806133bf8786858151811061339b57fe5b60200260200101518786600101815181106133b257fe5b60200260200101516142a5565b915091506133e18484815181106133d257fe5b602002602001015183836131d1565b8484600101815181106133f057fe5b6020908102919091010152505060010161337c565b509392505050565b600080600061341c8585613e9f565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501206001600160f81b031960688401529a90941b9093166069840152607d8301989098527fa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17815292518251600094606094938a169392918291908083835b602083106135525780518252601f199092019160209182019101613533565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146135b4576040519150601f19603f3d011682016040523d82523d6000602084013e6135b9565b606091505b50915091508180156135e75750805115806135e757508080602001905160208110156135e457600080fd5b50515b6136225760405162461bcd60e51b81526004018080602001828103825260318152602001806143c46031913960400191505060405180910390fd5b505050505050565b60005b600183510381101561386a5760008084838151811061364857fe5b602002602001015185846001018151811061365f57fe5b60200260200101519150915060006136778383613e9f565b509050600087856001018151811061368b57fe5b60200260200101519050600080836001600160a01b0316866001600160a01b0316146136b9578260006136bd565b6000835b91509150600060028a510388106136d45788613715565b6137157f0000000000000000000000000000000000000000000000000000000000000000878c8b6002018151811061370857fe5b602002602001015161340d565b90506137427f0000000000000000000000000000000000000000000000000000000000000000888861340d565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561377f576020820181803683370190505b506040518563ffffffff1660e01b815260040180858152602001848152602001836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156137f05781810151838201526020016137d8565b50505050905090810190601f16801561381d5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561383f57600080fd5b505af1158015613853573d6000803e3d6000fd5b50506001909901985061362d975050505050505050565b50505050565b60606002825110156138c9576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a20494e56414c49445f504154480000000000604482015290519081900360640190fd5b815167ffffffffffffffff811180156138e157600080fd5b5060405190808252806020026020018201604052801561390b578160200160208202803683370190505b509050828160018351038151811061391f57fe5b60209081029190910101528151600019015b8015613405576000806139618786600186038151811061394d57fe5b60200260200101518786815181106133b257fe5b9150915061398384848151811061397457fe5b60200260200101518383613d03565b84600185038151811061399257fe5b6020908102919091010152505060001901613931565b60005b60018351038110156131cc576000808483815181106139c657fe5b60200260200101518584600101815181106139dd57fe5b60200260200101519150915060006139f58383613e9f565b5090506000613a257f0000000000000000000000000000000000000000000000000000000000000000858561340d565b9050600080600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015613a6657600080fd5b505afa158015613a7a573d6000803e3d6000fd5b505050506040513d6060811015613a9057600080fd5b5080516020909101516001600160701b0391821693501690506000806001600160a01b038a811690891614613ac6578284613ac9565b83835b91509150613b27828b6001600160a01b03166370a082318a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b9550613b348683836131d1565b945050505050600080856001600160a01b0316886001600160a01b031614613b5e57826000613b62565b6000835b91509150600060028c51038a10613b79578a613bad565b613bad7f0000000000000000000000000000000000000000000000000000000000000000898e8d6002018151811061370857fe5b604080516000808252602082019283905263022c0d9f60e01b835260248201878152604483018790526001600160a01b038086166064850152608060848501908152845160a48601819052969750908c169563022c0d9f958a958a958a9591949193919260c486019290918190849084905b83811015613c37578181015183820152602001613c1f565b50505050905090810190601f168015613c645780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613c8657600080fd5b505af1158015613c9a573d6000803e3d6000fd5b50506001909b019a506139ab9950505050505050505050565b80820382811115611116576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b6000808411613d435760405162461bcd60e51b815260040180806020018281038252602981526020018061439b6029913960400191505060405180910390fd5b600083118015613d535750600082115b613d8e5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b6000613db2612710613da6868863ffffffff6141f316565b9063ffffffff6141f316565b90506000613dcc6126f7613da6868963ffffffff613cb316565b9050613de96001828481613ddc57fe5b049063ffffffff61425616565b9695505050505050565b6000808411613e335760405162461bcd60e51b81526004018080602001828103825260228152602001806143796022913960400191505060405180910390fd5b600083118015613e435750600082115b613e7e5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b82613e8f858463ffffffff6141f316565b81613e9657fe5b04949350505050565b600080826001600160a01b0316846001600160a01b03161415613ef35760405162461bcd60e51b81526004018080602001828103825260228152602001806144516022913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031610613f13578284613f16565b83835b90925090506001600160a01b038216613f76576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a205a45524f5f414444524553530000000000604482015290519081900360640190fd5b9250929050565b6040805163e6a4390560e01b81526001600160a01b03888116600483015287811660248301529151600092839283927f00000000000000000000000000000000000000000000000000000000000000009092169163e6a4390591604480820192602092909190829003018186803b158015613ff757600080fd5b505afa15801561400b573d6000803e3d6000fd5b505050506040513d602081101561402157600080fd5b50516001600160a01b031614156140d457604080516364e329cb60e11b81526001600160a01b038a81166004830152898116602483015291517f00000000000000000000000000000000000000000000000000000000000000009092169163c9c65396916044808201926020929091908290030181600087803b1580156140a757600080fd5b505af11580156140bb573d6000803e3d6000fd5b505050506040513d60208110156140d157600080fd5b50505b6000806141027f00000000000000000000000000000000000000000000000000000000000000008b8b6142a5565b91509150816000148015614114575080155b15614124578793508692506141e6565b6000614131898484613df3565b9050878111614185578581101561417a576040805162461bcd60e51b81526020600482015260086024820152674346543a2049424160c01b604482015290519081900360640190fd5b8894509250826141e4565b6000614192898486613df3565b90508981111561419e57fe5b878110156141de576040805162461bcd60e51b81526020600482015260086024820152674346543a2049414160c01b604482015290519081900360640190fd5b94508793505b505b5050965096945050505050565b600081158061420e5750508082028282828161420b57fe5b04145b611116576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b80820182811015611116576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fd5b60008060006142b48585613e9f565b5090506142c286868661340d565b506000806142d188888861340d565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561430957600080fd5b505afa15801561431d573d6000803e3d6000fd5b505050506040513d606081101561433357600080fd5b5080516020909101516001600160701b0391821693501690506001600160a01b0387811690841614614366578082614369565b81815b9099909850965050505050505056fe436f6c6466694c6962726172793a20494e53554646494349454e545f414d4f554e54436f6c6466694c6962726172793a20494e53554646494349454e545f4f55545055545f414d4f554e545472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472616e7366657246726f6d206661696c65645472616e7366657248656c7065723a3a736166655472616e736665724554483a20455448207472616e73666572206661696c6564436f6c6466694c6962726172793a20494e53554646494349454e545f494e5055545f414d4f554e54436f6c6466694c6962726172793a204944454e544943414c5f414444524553534553436f6c6466694c6962726172793a20494e53554646494349454e545f4c49515549444954595472616e7366657248656c7065723a3a736166655472616e736665723a207472616e73666572206661696c6564a2646970667358221220651fd93f2669115093e5748a4c42ad53795c42a526c6f9c48a6bd1734449179264736f6c634300060600330000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a
Deployed ByteCode
0x60806040526004361061014f5760003560e01c80638803dbee116100b6578063c45a01551161006f578063c45a015514610a10578063d06ca61f14610a25578063ded9382a14610ada578063e8e3370014610b4d578063f305d71914610bcd578063fb3bdb4114610c1357610188565b80638803dbee146107df578063ad5c464814610875578063ad615dec146108a6578063af2979eb146108dc578063b6f9de951461092f578063baa2abde146109b357610188565b80634a25d94a116101085780634a25d94a146104f05780635b0d5984146105865780635c11d795146105f9578063791ac9471461068f5780637ff36ab51461072557806385f8c259146107a957610188565b806302751cec1461018d578063054d50d4146101f957806318cbafe5146102415780631f00ca74146103275780632195995c146103dc57806338ed17391461045a57610188565b3661018857336001600160a01b037f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a161461018657fe5b005b600080fd5b34801561019957600080fd5b506101e0600480360360c08110156101b057600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135610c97565b6040805192835260208301919091528051918290030190f35b34801561020557600080fd5b5061022f6004803603606081101561021c57600080fd5b5080359060208101359060400135610dac565b60408051918252519081900360200190f35b34801561024d57600080fd5b506102d7600480360360a081101561026457600080fd5b813591602081013591810190606081016040820135600160201b81111561028a57600080fd5b82018360208201111561029c57600080fd5b803590602001918460208302840111600160201b831117156102bd57600080fd5b91935091506001600160a01b038135169060200135610dc1565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103135781810151838201526020016102fb565b505050509050019250505060405180910390f35b34801561033357600080fd5b506102d76004803603604081101561034a57600080fd5b81359190810190604081016020820135600160201b81111561036b57600080fd5b82018360208201111561037d57600080fd5b803590602001918460208302840111600160201b8311171561039e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506110e6945050505050565b3480156103e857600080fd5b506101e0600480360361016081101561040057600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c08101359060e081013515159060ff610100820135169061012081013590610140013561111c565b34801561046657600080fd5b506102d7600480360360a081101561047d57600080fd5b813591602081013591810190606081016040820135600160201b8111156104a357600080fd5b8201836020820111156104b557600080fd5b803590602001918460208302840111600160201b831117156104d657600080fd5b91935091506001600160a01b038135169060200135611216565b3480156104fc57600080fd5b506102d7600480360360a081101561051357600080fd5b813591602081013591810190606081016040820135600160201b81111561053957600080fd5b82018360208201111561054b57600080fd5b803590602001918460208302840111600160201b8311171561056c57600080fd5b91935091506001600160a01b038135169060200135611372565b34801561059257600080fd5b5061022f60048036036101408110156105aa57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e082013516906101008101359061012001356114f6565b34801561060557600080fd5b50610186600480360360a081101561061c57600080fd5b813591602081013591810190606081016040820135600160201b81111561064257600080fd5b82018360208201111561065457600080fd5b803590602001918460208302840111600160201b8311171561067557600080fd5b91935091506001600160a01b038135169060200135611604565b34801561069b57600080fd5b50610186600480360360a08110156106b257600080fd5b813591602081013591810190606081016040820135600160201b8111156106d857600080fd5b8201836020820111156106ea57600080fd5b803590602001918460208302840111600160201b8311171561070b57600080fd5b91935091506001600160a01b038135169060200135611895565b6102d76004803603608081101561073b57600080fd5b81359190810190604081016020820135600160201b81111561075c57600080fd5b82018360208201111561076e57600080fd5b803590602001918460208302840111600160201b8311171561078f57600080fd5b91935091506001600160a01b038135169060200135611b11565b3480156107b557600080fd5b5061022f600480360360608110156107cc57600080fd5b5080359060208101359060400135611e5c565b3480156107eb57600080fd5b506102d7600480360360a081101561080257600080fd5b813591602081013591810190606081016040820135600160201b81111561082857600080fd5b82018360208201111561083a57600080fd5b803590602001918460208302840111600160201b8311171561085b57600080fd5b91935091506001600160a01b038135169060200135611e69565b34801561088157600080fd5b5061088a611f5e565b604080516001600160a01b039092168252519081900360200190f35b3480156108b257600080fd5b5061022f600480360360608110156108c957600080fd5b5080359060208101359060400135611f82565b3480156108e857600080fd5b5061022f600480360360c08110156108ff57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a00135611f8f565b6101866004803603608081101561094557600080fd5b81359190810190604081016020820135600160201b81111561096657600080fd5b82018360208201111561097857600080fd5b803590602001918460208302840111600160201b8311171561099957600080fd5b91935091506001600160a01b03813516906020013561210b565b3480156109bf57600080fd5b506101e0600480360360e08110156109d657600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359091169060c0013561248e565b348015610a1c57600080fd5b5061088a6126cf565b348015610a3157600080fd5b506102d760048036036040811015610a4857600080fd5b81359190810190604081016020820135600160201b811115610a6957600080fd5b820183602082011115610a7b57600080fd5b803590602001918460208302840111600160201b83111715610a9c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506126f3945050505050565b348015610ae657600080fd5b506101e06004803603610140811015610afe57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e08201351690610100810135906101200135612720565b348015610b5957600080fd5b50610baf6004803603610100811015610b7157600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359160808201359160a08101359160c0820135169060e00135612834565b60408051938452602084019290925282820152519081900360600190f35b610baf600480360360c0811015610be357600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a0013561296b565b6102d760048036036080811015610c2957600080fd5b81359190810190604081016020820135600160201b811115610c4a57600080fd5b820183602082011115610c5c57600080fd5b803590602001918460208302840111600160201b83111715610c7d57600080fd5b91935091506001600160a01b038135169060200135612c0b565b6000808242811015610cd9576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b610d08897f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a8a8a8a308a61248e565b9093509150610d18898685612f85565b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015610d7e57600080fd5b505af1158015610d92573d6000803e3d6000fd5b50505050610da085836130d9565b50965096945050505050565b6000610db98484846131d1565b949350505050565b60608142811015610e02576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a1686866000198101818110610e3c57fe5b905060200201356001600160a01b03166001600160a01b031614610e91576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b610eef7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc898888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b91508682600184510381518110610f0257fe5b60200260200101511015610f48576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b610fe686866000818110610f5857fe5b905060200201356001600160a01b031633610fcc7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8a8a6000818110610f9a57fe5b905060200201356001600160a01b03168b8b6001818110610fb757fe5b905060200201356001600160a01b031661340d565b85600081518110610fd957fe5b60200260200101516134cd565b6110258287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525030925061362a915050565b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b0316632e1a7d4d8360018551038151811061106457fe5b60200260200101516040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156110a257600080fd5b505af11580156110b6573d6000803e3d6000fd5b505050506110db84836001855103815181106110ce57fe5b60200260200101516130d9565b509695505050505050565b60606111137f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8484613870565b90505b92915050565b600080600061114c7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8f8f61340d565b905060008761115b578c61115f565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156111d557600080fd5b505af11580156111e9573d6000803e3d6000fd5b505050506111fc8f8f8f8f8f8f8f61248e565b809450819550505050509b509b9950505050505050505050565b60608142811015611257576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6112b57f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc898888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b915086826001845103815181106112c857fe5b60200260200101511015611323576040805162461bcd60e51b815260206004820152601f60248201527f4346543a20494e53554646494349454e545f4f55545055545f414d4f554e5400604482015290519081900360640190fd5b61133386866000818110610f5857fe5b6110db8287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b606081428110156113b3576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a16868660001981018181106113ed57fe5b905060200201356001600160a01b03166001600160a01b031614611442576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b6114a07f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b915086826000815181106114b057fe5b60200260200101511115610f48576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b6000806115447f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8d7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a61340d565b9050600086611553578b611557565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018b905260ff8916608482015260a4810188905260c4810187905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156115cd57600080fd5b505af11580156115e1573d6000803e3d6000fd5b505050506115f38d8d8d8d8d8d611f8f565b9d9c50505050505050505050505050565b8042811015611643576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6116b88585600081811061165357fe5b905060200201356001600160a01b0316336116b27f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8989600081811061169557fe5b905060200201356001600160a01b03168a8a6001818110610fb757fe5b8a6134cd565b6000858560001981018181106116ca57fe5b905060200201356001600160a01b03166001600160a01b03166370a08231856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561172f57600080fd5b505afa158015611743573d6000803e3d6000fd5b505050506040513d602081101561175957600080fd5b5051604080516020888102828101820190935288825292935061179b9290918991899182918501908490808284376000920191909152508892506139a8915050565b8661184d82888860001981018181106117b057fe5b905060200201356001600160a01b03166001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b505afa158015611829573d6000803e3d6000fd5b505050506040513d602081101561183f57600080fd5b50519063ffffffff613cb316565b101561188b576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b5050505050505050565b80428110156118d4576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6001600160a01b037f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a168585600019810181811061190e57fe5b905060200201356001600160a01b03166001600160a01b031614611963576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b6119738585600081811061165357fe5b6119b18585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152503092506139a8915050565b604080516370a0823160e01b815230600482015290516000916001600160a01b037f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a16916370a0823191602480820192602092909190829003018186803b158015611a1b57600080fd5b505afa158015611a2f573d6000803e3d6000fd5b505050506040513d6020811015611a4557600080fd5b5051905086811015611a89576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611aef57600080fd5b505af1158015611b03573d6000803e3d6000fd5b5050505061188b84826130d9565b60608142811015611b52576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031686866000818110611b8957fe5b905060200201356001600160a01b03166001600160a01b031614611bde576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b611c3c7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc348888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132c192505050565b91508682600184510381518110611c4f57fe5b60200260200101511015611c95576040805162461bcd60e51b81526020600482015260086024820152674346543a20494f4160c01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663d0e30db083600081518110611cd157fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d0457600080fd5b505af1158015611d18573d6000803e3d6000fd5b50505050507f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663a9059cbb611d7d7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8989600081811061169557fe5b84600081518110611d8a57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611de157600080fd5b505af1158015611df5573d6000803e3d6000fd5b505050506040513d6020811015611e0b57600080fd5b5051611e1357fe5b611e528287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b5095945050505050565b6000610db9848484613d03565b60608142811015611eaa576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b611f087f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b91508682600081518110611f1857fe5b60200260200101511115611323576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a81565b6000610db9848484613df3565b60008142811015611fd0576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b611fff887f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a898989308961248e565b604080516370a0823160e01b8152306004820152905191945061208392508a9187916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b5051612f85565b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156120e957600080fd5b505af11580156120fd573d6000803e3d6000fd5b505050506110db84836130d9565b804281101561214a576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b03168585600081811061218157fe5b905060200201356001600160a01b03166001600160a01b0316146121d6576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b60003490507f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561223657600080fd5b505af115801561224a573d6000803e3d6000fd5b50505050507f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663a9059cbb6122af7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8989600081811061169557fe5b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156122ff57600080fd5b505af1158015612313573d6000803e3d6000fd5b505050506040513d602081101561232957600080fd5b505161233157fe5b60008686600019810181811061234357fe5b905060200201356001600160a01b03166001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123a857600080fd5b505afa1580156123bc573d6000803e3d6000fd5b505050506040513d60208110156123d257600080fd5b505160408051602089810282810182019093528982529293506124149290918a918a9182918501908490808284376000920191909152508992506139a8915050565b8761184d828989600019810181811061242957fe5b905060200201356001600160a01b03166001600160a01b03166370a08231896040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b60008082428110156124d0576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b60006124fd7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8c8c61340d565b604080516323b872dd60e01b81523360048201526001600160a01b03831660248201819052604482018d9052915192935090916323b872dd916064808201926020929091908290030181600087803b15801561255857600080fd5b505af115801561256c573d6000803e3d6000fd5b505050506040513d602081101561258257600080fd5b50506040805163226bf2d160e21b81526001600160a01b03888116600483015282516000938493928616926389afcb44926024808301939282900301818787803b1580156125cf57600080fd5b505af11580156125e3573d6000803e3d6000fd5b505050506040513d60408110156125f957600080fd5b508051602090910151909250905060006126138e8e613e9f565b509050806001600160a01b03168e6001600160a01b031614612636578183612639565b82825b90975095508a87101561267e576040805162461bcd60e51b81526020600482015260086024820152674346543a2049414160c01b604482015290519081900360640190fd5b898610156126be576040805162461bcd60e51b81526020600482015260086024820152674346543a2049424160c01b604482015290519081900360640190fd5b505050505097509795505050505050565b7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc81565b60606111137f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc84846132c1565b60008060006127707f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8e7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a61340d565b905060008761277f578c612783565b6000195b6040805163d505accf60e01b815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c4810188905290519192506001600160a01b0384169163d505accf9160e48082019260009290919082900301818387803b1580156127f957600080fd5b505af115801561280d573d6000803e3d6000fd5b5050505061281f8e8e8e8e8e8e610c97565b909f909e509c50505050505050505050505050565b60008060008342811015612878576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6128868c8c8c8c8c8c613f7d565b909450925060006128b87f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8e8e61340d565b90506128c68d3383886134cd565b6128d28c3383876134cd565b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561292a57600080fd5b505af115801561293e573d6000803e3d6000fd5b505050506040513d602081101561295457600080fd5b5051949d939c50939a509198505050505050505050565b600080600083428110156129af576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b6129dd8a7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a8b348c8c613f7d565b90945092506000612a2f7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8c7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a61340d565b9050612a3d8b3383886134cd565b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015612a9857600080fd5b505af1158015612aac573d6000803e3d6000fd5b50505050507f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663a9059cbb82866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612b3157600080fd5b505af1158015612b45573d6000803e3d6000fd5b505050506040513d6020811015612b5b57600080fd5b5051612b6357fe5b806001600160a01b0316636a627842886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b158015612bbb57600080fd5b505af1158015612bcf573d6000803e3d6000fd5b505050506040513d6020811015612be557600080fd5b5051925034841015612bfd57612bfd338534036130d9565b505096509650969350505050565b60608142811015612c4c576040805162461bcd60e51b81526020600482015260066024820152654346543a204560d01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031686866000818110612c8357fe5b905060200201356001600160a01b03166001600160a01b031614612cd8576040805162461bcd60e51b815260206004820152600760248201526604346543a2057560cc1b604482015290519081900360640190fd5b612d367f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8888888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061387092505050565b91503482600081518110612d4657fe5b60200260200101511115612d8c576040805162461bcd60e51b81526020600482015260086024820152674346543a2045494160c01b604482015290519081900360640190fd5b7f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663d0e30db083600081518110612dc857fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015612dfb57600080fd5b505af1158015612e0f573d6000803e3d6000fd5b50505050507f000000000000000000000000f5ad6f6edec824c7fd54a66d241a227f6503ad3a6001600160a01b031663a9059cbb612e747f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8989600081811061169557fe5b84600081518110612e8157fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612ed857600080fd5b505af1158015612eec573d6000803e3d6000fd5b505050506040513d6020811015612f0257600080fd5b5051612f0a57fe5b612f498287878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525089925061362a915050565b81600081518110612f5657fe5b6020026020010151341115611e5257611e523383600081518110612f7657fe5b602002602001015134036130d9565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b178152925182516000946060949389169392918291908083835b602083106130025780518252601f199092019160209182019101612fe3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613064576040519150601f19603f3d011682016040523d82523d6000602084013e613069565b606091505b5091509150818015613097575080511580613097575080806020019051602081101561309457600080fd5b50515b6130d25760405162461bcd60e51b815260040180806020018281038252602d815260200180614498602d913960400191505060405180910390fd5b5050505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106131255780518252601f199092019160209182019101613106565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613187576040519150601f19603f3d011682016040523d82523d6000602084013e61318c565b606091505b50509050806131cc5760405162461bcd60e51b81526004018080602001828103825260348152602001806143f56034913960400191505060405180910390fd5b505050565b60008084116132115760405162461bcd60e51b81526004018080602001828103825260288152602001806144296028913960400191505060405180910390fd5b6000831180156132215750600082115b61325c5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b6000613270856126f763ffffffff6141f316565b90506000613284828563ffffffff6141f316565b905060006132aa8361329e8861271063ffffffff6141f316565b9063ffffffff61425616565b90508082816132b557fe5b04979650505050505050565b606060028251101561331a576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a20494e56414c49445f504154480000000000604482015290519081900360640190fd5b815167ffffffffffffffff8111801561333257600080fd5b5060405190808252806020026020018201604052801561335c578160200160208202803683370190505b509050828160008151811061336d57fe5b60200260200101818152505060005b6001835103811015613405576000806133bf8786858151811061339b57fe5b60200260200101518786600101815181106133b257fe5b60200260200101516142a5565b915091506133e18484815181106133d257fe5b602002602001015183836131d1565b8484600101815181106133f057fe5b6020908102919091010152505060010161337c565b509392505050565b600080600061341c8585613e9f565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501206001600160f81b031960688401529a90941b9093166069840152607d8301989098527fa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17815292518251600094606094938a169392918291908083835b602083106135525780518252601f199092019160209182019101613533565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146135b4576040519150601f19603f3d011682016040523d82523d6000602084013e6135b9565b606091505b50915091508180156135e75750805115806135e757508080602001905160208110156135e457600080fd5b50515b6136225760405162461bcd60e51b81526004018080602001828103825260318152602001806143c46031913960400191505060405180910390fd5b505050505050565b60005b600183510381101561386a5760008084838151811061364857fe5b602002602001015185846001018151811061365f57fe5b60200260200101519150915060006136778383613e9f565b509050600087856001018151811061368b57fe5b60200260200101519050600080836001600160a01b0316866001600160a01b0316146136b9578260006136bd565b6000835b91509150600060028a510388106136d45788613715565b6137157f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc878c8b6002018151811061370857fe5b602002602001015161340d565b90506137427f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc888861340d565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561377f576020820181803683370190505b506040518563ffffffff1660e01b815260040180858152602001848152602001836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156137f05781810151838201526020016137d8565b50505050905090810190601f16801561381d5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561383f57600080fd5b505af1158015613853573d6000803e3d6000fd5b50506001909901985061362d975050505050505050565b50505050565b60606002825110156138c9576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a20494e56414c49445f504154480000000000604482015290519081900360640190fd5b815167ffffffffffffffff811180156138e157600080fd5b5060405190808252806020026020018201604052801561390b578160200160208202803683370190505b509050828160018351038151811061391f57fe5b60209081029190910101528151600019015b8015613405576000806139618786600186038151811061394d57fe5b60200260200101518786815181106133b257fe5b9150915061398384848151811061397457fe5b60200260200101518383613d03565b84600185038151811061399257fe5b6020908102919091010152505060001901613931565b60005b60018351038110156131cc576000808483815181106139c657fe5b60200260200101518584600101815181106139dd57fe5b60200260200101519150915060006139f58383613e9f565b5090506000613a257f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc858561340d565b9050600080600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015613a6657600080fd5b505afa158015613a7a573d6000803e3d6000fd5b505050506040513d6060811015613a9057600080fd5b5080516020909101516001600160701b0391821693501690506000806001600160a01b038a811690891614613ac6578284613ac9565b83835b91509150613b27828b6001600160a01b03166370a082318a6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561181557600080fd5b9550613b348683836131d1565b945050505050600080856001600160a01b0316886001600160a01b031614613b5e57826000613b62565b6000835b91509150600060028c51038a10613b79578a613bad565b613bad7f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc898e8d6002018151811061370857fe5b604080516000808252602082019283905263022c0d9f60e01b835260248201878152604483018790526001600160a01b038086166064850152608060848501908152845160a48601819052969750908c169563022c0d9f958a958a958a9591949193919260c486019290918190849084905b83811015613c37578181015183820152602001613c1f565b50505050905090810190601f168015613c645780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015613c8657600080fd5b505af1158015613c9a573d6000803e3d6000fd5b50506001909b019a506139ab9950505050505050505050565b80820382811115611116576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b6000808411613d435760405162461bcd60e51b815260040180806020018281038252602981526020018061439b6029913960400191505060405180910390fd5b600083118015613d535750600082115b613d8e5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b6000613db2612710613da6868863ffffffff6141f316565b9063ffffffff6141f316565b90506000613dcc6126f7613da6868963ffffffff613cb316565b9050613de96001828481613ddc57fe5b049063ffffffff61425616565b9695505050505050565b6000808411613e335760405162461bcd60e51b81526004018080602001828103825260228152602001806143796022913960400191505060405180910390fd5b600083118015613e435750600082115b613e7e5760405162461bcd60e51b81526004018080602001828103825260258152602001806144736025913960400191505060405180910390fd5b82613e8f858463ffffffff6141f316565b81613e9657fe5b04949350505050565b600080826001600160a01b0316846001600160a01b03161415613ef35760405162461bcd60e51b81526004018080602001828103825260228152602001806144516022913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031610613f13578284613f16565b83835b90925090506001600160a01b038216613f76576040805162461bcd60e51b815260206004820152601b60248201527f436f6c6466694c6962726172793a205a45524f5f414444524553530000000000604482015290519081900360640190fd5b9250929050565b6040805163e6a4390560e01b81526001600160a01b03888116600483015287811660248301529151600092839283927f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc9092169163e6a4390591604480820192602092909190829003018186803b158015613ff757600080fd5b505afa15801561400b573d6000803e3d6000fd5b505050506040513d602081101561402157600080fd5b50516001600160a01b031614156140d457604080516364e329cb60e11b81526001600160a01b038a81166004830152898116602483015291517f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc9092169163c9c65396916044808201926020929091908290030181600087803b1580156140a757600080fd5b505af11580156140bb573d6000803e3d6000fd5b505050506040513d60208110156140d157600080fd5b50505b6000806141027f0000000000000000000000001e1ca2eaffafadd63f8a833704ad39a0ee847fdc8b8b6142a5565b91509150816000148015614114575080155b15614124578793508692506141e6565b6000614131898484613df3565b9050878111614185578581101561417a576040805162461bcd60e51b81526020600482015260086024820152674346543a2049424160c01b604482015290519081900360640190fd5b8894509250826141e4565b6000614192898486613df3565b90508981111561419e57fe5b878110156141de576040805162461bcd60e51b81526020600482015260086024820152674346543a2049414160c01b604482015290519081900360640190fd5b94508793505b505b5050965096945050505050565b600081158061420e5750508082028282828161420b57fe5b04145b611116576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b80820182811015611116576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fd5b60008060006142b48585613e9f565b5090506142c286868661340d565b506000806142d188888861340d565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561430957600080fd5b505afa15801561431d573d6000803e3d6000fd5b505050506040513d606081101561433357600080fd5b5080516020909101516001600160701b0391821693501690506001600160a01b0387811690841614614366578082614369565b81815b9099909850965050505050505056fe436f6c6466694c6962726172793a20494e53554646494349454e545f414d4f554e54436f6c6466694c6962726172793a20494e53554646494349454e545f4f55545055545f414d4f554e545472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472616e7366657246726f6d206661696c65645472616e7366657248656c7065723a3a736166655472616e736665724554483a20455448207472616e73666572206661696c6564436f6c6466694c6962726172793a20494e53554646494349454e545f494e5055545f414d4f554e54436f6c6466694c6962726172793a204944454e544943414c5f414444524553534553436f6c6466694c6962726172793a20494e53554646494349454e545f4c49515549444954595472616e7366657248656c7065723a3a736166655472616e736665723a207472616e73666572206661696c6564a2646970667358221220651fd93f2669115093e5748a4c42ad53795c42a526c6f9c48a6bd1734449179264736f6c63430006060033