More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 692,468 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Swap Exact Token... | 19157490 | 5 hrs ago | IN | 0 ETH | 0.00002538 | ||||
Swap Exact Token... | 19153746 | 8 hrs ago | IN | 0 ETH | 0.00002192 | ||||
Swap Exact Token... | 19135745 | 26 hrs ago | IN | 0 ETH | 0.00001872 | ||||
Swap Exact Token... | 19135652 | 26 hrs ago | IN | 0 ETH | 0.00001861 | ||||
Swap Exact Token... | 19130703 | 31 hrs ago | IN | 0 ETH | 0.00003146 | ||||
Swap Exact Token... | 19123413 | 38 hrs ago | IN | 0 ETH | 0.00001177 | ||||
Swap Exact Token... | 19119955 | 41 hrs ago | IN | 0 ETH | 0.00000588 | ||||
Swap Exact Token... | 19103133 | 2 days ago | IN | 0 ETH | 0.00000881 | ||||
Swap Exact Token... | 19102387 | 2 days ago | IN | 0 ETH | 0.00000488 | ||||
Swap Exact Token... | 19097909 | 2 days ago | IN | 0 ETH | 0.0000077 | ||||
Swap Exact Token... | 19095840 | 2 days ago | IN | 0 ETH | 0.00000458 | ||||
Swap Exact Token... | 19093263 | 2 days ago | IN | 0 ETH | 0.00000497 | ||||
Swap Exact Token... | 19091945 | 2 days ago | IN | 0 ETH | 0.00000565 | ||||
Swap Exact Token... | 19079870 | 3 days ago | IN | 0 ETH | 0.00000864 | ||||
Swap Exact Token... | 19042967 | 4 days ago | IN | 0 ETH | 0.0000097 | ||||
Swap Exact Token... | 19042832 | 4 days ago | IN | 0 ETH | 0.0000089 | ||||
Swap Exact Token... | 19042811 | 4 days ago | IN | 0 ETH | 0.00001027 | ||||
Swap Exact Token... | 19042757 | 4 days ago | IN | 0 ETH | 0.00001092 | ||||
Swap Exact Token... | 19042751 | 4 days ago | IN | 0 ETH | 0.00000878 | ||||
Swap Exact Token... | 19041598 | 4 days ago | IN | 0 ETH | 0.00000868 | ||||
Swap Exact Token... | 19041183 | 4 days ago | IN | 0 ETH | 0.00000756 | ||||
Swap Exact Token... | 19022364 | 5 days ago | IN | 0 ETH | 0.00001023 | ||||
Swap Exact Token... | 19022111 | 5 days ago | IN | 0 ETH | 0.00001115 | ||||
Swap Exact Token... | 19021841 | 5 days ago | IN | 0 ETH | 0.0000102 | ||||
Swap Exact Token... | 19021699 | 5 days ago | IN | 0 ETH | 0.00001029 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19157490 | 5 hrs ago | 0.00024695 ETH | ||||
19157490 | 5 hrs ago | 0.00024695 ETH | ||||
19153746 | 8 hrs ago | 0.00005982 ETH | ||||
19153746 | 8 hrs ago | 0.00005982 ETH | ||||
19135745 | 26 hrs ago | 0.00007411 ETH | ||||
19135745 | 26 hrs ago | 0.00007411 ETH | ||||
19135652 | 26 hrs ago | 0.00010274 ETH | ||||
19135652 | 26 hrs ago | 0.00010274 ETH | ||||
19130703 | 31 hrs ago | 0.00010336 ETH | ||||
19130703 | 31 hrs ago | 0.00010336 ETH | ||||
19119955 | 41 hrs ago | 0.00327472 ETH | ||||
19119955 | 41 hrs ago | 0.00327472 ETH | ||||
19103133 | 2 days ago | 0.00008866 ETH | ||||
19103133 | 2 days ago | 0.00008866 ETH | ||||
19102387 | 2 days ago | 0.00010679 ETH | ||||
19102387 | 2 days ago | 0.00010679 ETH | ||||
19095840 | 2 days ago | 0.0000896 ETH | ||||
19095840 | 2 days ago | 0.0000896 ETH | ||||
19093263 | 2 days ago | 0.00008865 ETH | ||||
19093263 | 2 days ago | 0.00008865 ETH | ||||
19091945 | 2 days ago | 0.00009037 ETH | ||||
19091945 | 2 days ago | 0.00009037 ETH | ||||
19079870 | 3 days ago | 0.00017896 ETH | ||||
19079870 | 3 days ago | 0.00017896 ETH | ||||
19042967 | 4 days ago | 0.00003208 ETH |
Loading...
Loading
Contract Name:
AntfarmRouter
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; import "../interfaces/IAntfarmRouter.sol"; import "../interfaces/IAntfarmPair.sol"; import "../interfaces/IAntfarmFactory.sol"; import "../interfaces/IERC20.sol"; import "../interfaces/IWETH.sol"; import "../libraries/TransferHelper.sol"; import "./AntfarmOracle.sol"; import "../utils/AntfarmRouterErrors.sol"; /// @title Antfarm Router for AntFarmPair /// @notice High-level contract that serves as the entrypoint for swapping contract AntfarmRouter is IAntfarmRouter { address public immutable factory; address public immutable WETH; address public immutable antfarmToken; modifier ensure(uint256 deadline) { if (deadline < block.timestamp) revert Expired(); _; } constructor( address _factory, address _WETH, address _antfarmToken ) { require(_factory != address(0), "NULL_FACTORY_ADDRESS"); require(_WETH != address(0), "NULL_WETH_ADDRESS"); require(_antfarmToken != address(0), "NULL_ATF_ADDRESS"); factory = _factory; WETH = _WETH; antfarmToken = _antfarmToken; } receive() external payable { assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract } /// @notice Swaps an exact amount of input tokens for as many output tokens as possible /// @param params The parameters necessary for the swap, encoded as `swapExactTokensForTokensParams` in calldata // @param amountIn The amount of input tokens to send // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapExactTokensForTokens( swapExactTokensForTokensParams calldata params ) external virtual ensure(params.deadline) returns (uint256[] memory amounts) { uint256 amountIn = params.path[0] == antfarmToken ? (params.amountIn * (1000 + params.fees[0])) / 1000 : params.amountIn; amounts = getAmountsOut(amountIn, params.path, params.fees); if (amounts[amounts.length - 1] < params.amountOutMin) { revert InsufficientOutputAmount(); } TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ); if ( _swap(amounts, params.path, params.fees, params.to) > params.maxFee ) { revert InsufficientMaxFee(); } } /// @notice Receive an exact amount of output tokens for as few input tokens as possible /// @param params The parameters necessary for the swap, encoded as `swapTokensForExactTokensParams` in calldata // @param amountOut The amount of output tokens to receive // @param amountInMax The maximum amount of input tokens that can be required before the transaction reverts // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapTokensForExactTokens( swapTokensForExactTokensParams calldata params ) external virtual ensure(params.deadline) returns (uint256[] memory amounts) { uint256 amountInMax = params.path[0] == antfarmToken ? (params.amountInMax * (1000 + params.fees[0])) / 1000 : params.amountInMax; amounts = getAmountsIn(params.amountOut, params.path, params.fees); if (amounts[0] > amountInMax) revert ExcessiveInputAmount(); TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ); if ( _swap(amounts, params.path, params.fees, params.to) > params.maxFee ) { revert InsufficientMaxFee(); } } /// @notice Swaps an exact amount of ETH for as many output tokens as possible /// @param params The parameters necessary for the swap, encoded as `swapExactETHForTokensParams` in calldata // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapExactETHForTokens(swapExactETHForTokensParams calldata params) external payable virtual ensure(params.deadline) returns (uint256[] memory amounts) { if (params.path[0] != WETH) revert InvalidPath(); amounts = getAmountsOut(msg.value, params.path, params.fees); if (amounts[amounts.length - 1] < params.amountOutMin) { revert InsufficientOutputAmount(); } IWETH(WETH).deposit{value: amounts[0]}(); assert( IWETH(WETH).transfer( pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ) ); if ( _swap(amounts, params.path, params.fees, params.to) > params.maxFee ) { revert InsufficientMaxFee(); } } /// @notice Receive an exact amount of ETH for as few input tokens as possible /// @param params The parameters necessary for the swap, encoded as `swapTokensForExactETHParams` in calldata // @param amountOut The amount of ETH to receive // @param amountInMax The maximum amount of input tokens that can be required before the transaction reverts // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapTokensForExactETH(swapTokensForExactETHParams calldata params) external virtual ensure(params.deadline) returns (uint256[] memory amounts) { if (params.path[params.path.length - 1] != WETH) revert InvalidPath(); uint256 amountInMax = params.path[0] == antfarmToken ? (params.amountInMax * (1000 + params.fees[0])) / 1000 : params.amountInMax; amounts = getAmountsIn(params.amountOut, params.path, params.fees); if (amounts[0] > amountInMax) revert ExcessiveInputAmount(); TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ); if ( _swap(amounts, params.path, params.fees, address(this)) > params.maxFee ) { revert InsufficientMaxFee(); } IWETH(WETH).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferETH(params.to, amounts[amounts.length - 1]); } /// @notice Swaps an exact amount of tokens for as much ETH as possible /// @param params The parameters necessary for the swap, encoded as `swapExactTokensForETHParams` in calldata // @param amountIn The amount of input tokens to send // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapExactTokensForETH(swapExactTokensForETHParams calldata params) external virtual ensure(params.deadline) returns (uint256[] memory amounts) { uint256 amountIn = params.path[0] == antfarmToken ? (params.amountIn * (1000 + params.fees[0])) / 1000 : params.amountIn; if (params.path[params.path.length - 1] != WETH) revert InvalidPath(); amounts = getAmountsOut(amountIn, params.path, params.fees); if (amounts[amounts.length - 1] < params.amountOutMin) { revert InsufficientOutputAmount(); } TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ); if ( _swap(amounts, params.path, params.fees, address(this)) > params.maxFee ) { revert InsufficientMaxFee(); } IWETH(WETH).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferETH(params.to, amounts[amounts.length - 1]); } /// @notice Receive an exact amount of tokens for as little ETH as possible /// @param params The parameters necessary for the swap, encoded as `swapETHForExactTokensParams` in calldata // @param amountOut The amount of tokens to receive // @param maxFee Maximum fees to be paid // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert /// @return amounts The input token amount and all subsequent output token amounts function swapETHForExactTokens(swapETHForExactTokensParams calldata params) external payable virtual ensure(params.deadline) returns (uint256[] memory amounts) { if (params.path[0] != WETH) revert InvalidPath(); amounts = getAmountsIn(params.amountOut, params.path, params.fees); if (amounts[0] > msg.value) revert ExcessiveInputAmount(); IWETH(WETH).deposit{value: amounts[0]}(); assert( IWETH(WETH).transfer( pairFor(params.path[0], params.path[1], params.fees[0]), amounts[0] ) ); if ( _swap(amounts, params.path, params.fees, params.to) > params.maxFee ) { revert InsufficientMaxFee(); } // refund dust ETH if any if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]); } /// @notice Identical to swapExactTokensForTokens, but succeeds for tokens that take a fee on transfer /// @param params The parameters necessary for the swap, encoded as `swapExactTokensForTokensParams` in calldata // @param amountIn The amount of input tokens to send // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert function swapExactTokensForTokensSupportingFeeOnTransferTokens( swapExactTokensForTokensParams calldata params ) external virtual ensure(params.deadline) { TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), params.amountIn ); uint256 balanceBefore = IERC20(params.path[params.path.length - 1]) .balanceOf(params.to); swapParams memory sParams = swapParams( params.path, params.fees, params.to ); if (_swapSupportingFeeOnTransferTokens(sParams) > params.maxFee) { revert InsufficientMaxFee(); } if ( IERC20(params.path[params.path.length - 1]).balanceOf(params.to) - balanceBefore < params.amountOutMin ) { revert InsufficientOutputAmount(); } } /// @notice Identical to swapExactETHForTokens, but succeeds for tokens that take a fee on transfer /// @param params The parameters necessary for the swap, encoded as `swapExactETHForTokensParams` in calldata // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert function swapExactETHForTokensSupportingFeeOnTransferTokens( swapExactETHForTokensParams calldata params ) external payable virtual ensure(params.deadline) { if (params.path[0] != WETH) revert InvalidPath(); uint256 amountIn = msg.value; IWETH(WETH).deposit{value: amountIn}(); assert( IWETH(WETH).transfer( pairFor(params.path[0], params.path[1], params.fees[0]), amountIn ) ); uint256 balanceBefore = IERC20(params.path[params.path.length - 1]) .balanceOf(params.to); swapParams memory sParams = swapParams( params.path, params.fees, params.to ); if (_swapSupportingFeeOnTransferTokens(sParams) > params.maxFee) { revert InsufficientMaxFee(); } if ( IERC20(params.path[params.path.length - 1]).balanceOf(params.to) - balanceBefore < params.amountOutMin ) { revert InsufficientOutputAmount(); } } /// @notice Identical to swapExactTokensForETH, but succeeds for tokens that take a fee on transfer /// @param params The parameters necessary for the swap, encoded as `swapExactTokensForETHParams` in calldata // @param amountIn The amount of input tokens to send // @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert // @param path An array of token addresses // @param fees Associated fee for each two token addresses within the path // @param to Recipient of the output tokens // @param deadline Unix timestamp after which the transaction will revert function swapExactTokensForETHSupportingFeeOnTransferTokens( swapExactTokensForETHParams calldata params ) external virtual ensure(params.deadline) { if (params.path[params.path.length - 1] != WETH) revert InvalidPath(); TransferHelper.safeTransferFrom( params.path[0], msg.sender, pairFor(params.path[0], params.path[1], params.fees[0]), params.amountIn ); swapParams memory sParams = swapParams( params.path, params.fees, address(this) ); if (_swapSupportingFeeOnTransferTokens(sParams) > params.maxFee) { revert InsufficientMaxFee(); } uint256 amountOut = IERC20(WETH).balanceOf(address(this)); if (amountOut < params.amountOutMin) revert InsufficientOutputAmount(); IWETH(WETH).withdraw(amountOut); TransferHelper.safeTransferETH(params.to, amountOut); } // fetches and sorts the reserves for a pair function getReserves( address tokenA, address tokenB, uint16 fee ) public view returns (uint256 reserveA, uint256 reserveB) { (address token0, ) = sortTokens(tokenA, tokenB); (uint256 reserve0, uint256 reserve1, ) = IAntfarmPair( pairFor(tokenA, tokenB, fee) ).getReserves(); (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); } // SWAP // requires the initial amount to have already been sent to the first pair function _swap( uint256[] memory amounts, address[] memory path, uint16[] memory fees, address _to ) internal virtual returns (uint256 totalFee) { for (uint256 i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); uint16 fee = fees[i]; IAntfarmPair antfarmPair = IAntfarmPair( pairFor(input, output, fee) ); (address token0, ) = sortTokens(input, output); (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amounts[i + 1]) : (amounts[i + 1], uint256(0)); { uint256 amountIn = amounts[i]; if (input == antfarmToken) { totalFee = totalFee + ((amountIn * fee) / (1000 + fee)); } else if (output == antfarmToken) { totalFee = totalFee + ((amounts[i + 1] * fee) / (1000 - fee)); } else { uint256 feeToPay = antfarmPair.getFees( amount0Out, input == token0 ? amountIn : uint256(0), amount1Out, input == token0 ? uint256(0) : amountIn ); TransferHelper.safeTransferFrom( antfarmToken, msg.sender, address(antfarmPair), feeToPay ); totalFee = totalFee + feeToPay; } } address to = i < path.length - 2 ? pairFor(output, path[i + 2], fees[i + 1]) : _to; antfarmPair.swap(amount0Out, amount1Out, to); } } // **** SWAP (supporting fee-on-transfer tokens) **** function _swapSupportingFeeOnTransferTokens(swapParams memory sParams) internal virtual returns (uint256 totalFee) { for (uint256 i; i < sParams.path.length - 1; i++) { (address input, address output) = ( sParams.path[i], sParams.path[i + 1] ); uint16 fee = sParams.fees[i]; IAntfarmPair antfarmPair = IAntfarmPair( pairFor(input, output, fee) ); (address token0, ) = sortTokens(input, output); uint256 amountIn; uint256 amountOut; { (uint256 reserve0, uint256 reserve1, ) = antfarmPair .getReserves(); (uint256 reserveIn, uint256 reserveOut) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0); amountIn = IERC20(input).balanceOf(address(antfarmPair)) - reserveIn; if (input == antfarmToken) { amountOut = getAmountOut( (amountIn * 1000) / (1000 + fee), reserveIn, reserveOut ); } else if (output == antfarmToken) { amountOut = (getAmountOut(amountIn, reserveIn, reserveOut) * (1000 - fee)) / 1000; } else { amountOut = getAmountOut(amountIn, reserveIn, reserveOut); } } (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0)); if (input == antfarmToken) { totalFee = totalFee + ((amountIn * fee) / (1000 + fee)); } else if (output == antfarmToken) { totalFee = totalFee + ((amountIn * fee) / 1000); } else { uint256 feeToPay = antfarmPair.getFees( amount0Out, input == token0 ? amountIn : uint256(0), amount1Out, input == token0 ? uint256(0) : amountIn ); TransferHelper.safeTransferFrom( antfarmToken, msg.sender, address(antfarmPair), feeToPay ); totalFee = totalFee + feeToPay; } address to = i < sParams.path.length - 2 ? pairFor(output, sParams.path[i + 2], sParams.fees[i + 1]) : sParams.to; antfarmPair.swap(amount0Out, amount1Out, to); } } // **** LIBRARY FUNCTIONS ADDED INTO THE CONTRACT **** // returns sorted token addresses, used to handle return values from pairs sorted in this order function sortTokens(address tokenA, address tokenB) internal view returns (address token0, address token1) { if (tokenA == tokenB) revert IdenticalAddresses(); if (tokenA == antfarmToken || tokenB == antfarmToken) { (token0, token1) = tokenA == antfarmToken ? (antfarmToken, tokenB) : (antfarmToken, tokenA); if (token1 == address(0)) revert ZeroAddress(); } else { (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); if (token0 == address(0)) revert ZeroAddress(); } } /// @notice Calculates the CREATE2 address for a pair without making any external calls /// @param tokenA Token0 from the AntfarmPair /// @param tokenB Token1 from the AntfarmPair /// @param fee Associated fee to the AntfarmPair /// @return pair The CREATE2 address for the desired AntFarmPair function pairFor( address tokenA, address tokenB, uint16 fee ) public view returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256( abi.encodePacked( token0, token1, fee, antfarmToken ) ), token0 == antfarmToken ? hex"99c189a5ef3d337612cf0ce2bd055546e23b91fea9e9e54201b23f14d763f333" // AtfPair init code hash : hex"3b29ecd4cb06592a81cac4799fb24ef6a176fe95ecb50f304972882b150f3f3a" // Pair init code hash ) ) ) ) ); } // performs chained getAmountOut calculations on any number of pairs function getAmountsOut( uint256 amountIn, address[] memory path, uint16[] memory fees ) public view returns (uint256[] memory) { if (path.length < 2) revert InvalidPath(); uint256[] memory amounts = new uint256[](path.length); amounts[0] = amountIn; for (uint256 i; i < path.length - 1; i++) { (uint256 reserveIn, uint256 reserveOut) = getReserves( path[i], path[i + 1], fees[i] ); if (path[i] == antfarmToken) { amounts[i + 1] = getAmountOut( (amounts[i] * 1000) / (1000 + fees[i]), reserveIn, reserveOut ); } else if (path[i + 1] == antfarmToken) { amounts[i + 1] = (getAmountOut(amounts[i], reserveIn, reserveOut) * (1000 - fees[i])) / 1000; } else { amounts[i + 1] = getAmountOut( amounts[i], reserveIn, reserveOut ); } } return amounts; } // performs chained getAmountIn calculations on any number of pairs function getAmountsIn( uint256 amountOut, address[] memory path, uint16[] memory fees ) public view returns (uint256[] memory) { if (path.length < 2) revert InvalidPath(); uint256[] memory amounts = new uint256[](path.length); amounts[path.length - 1] = amountOut; for (uint256 i = path.length - 1; i > 0; i--) { (uint256 reserveIn, uint256 reserveOut) = getReserves( path[i - 1], path[i], fees[i - 1] ); if (path[i - 1] == antfarmToken) { amounts[i - 1] = (getAmountIn(amounts[i], reserveIn, reserveOut) * (1000 + fees[i - 1])) / 1000; } else if (path[i] == antfarmToken) { amounts[i - 1] = getAmountIn( (amounts[i] * 1000) / (1000 - fees[i - 1]), reserveIn, reserveOut ); } else { amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); } } return amounts; } // 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) { if (amountIn == 0) revert InsufficientInputAmount(); if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity(); uint256 numerator = amountIn * reserveOut; uint256 denominator = reserveIn + amountIn; return 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) { if (amountOut == 0) revert InsufficientOutputAmount(); if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity(); uint256 numerator = reserveIn * amountOut; uint256 denominator = reserveOut - amountOut; return (numerator / denominator) + 1; } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; import "../libraries/fixedpoint/FixedPoint.sol"; error InvalidToken(); /// @title Antfarm Oracle for AntfarmPair /// @notice Fixed window oracle that recomputes the average price for the entire period once every period contract AntfarmOracle { using FixedPoint for *; uint256 public constant PERIOD = 1 hours; address public token1; address public pair; uint256 public price1CumulativeLast; uint32 public blockTimestampLast; FixedPoint.uq112x112 public price1Average; bool public firstUpdateCall; constructor( address _token1, uint256 _price1CumulativeLast, uint32 _blockTimestampLast ) { token1 = _token1; pair = msg.sender; price1CumulativeLast = _price1CumulativeLast; // fetch the current accumulated price value (1 / 0) blockTimestampLast = _blockTimestampLast; firstUpdateCall = true; } /// @notice Average price update /// @param price1Cumulative Price cumulative for the associated AntfarmPair's token1 /// @param blockTimestamp Last block timestamp for the associated AntfarmPair /// @dev Only usable by the associated AntfarmPair function update(uint256 price1Cumulative, uint32 blockTimestamp) external { require(msg.sender == pair); unchecked { uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired // ensure that at least one full period has passed since the last update if (timeElapsed >= PERIOD || firstUpdateCall) { // overflow is desired, casting never truncates // cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed price1Average = FixedPoint.uq112x112( uint224( (price1Cumulative - price1CumulativeLast) / timeElapsed ) ); price1CumulativeLast = price1Cumulative; blockTimestampLast = blockTimestamp; if (firstUpdateCall) { firstUpdateCall = false; } } } } /// @notice Consult the average price for a given token /// @param token Price cumulative for the associated AntfarmPair's token /// @param amountIn The amount to get the value of /// @return amountOut Return the calculated amount (always return 0 before update has been called successfully for the first time) function consult(address token, uint256 amountIn) external view returns (uint256 amountOut) { if (token == token1) { amountOut = price1Average.mul(amountIn).decode144(); } else { revert InvalidToken(); } } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; import "./pair/IAntfarmPairState.sol"; import "./pair/IAntfarmPairEvents.sol"; import "./pair/IAntfarmPairActions.sol"; import "./pair/IAntfarmPairDerivedState.sol"; interface IAntfarmBase is IAntfarmPairState, IAntfarmPairEvents, IAntfarmPairActions, IAntfarmPairDerivedState {}
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmFactory { event PairCreated( address indexed token0, address indexed token1, address pair, uint16 fee, uint256 allPairsLength ); function possibleFees(uint256) external view returns (uint16); function allPairs(uint256) external view returns (address); function antfarmToken() external view returns (address); function getPairs(uint256 startIndex, uint256 numOfPairs) external view returns (address[] memory, uint256); function getPair( address tokenA, address tokenB, uint16 fee ) external view returns (address pair); function feesForPair( address tokenA, address tokenB, uint256 ) external view returns (uint16); function getFeesForPair(address tokenA, address tokenB) external view returns (uint16[8] memory fees); function allPairsLength() external view returns (uint256); function createPair( address tokenA, address tokenB, uint16 fee ) external returns (address pair); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; import "./IAntfarmBase.sol"; interface IAntfarmPair is IAntfarmBase { /// @notice Initialize the pair /// @dev Can only be called by the factory function initialize( address, address, uint16, address ) external; /// @notice The Antfarm token address /// @return address Address function antfarmToken() external view returns (address); /// @notice The Oracle instance used to compute swap's fees /// @return AntfarmOracle Oracle instance function antfarmOracle() external view returns (address); /// @notice Calcul fee to pay /// @param amount0Out The token0 amount going out of the pool /// @param amount0In The token0 amount going in the pool /// @param amount1Out The token1 amount going out of the pool /// @param amount1In The token1 amount going in the pool /// @return feeToPay Calculated fee to be paid function getFees( uint256 amount0Out, uint256 amount0In, uint256 amount1Out, uint256 amount1In ) external view returns (uint256 feeToPay); /// @notice Check for the best Oracle to use to perform fee calculation for a swap /// @dev Returns address(0) if no better oracle is found. /// @param maxReserve Actual oracle reserve0 /// @return bestOracle Address from the best oracle found function scanOracles(uint112 maxReserve) external view returns (address bestOracle); /// @notice Update oracle for token /// @custom:usability Update the current Oracle with a more suitable one. Revert if the current Oracle is already the more suitable function updateOracle() external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmRouter { function factory() external view returns (address); function WETH() external view returns (address); function antfarmToken() external view returns (address); struct swapParams { address[] path; uint16[] fees; address to; } struct swapExactTokensForTokensParams { uint256 amountIn; uint256 amountOutMin; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapExactTokensForTokens( swapExactTokensForTokensParams calldata params ) external returns (uint256[] memory amounts); struct swapTokensForExactTokensParams { uint256 amountOut; uint256 amountInMax; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapTokensForExactTokens( swapTokensForExactTokensParams calldata params ) external returns (uint256[] memory amounts); struct swapExactETHForTokensParams { uint256 amountOutMin; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapExactETHForTokens(swapExactETHForTokensParams calldata params) external payable returns (uint256[] memory amounts); struct swapTokensForExactETHParams { uint256 amountOut; uint256 amountInMax; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapTokensForExactETH(swapTokensForExactETHParams calldata params) external returns (uint256[] memory amounts); struct swapExactTokensForETHParams { uint256 amountIn; uint256 amountOutMin; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapExactTokensForETH(swapExactTokensForETHParams calldata params) external returns (uint256[] memory amounts); struct swapETHForExactTokensParams { uint256 amountOut; uint256 maxFee; address[] path; uint16[] fees; address to; uint256 deadline; } function swapETHForExactTokens(swapETHForExactTokensParams calldata params) external payable returns (uint256[] memory amounts); function swapExactTokensForTokensSupportingFeeOnTransferTokens( swapExactTokensForTokensParams calldata params ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( swapExactETHForTokensParams calldata params ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( swapExactTokensForETHParams calldata params ) external; // fetches and sorts the reserves for a pair function getReserves( address tokenA, address tokenB, uint16 fee ) external view returns (uint256 reserveA, uint256 reserveB); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmToken { 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 account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function nonces(address owner) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function DOMAIN_SEPARATOR() external view returns (bytes32); function burn(uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmPairActions { /// @notice Mint liquidity for a specific position /// @dev Low-level function. Should be called from another contract which performs all necessary checks /// @param to The address to mint liquidity /// @param positionId The ID to store the position to allow multiple positions for a single address /// @return liquidity Minted liquidity function mint(address to, uint256 positionId) external returns (uint256 liquidity); /// @notice Burn liquidity from a specific position /// @dev Low-level function. Should be called from another contract which performs all necessary checks /// @param to The address to return the liquidity to /// @param positionId The ID of the position to burn liquidity from /// @param liquidity Liquidity amount to be burned /// @return amount0 The token0 amount received from the liquidity burn /// @return amount1 The token1 amount received from the liquidity burn function burn( address to, uint256 liquidity, uint256 positionId ) external returns (uint256 amount0, uint256 amount1); /// @notice Swap tokens /// @dev Low-level function. Should be called from another contract which performs all necessary checks /// @param amount0Out token0 amount to be swapped /// @param amount1Out token1 amount to be swapped /// @param to The address to send the swapped tokens function swap( uint256 amount0Out, uint256 amount1Out, address to ) external; /// @notice Force balances to match reserves /// @param to The address to send excessive tokens function skim(address to) external; /// @notice Force reserves to match balances function sync() external; /// @notice Claim dividends for a specific position /// @param to The address to receive claimed dividends /// @param positionId The ID of the position to claim /// @return claimedAmount The amount claimed function claimDividend(address to, uint256 positionId) external returns (uint256 claimedAmount); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmPairDerivedState { /// @notice Get position LP tokens /// @param operator Position owner /// @param positionId ID of the position /// @return uint128 LP tokens owned by the operator function getPositionLP(address operator, uint256 positionId) external view returns (uint128); /// @notice Get pair reserves /// @return reserve0 Reserve for token0 /// @return reserve1 Reserve for token1 /// @return blockTimestampLast Last block proceeded function getReserves() external view returns ( uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast ); /// @notice Get Dividend from a specific position /// @param operator The address used to get dividends /// @param positionId Specific position /// @return amount Dividends owned by the address function claimableDividends(address operator, uint256 positionId) external view returns (uint256 amount); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; interface IAntfarmPairEvents { /// @notice Emitted when a position's liquidity is removed /// @param sender The address that initiated the burn call /// @param amount0 The amount of token0 withdrawn /// @param amount1 The amount of token1 withdrawn /// @param to The address to send token0 & token1 event Burn( address indexed sender, uint256 amount0, uint256 amount1, address indexed to ); /// @notice Emitted when liquidity is minted for a given position /// @param sender The address that initiated the mint call /// @param amount0 Required token0 for the minted liquidity /// @param amount1 Required token1 for the minted liquidity event Mint(address indexed sender, uint256 amount0, uint256 amount1); /// @notice Emitted by the pool for any swaps between token0 and token1 /// @param sender The address that initiated the swap call /// @param amount0In Amount of token0 sent to the pair /// @param amount1In Amount of token1 sent to the pair /// @param amount0Out Amount of token0 going out of the pair /// @param amount1Out Amount of token1 going out of the pair /// @param to Address to transfer the swapped amount event Swap( address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to ); /// @notice Emitted by the pool for any call to Sync function /// @param reserve0 reserve0 updated from the pair /// @param reserve1 reserve1 updated from the pair event Sync(uint112 reserve0, uint112 reserve1); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; import "../IAntfarmToken.sol"; interface IAntfarmPairState { /// @notice The contract that deployed the AntfarmPair, which must adhere to the IAntfarmFactory interface /// @return address The contract address function factory() external view returns (address); /// @notice The first of the two tokens of the AntfarmPair, sorted by address /// @return address The token contract address function token0() external view returns (address); /// @notice The second of the two tokens of the AntfarmPair, sorted by address /// @return address The token contract address function token1() external view returns (address); /// @notice Fee associated to the AntfarmPair instance /// @return uint16 Fee function fee() external view returns (uint16); /// @notice The LP tokens total circulating supply /// @return uint Total LP tokens function totalSupply() external view returns (uint256); /// @notice The AntFarmPair AntFarm's tokens cumulated fees /// @return uint Total Antfarm tokens function antfarmTokenReserve() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; // computes square roots using the babylonian method // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method library Babylonian { // credit for this implementation goes to // https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687 function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; // this block is equivalent to r = uint256(1) << (BitMath.mostSignificantBit(x) / 2); // however that code costs significantly more gas uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return (r < r1 ? r : r1); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; library BitMath { // returns the 0 indexed position of the most significant bit of the input x // s.t. x >= 2**msb and x < 2**(msb+1) function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0, "BitMath::mostSignificantBit: zero"); if (x >= 0x100000000000000000000000000000000) { x >>= 128; r += 128; } if (x >= 0x10000000000000000) { x >>= 64; r += 64; } if (x >= 0x100000000) { x >>= 32; r += 32; } if (x >= 0x10000) { x >>= 16; r += 16; } if (x >= 0x100) { x >>= 8; r += 8; } if (x >= 0x10) { x >>= 4; r += 4; } if (x >= 0x4) { x >>= 2; r += 2; } if (x >= 0x2) r += 1; } // returns the 0 indexed position of the least significant bit of the input x // s.t. (x & 2**lsb) != 0 and (x & (2**(lsb) - 1)) == 0) // i.e. the bit at the index is set and the mask of all lower bits is 0 function leastSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0, "BitMath::leastSignificantBit: zero"); r = 255; if (x & type(uint128).max > 0) { r -= 128; } else { x >>= 128; } if (x & type(uint64).max > 0) { r -= 64; } else { x >>= 64; } if (x & type(uint32).max > 0) { r -= 32; } else { x >>= 32; } if (x & type(uint16).max > 0) { r -= 16; } else { x >>= 16; } if (x & type(uint16).max > 0) { r -= 8; } else { x >>= 8; } if (x & 0xf > 0) { r -= 4; } else { x >>= 4; } if (x & 0x3 > 0) { r -= 2; } else { x >>= 2; } if (x & 0x1 > 0) r -= 1; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.0; import "./FullMath.sol"; import "./Babylonian.sol"; import "./BitMath.sol"; // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) library FixedPoint { // range: [0, 2**112 - 1] // resolution: 1 / 2**112 struct uq112x112 { uint224 _x; } // range: [0, 2**144 - 1] // resolution: 1 / 2**112 struct uq144x112 { uint256 _x; } uint8 public constant RESOLUTION = 112; uint256 public constant Q112 = 0x10000000000000000000000000000; // 2**112 uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; // 2**224 uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits) // encode a uint112 as a UQ112x112 function encode(uint112 x) internal pure returns (uq112x112 memory) { return uq112x112(uint224(x) << RESOLUTION); } // encodes a uint144 as a UQ144x112 function encode144(uint144 x) internal pure returns (uq144x112 memory) { return uq144x112(uint256(x) << RESOLUTION); } // decode a UQ112x112 into a uint112 by truncating after the radix point function decode(uq112x112 memory self) internal pure returns (uint112) { return uint112(self._x >> RESOLUTION); } // decode a UQ144x112 into a uint144 by truncating after the radix point function decode144(uq144x112 memory self) internal pure returns (uint144) { return uint144(self._x >> RESOLUTION); } // multiply a UQ112x112 by a uint, returning a UQ144x112 // reverts on overflow function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) { uint256 z = 0; require(y == 0 || (z = self._x * y) / y == self._x, "FixedPoint::mul: overflow"); return uq144x112(z); } // multiply a UQ112x112 by an int and decode, returning an int // reverts on overflow function muli(uq112x112 memory self, int256 y) internal pure returns (int256) { uint256 z = FullMath.mulDiv(self._x, uint256(y < 0 ? -y : y), Q112); require(z < 2**255, "FixedPoint::muli: overflow"); return y < 0 ? -int256(z) : int256(z); } // multiply a UQ112x112 by a UQ112x112, returning a UQ112x112 // lossy function muluq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { if (self._x == 0 || other._x == 0) { return uq112x112(0); } uint112 upper_self = uint112(self._x >> RESOLUTION); // * 2^0 uint112 lower_self = uint112(self._x & LOWER_MASK); // * 2^-112 uint112 upper_other = uint112(other._x >> RESOLUTION); // * 2^0 uint112 lower_other = uint112(other._x & LOWER_MASK); // * 2^-112 // partial products uint224 upper = uint224(upper_self) * upper_other; // * 2^0 uint224 lower = uint224(lower_self) * lower_other; // * 2^-224 uint224 uppers_lowero = uint224(upper_self) * lower_other; // * 2^-112 uint224 uppero_lowers = uint224(upper_other) * lower_self; // * 2^-112 // so the bit shift does not overflow require(upper <= type(uint112).max, "FixedPoint::muluq: upper overflow"); // this cannot exceed 256 bits, all values are 224 bits uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION); // so the cast does not overflow require(sum <= type(uint224).max, "FixedPoint::muluq: sum overflow"); return uq112x112(uint224(sum)); } // divide a UQ112x112 by a UQ112x112, returning a UQ112x112 function divuq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { require(other._x > 0, "FixedPoint::divuq: division by zero"); if (self._x == other._x) { return uq112x112(uint224(Q112)); } if (self._x <= type(uint144).max) { uint256 value = (uint256(self._x) << RESOLUTION) / other._x; require(value <= type(uint224).max, "FixedPoint::divuq: overflow"); return uq112x112(uint224(value)); } uint256 result = FullMath.mulDiv(Q112, self._x, other._x); require(result <= type(uint224).max, "FixedPoint::divuq: overflow"); return uq112x112(uint224(result)); } // returns a UQ112x112 which represents the ratio of the numerator to the denominator // can be lossy function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) { require(denominator > 0, "FixedPoint::fraction: division by zero"); if (numerator == 0) return FixedPoint.uq112x112(0); if (numerator <= type(uint144).max) { uint256 result = (numerator << RESOLUTION) / denominator; require(result <= type(uint224).max, "FixedPoint::fraction: overflow"); return uq112x112(uint224(result)); } else { uint256 result = FullMath.mulDiv(numerator, Q112, denominator); require(result <= type(uint224).max, "FixedPoint::fraction: overflow"); return uq112x112(uint224(result)); } } // take the reciprocal of a UQ112x112 // reverts on overflow // lossy function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) { require(self._x != 0, "FixedPoint::reciprocal: reciprocal of zero"); require(self._x != 1, "FixedPoint::reciprocal: overflow"); return uq112x112(uint224(Q224 / self._x)); } // square root of a UQ112x112 // lossy between 0/1 and 40 bits function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { if (self._x <= type(uint144).max) { return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112))); } uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x); safeShiftBits -= safeShiftBits % 2; return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2))); } }
// SPDX-License-Identifier: CC-BY-4.0 pragma solidity >=0.8.0; // taken from https://medium.com/coinmonks/math-in-solidity-part-3-percents-and-proportions-4db014e080b1 // license is CC-BY-4.0 library FullMath { function fullMul(uint256 x, uint256 y) internal pure returns (uint256 l, uint256 h) { uint256 mm = mulmod(x, y, type(uint256).max); l = x * y; h = mm - l; if (mm < l) h -= 1; } function fullDiv( uint256 l, uint256 h, uint256 d ) private pure returns (uint256) { uint256 pow2 = d & (type(uint256).max - d + 1) & d; d /= pow2; l /= pow2; l += h * (((type(uint256).max - pow2 + 1) & pow2) / pow2 + 1); uint256 r = 1; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; return l * r; } function mulDiv( uint256 x, uint256 y, uint256 d ) internal pure returns (uint256) { (uint256 l, uint256 h) = fullMul(x, y); uint256 mm = mulmod(x, y, d); if (mm > l) h -= 1; l -= mm; if (h == 0) return l / d; require(h < d, "FullMath: FULLDIV_OVERFLOW"); return fullDiv(l, h, d); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity =0.8.10; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes("approve(address,uint256)"))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0x095ea7b3, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed" ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes("transfer(address,uint256)"))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0xa9059cbb, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed" ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes("transferFrom(address,address,uint256)"))); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(0x23b872dd, from, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::transferFrom: transferFrom failed" ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require( success, "TransferHelper::safeTransferETH: ETH transfer failed" ); } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.10; error Expired(); error InsufficientOutputAmount(); error InsufficientInputAmount(); error InsufficientLiquidity(); error InsufficientMaxFee(); error ExcessiveInputAmount(); error InvalidPath(); error IdenticalAddresses(); error ZeroAddress();
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_antfarmToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ExcessiveInputAmount","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"IdenticalAddresses","type":"error"},{"inputs":[],"name":"InsufficientInputAmount","type":"error"},{"inputs":[],"name":"InsufficientLiquidity","type":"error"},{"inputs":[],"name":"InsufficientMaxFee","type":"error"},{"inputs":[],"name":"InsufficientOutputAmount","type":"error"},{"inputs":[],"name":"InvalidPath","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"antfarmToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint16","name":"fee","type":"uint16"}],"name":"getReserves","outputs":[{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint16","name":"fee","type":"uint16"}],"name":"pairFor","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapETHForExactTokensParams","name":"params","type":"tuple"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactETHForTokensParams","name":"params","type":"tuple"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactETHForTokensParams","name":"params","type":"tuple"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactTokensForETHParams","name":"params","type":"tuple"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactTokensForETHParams","name":"params","type":"tuple"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactTokensForTokensParams","name":"params","type":"tuple"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapExactTokensForTokensParams","name":"params","type":"tuple"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapTokensForExactETHParams","name":"params","type":"tuple"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint16[]","name":"fees","type":"uint16[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IAntfarmRouter.swapTokensForExactTokensParams","name":"params","type":"tuple"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040523480156200001157600080fd5b506040516200417c3803806200417c833981016040819052620000349162000162565b6001600160a01b038316620000905760405162461bcd60e51b815260206004820152601460248201527f4e554c4c5f464143544f52595f4144445245535300000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216620000dc5760405162461bcd60e51b81526020600482015260116024820152704e554c4c5f574554485f4144445245535360781b604482015260640162000087565b6001600160a01b038116620001275760405162461bcd60e51b815260206004820152601060248201526f4e554c4c5f4154465f4144445245535360801b604482015260640162000087565b6001600160a01b0392831660805290821660a0521660c052620001ac565b80516001600160a01b03811681146200015d57600080fd5b919050565b6000806000606084860312156200017857600080fd5b620001838462000145565b9250620001936020850162000145565b9150620001a36040850162000145565b90509250925092565b60805160a05160c051613e88620002f4600039600081816102ca015281816108f001528181610cdf01528181610fd10152818161129a0152818161138c0152818161196d01528181611a5b01528181611cb201528181611d1b015281816124ac01528181612b4401528181612ba401528181612c4c01528181612cc101528181612dda015281816131c00152818161323501528181613382015281816136d7015281816137120152818161374d0152818161378601526137ad01526000818161010701528181610296015281816103c301528181610444015281816104b801528181610c4101528181610eb8015281816114ea015281816115f40152818161168201528181611e2a01528181611f4301528181611fd10152818161257b0152818161269b0152818161282001526128e90152600081816102fe0152611ce00152613e886000f3fe6080604052600436106100f75760003560e01c8063a502d3a01161008a578063cd0ba5df11610059578063cd0ba5df14610320578063d2a4949a14610333578063e80d2b3414610353578063ef1c88fb1461037357600080fd5b8063a502d3a01461024c578063ad5c464814610284578063c12a00a8146102b8578063c45a0155146102ec57600080fd5b80635ec70f5d116100c65780635ec70f5d146101c4578063636f5e0e146101e45780636451737d146101f7578063951eb42d1461021757600080fd5b80630438c45e1461013b57806305f9b6271461014e578063164d01be1461018457806359c90959146101a457600080fd5b3661013657336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461013457610134613855565b005b600080fd5b61013461014936600461387d565b610393565b34801561015a57600080fd5b5061016e6101693660046138cc565b6108bc565b60405161017b9190613901565b60405180910390f35b34801561019057600080fd5b5061016e61019f3660046138cc565b610c0f565b3480156101b057600080fd5b5061016e6101bf3660046138cc565b610f9d565b3480156101d057600080fd5b5061016e6101df366004613a50565b61116a565b61016e6101f236600461387d565b6114b8565b34801561020357600080fd5b5061016e610212366004613a50565b61186a565b34801561022357600080fd5b50610237610232366004613b1b565b611b76565b6040805192835260208301919091520161017b565b34801561025857600080fd5b5061026c610267366004613b1b565b611c4e565b6040516001600160a01b03909116815260200161017b565b34801561029057600080fd5b5061026c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c457600080fd5b5061026c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102f857600080fd5b5061026c7f000000000000000000000000000000000000000000000000000000000000000081565b61016e61032e36600461387d565b611df8565b34801561033f57600080fd5b5061013461034e3660046138cc565b6120e1565b34801561035f57600080fd5b5061016e61036e3660046138cc565b612478565b34801561037f57600080fd5b5061013461038e3660046138cc565b61266b565b8060a00135428110156103b957604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166103f06040840184613b5e565b600081811061040157610401613ba8565b90506020020160208101906104169190613bbe565b6001600160a01b03161461043d576040516320db826760e01b815260040160405180910390fd5b60003490507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561049d57600080fd5b505af11580156104b1573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6105848580604001906104f89190613b5e565b600081811061050957610509613ba8565b905060200201602081019061051e9190613bbe565b61052b6040880188613b5e565b600181811061053c5761053c613ba8565b90506020020160208101906105519190613bbe565b61055e6060890189613b5e565b600081811061056f5761056f613ba8565b90506020020160208101906102679190613be0565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156105d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f59190613bfb565b61060157610601613855565b60006106106040850185613b5e565b600161061f6040880188613b5e565b61062a929150613c33565b81811061063957610639613ba8565b905060200201602081019061064e9190613bbe565b6001600160a01b03166370a0823161066c60a0870160808801613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d49190613c4a565b9050600060405180606001604052808680604001906106f39190613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020016107376060880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161077e60a0880160808901613bbe565b6001600160a01b031690529050602085013561079982612968565b11156107b857604051634b41cb4560e01b815260040160405180910390fd5b8435826107c86040880188613b5e565b60016107d760408b018b613b5e565b6107e2929150613c33565b8181106107f1576107f1613ba8565b90506020020160208101906108069190613bbe565b6001600160a01b03166370a0823161082460a08a0160808b01613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088c9190613c4a565b6108969190613c33565b10156108b5576040516342301c2360e01b815260040160405180910390fd5b5050505050565b60608160c00135428110156108e457604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001661091d6060860186613b5e565b600081811061092e5761092e613ba8565b90506020020160208101906109439190613bbe565b6001600160a01b03161461095b5783602001356109b9565b6103e861096b6080860186613b5e565b600081811061097c5761097c613ba8565b90506020020160208101906109919190613be0565b61099d906103e8613c63565b6109af9061ffff166020870135613c89565b6109b99190613ca8565b9050610a4384356109cd6060870187613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610a0c925050506080880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061116a92505050565b92508083600081518110610a5957610a59613ba8565b60200260200101511115610a805760405163e1b0da4f60e01b815260040160405180910390fd5b610b4d610a906060860186613b5e565b6000818110610aa157610aa1613ba8565b9050602002016020810190610ab69190613bbe565b33610b2d610ac76060890189613b5e565b6000818110610ad857610ad8613ba8565b9050602002016020810190610aed9190613bbe565b610afa60608a018a613b5e565b6001818110610b0b57610b0b613ba8565b9050602002016020810190610b209190613bbe565b61055e60808b018b613b5e565b86600081518110610b4057610b40613ba8565b6020026020010151612f15565b6040840135610be984610b636060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610ba2925050506080890189613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610be49250505060c08a0160a08b01613bbe565b613092565b1115610c0857604051634b41cb4560e01b815260040160405180910390fd5b5050919050565b60608160c0013542811015610c3757604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610c6e6060850185613b5e565b6001610c7d6060880188613b5e565b610c88929150613c33565b818110610c9757610c97613ba8565b9050602002016020810190610cac9190613bbe565b6001600160a01b031614610cd3576040516320db826760e01b815260040160405180910390fd5b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610d0c6060860186613b5e565b6000818110610d1d57610d1d613ba8565b9050602002016020810190610d329190613bbe565b6001600160a01b031614610d4a578360200135610da8565b6103e8610d5a6080860186613b5e565b6000818110610d6b57610d6b613ba8565b9050602002016020810190610d809190613be0565b610d8c906103e8613c63565b610d9e9061ffff166020870135613c89565b610da89190613ca8565b9050610dbc84356109cd6060870187613b5e565b92508083600081518110610dd257610dd2613ba8565b60200260200101511115610df95760405163e1b0da4f60e01b815260040160405180910390fd5b610e09610a906060860186613b5e565b6040840135610e9784610e1f6060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610e5e925050506080890189613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250613092915050565b1115610eb657604051634b41cb4560e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8460018651610ef49190613c33565b81518110610f0457610f04613ba8565b60200260200101516040518263ffffffff1660e01b8152600401610f2a91815260200190565b600060405180830381600087803b158015610f4457600080fd5b505af1158015610f58573d6000803e3d6000fd5b50610c089250610f7191505060c0860160a08701613bbe565b8460018651610f809190613c33565b81518110610f9057610f90613ba8565b6020026020010151613492565b60608160c0013542811015610fc557604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610ffe6060860186613b5e565b600081811061100f5761100f613ba8565b90506020020160208101906110249190613bbe565b6001600160a01b031614611039578335611094565b6103e86110496080860186613b5e565b600081811061105a5761105a613ba8565b905060200201602081019061106f9190613be0565b61107b906103e8613c63565b61108a9061ffff168635613c89565b6110949190613ca8565b905061111d816110a76060870187613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506110e6925050506080880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061186a92505050565b9250836020013583600185516111339190613c33565b8151811061114357611143613ba8565b60200260200101511015610a80576040516342301c2360e01b815260040160405180910390fd5b606060028351101561118f576040516320db826760e01b815260040160405180910390fd5b6000835167ffffffffffffffff8111156111ab576111ab613945565b6040519080825280602002602001820160405280156111d4578160200160208202803683370190505b5090508481600186516111e79190613c33565b815181106111f7576111f7613ba8565b6020026020010181815250506000600185516112139190613c33565b90505b80156114af5760008061128b8761122e600186613c33565b8151811061123e5761123e613ba8565b602002602001015188858151811061125857611258613ba8565b60200260200101518860018761126e9190613c33565b8151811061127e5761127e613ba8565b6020026020010151611b76565b90925090506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016876112c6600186613c33565b815181106112d6576112d6613ba8565b60200260200101516001600160a01b0316141561138a576103e8866112fc600186613c33565b8151811061130c5761130c613ba8565b60200260200101516103e86113219190613c63565b61ffff1661134986868151811061133a5761133a613ba8565b6020026020010151858561357a565b6113539190613c89565b61135d9190613ca8565b84611369600186613c33565b8151811061137957611379613ba8565b60200260200101818152505061149a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168784815181106113c6576113c6613ba8565b60200260200101516001600160a01b0316141561144d5761135d866113ec600186613c33565b815181106113fc576113fc613ba8565b60200260200101516103e86114119190613cca565b61ffff1685858151811061142757611427613ba8565b60200260200101516103e861143c9190613c89565b6114469190613ca8565b838361357a565b61147184848151811061146257611462613ba8565b6020026020010151838361357a565b8461147d600186613c33565b8151811061148d5761148d613ba8565b6020026020010181815250505b505080806114a790613ced565b915050611216565b50949350505050565b60608160a00135428110156114e057604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166115176040850185613b5e565b600081811061152857611528613ba8565b905060200201602081019061153d9190613bbe565b6001600160a01b031614611564576040516320db826760e01b815260040160405180910390fd5b6115b583356115766040860186613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610a0c925050506060870187613b5e565b915034826000815181106115cb576115cb613ba8565b602002602001015111156115f25760405163e1b0da4f60e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08360008151811061163457611634613ba8565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166757600080fd5b505af115801561167b573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6116c28580604001906104f89190613b5e565b846000815181106116d5576116d5613ba8565b60200260200101516040518363ffffffff1660e01b815260040161170e9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561172d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117519190613bfb565b61175d5761175d613855565b60208301356117f4836117736040870187613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506117b2925050506060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610be49250505060a0890160808a01613bbe565b111561181357604051634b41cb4560e01b815260040160405180910390fd5b8160008151811061182657611826613ba8565b602002602001015134111561186457611864338360008151811061184c5761184c613ba8565b60200260200101513461185f9190613c33565b613492565b50919050565b606060028351101561188f576040516320db826760e01b815260040160405180910390fd5b6000835167ffffffffffffffff8111156118ab576118ab613945565b6040519080825280602002602001820160405280156118d4578160200160208202803683370190505b50905084816000815181106118eb576118eb613ba8565b60200260200101818152505060005b600185516119089190613c33565b8110156114af5760008061196787848151811061192757611927613ba8565b60200260200101518885600161193d9190613d04565b8151811061194d5761194d613ba8565b602002602001015188868151811061127e5761127e613ba8565b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168784815181106119a7576119a7613ba8565b60200260200101516001600160a01b03161415611a5157611a248684815181106119d3576119d3613ba8565b60200260200101516103e86119e89190613c63565b61ffff168585815181106119fe576119fe613ba8565b60200260200101516103e8611a139190613c89565b611a1d9190613ca8565b83836135fe565b84611a30856001613d04565b81518110611a4057611a40613ba8565b602002602001018181525050611b61565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001687611a87856001613d04565b81518110611a9757611a97613ba8565b60200260200101516001600160a01b03161415611b14576103e8868481518110611ac357611ac3613ba8565b60200260200101516103e8611ad89190613cca565b61ffff16611b00868681518110611af157611af1613ba8565b602002602001015185856135fe565b611b0a9190613c89565b611a249190613ca8565b611b38848481518110611b2957611b29613ba8565b602002602001015183836135fe565b84611b44856001613d04565b81518110611b5457611b54613ba8565b6020026020010181815250505b50508080611b6e90613d1c565b9150506118fa565b6000806000611b858686613686565b509050600080611b96888888611c4e565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf79190613d55565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150826001600160a01b0316886001600160a01b031614611c3c578082611c3f565b81815b90999098509650505050505050565b6000806000611c5d8686613686565b6040516bffffffffffffffffffffffff19606084811b8216602084015283811b821660348401527fffff00000000000000000000000000000000000000000000000000000000000060f08a901b1660488401527f0000000000000000000000000000000000000000000000000000000000000000901b16604a82015291935091507f000000000000000000000000000000000000000000000000000000000000000090605e01604051602081830303815290604052805190602001207f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614611d8d576040518060400160405280602081526020017f3b29ecd4cb06592a81cac4799fb24ef6a176fe95ecb50f304972882b150f3f3a815250611dc4565b6040518060400160405280602081526020017f99c189a5ef3d337612cf0ce2bd055546e23b91fea9e9e54201b23f14d763f3338152505b604051602001611dd693929190613dd1565b60408051601f1981840301815291905280516020909101209695505050505050565b60608160a0013542811015611e2057604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016611e576040850185613b5e565b6000818110611e6857611e68613ba8565b9050602002016020810190611e7d9190613bbe565b6001600160a01b031614611ea4576040516320db826760e01b815260040160405180910390fd5b611ef434611eb56040860186613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506110e6925050506060870187613b5e565b915082600001358260018451611f0a9190613c33565b81518110611f1a57611f1a613ba8565b60200260200101511015611f41576040516342301c2360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db083600081518110611f8357611f83613ba8565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015611fb657600080fd5b505af1158015611fca573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6120118580604001906104f89190613b5e565b8460008151811061202457612024613ba8565b60200260200101516040518363ffffffff1660e01b815260040161205d9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561207c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a09190613bfb565b6120ac576120ac613855565b60208301356120c2836117736040870187613b5e565b111561186457604051634b41cb4560e01b815260040160405180910390fd5b8060c001354281101561210757604051630407b05b60e31b815260040160405180910390fd5b6121bb6121176060840184613b5e565b600081811061212857612128613ba8565b905060200201602081019061213d9190613bbe565b336121b461214e6060870187613b5e565b600081811061215f5761215f613ba8565b90506020020160208101906121749190613bbe565b6121816060880188613b5e565b600181811061219257612192613ba8565b90506020020160208101906121a79190613bbe565b61055e6080890189613b5e565b8535612f15565b60006121ca6060840184613b5e565b60016121d96060870187613b5e565b6121e4929150613c33565b8181106121f3576121f3613ba8565b90506020020160208101906122089190613bbe565b6001600160a01b03166370a0823161222660c0860160a08701613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561226a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228e9190613c4a565b9050600060405180606001604052808580606001906122ad9190613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020016122f16080870187613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161233860c0870160a08801613bbe565b6001600160a01b031690529050604084013561235382612968565b111561237257604051634b41cb4560e01b815260040160405180910390fd5b6020840135826123856060870187613b5e565b600161239460608a018a613b5e565b61239f929150613c33565b8181106123ae576123ae613ba8565b90506020020160208101906123c39190613bbe565b6001600160a01b03166370a082316123e160c0890160a08a01613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124499190613c4a565b6124539190613c33565b1015612472576040516342301c2360e01b815260040160405180910390fd5b50505050565b60608160c00135428110156124a057604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166124d96060860186613b5e565b60008181106124ea576124ea613ba8565b90506020020160208101906124ff9190613bbe565b6001600160a01b03161461251457833561256f565b6103e86125246080860186613b5e565b600081811061253557612535613ba8565b905060200201602081019061254a9190613be0565b612556906103e8613c63565b6125659061ffff168635613c89565b61256f9190613ca8565b90506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166125a86060860186613b5e565b60016125b76060890189613b5e565b6125c2929150613c33565b8181106125d1576125d1613ba8565b90506020020160208101906125e69190613bbe565b6001600160a01b03161461260d576040516320db826760e01b815260040160405180910390fd5b61261e816110a76060870187613b5e565b9250836020013583600185516126349190613c33565b8151811061264457612644613ba8565b60200260200101511015610df9576040516342301c2360e01b815260040160405180910390fd5b8060c001354281101561269157604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166126c86060840184613b5e565b60016126d76060870187613b5e565b6126e2929150613c33565b8181106126f1576126f1613ba8565b90506020020160208101906127069190613bbe565b6001600160a01b03161461272d576040516320db826760e01b815260040160405180910390fd5b61273d6121176060840184613b5e565b6000604051806060016040528084806060019061275a9190613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161279e6080860186613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525030602090910152905060408301356127e982612968565b111561280857604051634b41cb4560e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561286f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128939190613c4a565b905083602001358110156128ba576040516342301c2360e01b815260040160405180910390fd5b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561293557600080fd5b505af1158015612949573d6000803e3d6000fd5b50612472925061296291505060c0860160a08701613bbe565b82613492565b6000805b82515161297b90600190613c33565b811015611864576000808460000151838151811061299b5761299b613ba8565b602002602001015185600001518460016129b59190613d04565b815181106129c5576129c5613ba8565b6020026020010151915091506000856020015184815181106129e9576129e9613ba8565b602002602001015190506000612a00848484611c4e565b90506000612a0e8585613686565b509050600080600080856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a799190613d55565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600080866001600160a01b03168b6001600160a01b031614612ac1578284612ac4565b83835b6040516370a0823160e01b81526001600160a01b038b8116600483015292945090925083918d16906370a0823190602401602060405180830381865afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190613c4a565b612b409190613c33565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168b6001600160a01b03161415612ba257612b9b612b8b8a6103e8613c63565b61ffff16611a13886103e8613c89565b9450612c1a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b03161415612c0c576103e8612be98a82613cca565b61ffff16612bf88885856135fe565b612c029190613c89565b612b9b9190613ca8565b612c178683836135fe565b94505b50505050600080846001600160a01b0316896001600160a01b031614612c4257826000612c46565b6000835b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161415612cbf57612c90876103e8613c63565b61ffff168761ffff1685612ca49190613c89565b612cae9190613ca8565b612cb8908c613d04565b9a50612e0f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b03161415612d0a576103e8612ca461ffff891686613c89565b6000866001600160a01b0316632f72563884886001600160a01b03168d6001600160a01b031614612d3c576000612d3e565b875b858a6001600160a01b03168f6001600160a01b031614612d5e5789612d61565b60005b6040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401602060405180830381865afa158015612daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd39190613c4a565b9050612e017f0000000000000000000000000000000000000000000000000000000000000000338984612f15565b612e0b818d613d04565b9b50505b8b5151600090612e2190600290613c33565b8b10612e31578c60400151612e8b565b8c51612e8b908a90612e448e6002613d04565b81518110612e5457612e54613ba8565b60200260200101518f602001518e6001612e6e9190613d04565b81518110612e7e57612e7e613ba8565b6020026020010151611c4e565b6040516336cd320560e11b815260048101859052602481018490526001600160a01b03808316604483015291925090881690636d9a640a90606401600060405180830381600087803b158015612ee057600080fd5b505af1158015612ef4573d6000803e3d6000fd5b50505050505050505050505050508080612f0d90613d1c565b91505061296c565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612fa79190613e36565b6000604051808303816000865af19150503d8060008114612fe4576040519150601f19603f3d011682016040523d82523d6000602084013e612fe9565b606091505b50915091508180156130135750805115806130135750808060200190518101906130139190613bfb565b61308a5760405162461bcd60e51b815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c656400000000000000000000000000000060648201526084015b60405180910390fd5b505050505050565b6000805b600185516130a49190613c33565b8110156114af576000808683815181106130c0576130c0613ba8565b6020026020010151878460016130d69190613d04565b815181106130e6576130e6613ba8565b602002602001015191509150600086848151811061310657613106613ba8565b60200260200101519050600061311d848484611c4e565b9050600061312b8585613686565b509050600080826001600160a01b0316876001600160a01b031614613175578c613156896001613d04565b8151811061316657613166613ba8565b6020026020010151600061319c565b60008d6131838a6001613d04565b8151811061319357613193613ba8565b60200260200101515b9150915060008d89815181106131b4576131b4613ba8565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b0316141561323357613204866103e8613c63565b61ffff168661ffff16826132189190613c89565b6132229190613ca8565b61322c908b613d04565b99506133b7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614156132b257613279866103e8613cca565b61ffff168661ffff168f8b60016132909190613d04565b815181106132a0576132a0613ba8565b60200260200101516132189190613c89565b6000856001600160a01b0316632f72563885876001600160a01b03168c6001600160a01b0316146132e45760006132e6565b845b86896001600160a01b03168e6001600160a01b0316146133065786613309565b60005b6040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401602060405180830381865afa158015613357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337b9190613c4a565b90506133a97f0000000000000000000000000000000000000000000000000000000000000000338884612f15565b6133b3818c613d04565b9a50505b50600060028d516133c89190613c33565b89106133d4578a61340a565b61340a878e6133e48c6002613d04565b815181106133f4576133f4613ba8565b60200260200101518e8c6001612e6e9190613d04565b6040516336cd320560e11b815260048101859052602481018490526001600160a01b03808316604483015291925090861690636d9a640a90606401600060405180830381600087803b15801561345f57600080fd5b505af1158015613473573d6000803e3d6000fd5b505050505050505050505050808061348a90613d1c565b915050613096565b604080516000808252602082019092526001600160a01b0384169083906040516134bc9190613e36565b60006040518083038185875af1925050503d80600081146134f9576040519150601f19603f3d011682016040523d82523d6000602084013e6134fe565b606091505b50509050806135755760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401613081565b505050565b60008361359a576040516342301c2360e01b815260040160405180910390fd5b8215806135a5575081155b156135c35760405163bb55fd2760e01b815260040160405180910390fd5b60006135cf8585613c89565b905060006135dd8685613c33565b90506135e98183613ca8565b6135f4906001613d04565b9695505050505050565b600083613637576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821580613642575081155b156136605760405163bb55fd2760e01b815260040160405180910390fd5b600061366c8386613c89565b9050600061367a8686613d04565b90506135f48183613ca8565b600080826001600160a01b0316846001600160a01b031614156136d5576040517fbd969eb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316148061374657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b156137ff577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146137ab577f0000000000000000000000000000000000000000000000000000000000000000846137ce565b7f0000000000000000000000000000000000000000000000000000000000000000835b90925090506001600160a01b0381166137fa5760405163d92e233d60e01b815260040160405180910390fd5b61384e565b826001600160a01b0316846001600160a01b03161061381f578284613822565b83835b90925090506001600160a01b03821661384e5760405163d92e233d60e01b815260040160405180910390fd5b9250929050565b634e487b7160e01b600052600160045260246000fd5b600060c0828403121561186457600080fd5b60006020828403121561388f57600080fd5b813567ffffffffffffffff8111156138a657600080fd5b6138b28482850161386b565b949350505050565b600060e0828403121561186457600080fd5b6000602082840312156138de57600080fd5b813567ffffffffffffffff8111156138f557600080fd5b6138b2848285016138ba565b6020808252825182820181905260009190848201906040850190845b818110156139395783518352928401929184019160010161391d565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561398457613984613945565b604052919050565b600067ffffffffffffffff8211156139a6576139a6613945565b5060051b60200190565b80356001600160a01b03811681146139c757600080fd5b919050565b803561ffff811681146139c757600080fd5b600082601f8301126139ef57600080fd5b81356020613a046139ff8361398c565b61395b565b82815260059290921b84018101918181019086841115613a2357600080fd5b8286015b84811015613a4557613a38816139cc565b8352918301918301613a27565b509695505050505050565b600080600060608486031215613a6557600080fd5b8335925060208085013567ffffffffffffffff80821115613a8557600080fd5b818701915087601f830112613a9957600080fd5b8135613aa76139ff8261398c565b81815260059190911b8301840190848101908a831115613ac657600080fd5b938501935b82851015613aeb57613adc856139b0565b82529385019390850190613acb565b965050506040870135925080831115613b0357600080fd5b5050613b11868287016139de565b9150509250925092565b600080600060608486031215613b3057600080fd5b613b39846139b0565b9250613b47602085016139b0565b9150613b55604085016139cc565b90509250925092565b6000808335601e19843603018112613b7557600080fd5b83018035915067ffffffffffffffff821115613b9057600080fd5b6020019150600581901b360382131561384e57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215613bd057600080fd5b613bd9826139b0565b9392505050565b600060208284031215613bf257600080fd5b613bd9826139cc565b600060208284031215613c0d57600080fd5b81518015158114613bd957600080fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613c4557613c45613c1d565b500390565b600060208284031215613c5c57600080fd5b5051919050565b600061ffff808316818516808303821115613c8057613c80613c1d565b01949350505050565b6000816000190483118215151615613ca357613ca3613c1d565b500290565b600082613cc557634e487b7160e01b600052601260045260246000fd5b500490565b600061ffff83811690831681811015613ce557613ce5613c1d565b039392505050565b600081613cfc57613cfc613c1d565b506000190190565b60008219821115613d1757613d17613c1d565b500190565b6000600019821415613d3057613d30613c1d565b5060010190565b80516dffffffffffffffffffffffffffff811681146139c757600080fd5b600080600060608486031215613d6a57600080fd5b613d7384613d37565b9250613d8160208501613d37565b9150604084015163ffffffff81168114613d9a57600080fd5b809150509250925092565b60005b83811015613dc0578181015183820152602001613da8565b838111156124725750506000910152565b7fff0000000000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff198460601b16600182015282601582015260008251613e27816035850160208701613da5565b91909101603501949350505050565b60008251613e48818460208701613da5565b919091019291505056fea2646970667358221220035e8a06ff2fb49525cf9f2c1541d7436c7f4a2a69289412e1072cf4ddea72c364736f6c634300080a00330000000000000000000000008af94528fbe3c4c148523e7aad48bcebcc0a71d70000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e900000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c
Deployed Bytecode
0x6080604052600436106100f75760003560e01c8063a502d3a01161008a578063cd0ba5df11610059578063cd0ba5df14610320578063d2a4949a14610333578063e80d2b3414610353578063ef1c88fb1461037357600080fd5b8063a502d3a01461024c578063ad5c464814610284578063c12a00a8146102b8578063c45a0155146102ec57600080fd5b80635ec70f5d116100c65780635ec70f5d146101c4578063636f5e0e146101e45780636451737d146101f7578063951eb42d1461021757600080fd5b80630438c45e1461013b57806305f9b6271461014e578063164d01be1461018457806359c90959146101a457600080fd5b3661013657336001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9161461013457610134613855565b005b600080fd5b61013461014936600461387d565b610393565b34801561015a57600080fd5b5061016e6101693660046138cc565b6108bc565b60405161017b9190613901565b60405180910390f35b34801561019057600080fd5b5061016e61019f3660046138cc565b610c0f565b3480156101b057600080fd5b5061016e6101bf3660046138cc565b610f9d565b3480156101d057600080fd5b5061016e6101df366004613a50565b61116a565b61016e6101f236600461387d565b6114b8565b34801561020357600080fd5b5061016e610212366004613a50565b61186a565b34801561022357600080fd5b50610237610232366004613b1b565b611b76565b6040805192835260208301919091520161017b565b34801561025857600080fd5b5061026c610267366004613b1b565b611c4e565b6040516001600160a01b03909116815260200161017b565b34801561029057600080fd5b5061026c7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e981565b3480156102c457600080fd5b5061026c7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c81565b3480156102f857600080fd5b5061026c7f0000000000000000000000008af94528fbe3c4c148523e7aad48bcebcc0a71d781565b61016e61032e36600461387d565b611df8565b34801561033f57600080fd5b5061013461034e3660046138cc565b6120e1565b34801561035f57600080fd5b5061016e61036e3660046138cc565b612478565b34801561037f57600080fd5b5061013461038e3660046138cc565b61266b565b8060a00135428110156103b957604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9166103f06040840184613b5e565b600081811061040157610401613ba8565b90506020020160208101906104169190613bbe565b6001600160a01b03161461043d576040516320db826760e01b815260040160405180910390fd5b60003490507f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561049d57600080fd5b505af11580156104b1573d6000803e3d6000fd5b50505050507f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663a9059cbb6105848580604001906104f89190613b5e565b600081811061050957610509613ba8565b905060200201602081019061051e9190613bbe565b61052b6040880188613b5e565b600181811061053c5761053c613ba8565b90506020020160208101906105519190613bbe565b61055e6060890189613b5e565b600081811061056f5761056f613ba8565b90506020020160208101906102679190613be0565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156105d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f59190613bfb565b61060157610601613855565b60006106106040850185613b5e565b600161061f6040880188613b5e565b61062a929150613c33565b81811061063957610639613ba8565b905060200201602081019061064e9190613bbe565b6001600160a01b03166370a0823161066c60a0870160808801613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d49190613c4a565b9050600060405180606001604052808680604001906106f39190613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020016107376060880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161077e60a0880160808901613bbe565b6001600160a01b031690529050602085013561079982612968565b11156107b857604051634b41cb4560e01b815260040160405180910390fd5b8435826107c86040880188613b5e565b60016107d760408b018b613b5e565b6107e2929150613c33565b8181106107f1576107f1613ba8565b90506020020160208101906108069190613bbe565b6001600160a01b03166370a0823161082460a08a0160808b01613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088c9190613c4a565b6108969190613c33565b10156108b5576040516342301c2360e01b815260040160405180910390fd5b5050505050565b60608160c00135428110156108e457604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c1661091d6060860186613b5e565b600081811061092e5761092e613ba8565b90506020020160208101906109439190613bbe565b6001600160a01b03161461095b5783602001356109b9565b6103e861096b6080860186613b5e565b600081811061097c5761097c613ba8565b90506020020160208101906109919190613be0565b61099d906103e8613c63565b6109af9061ffff166020870135613c89565b6109b99190613ca8565b9050610a4384356109cd6060870187613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610a0c925050506080880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061116a92505050565b92508083600081518110610a5957610a59613ba8565b60200260200101511115610a805760405163e1b0da4f60e01b815260040160405180910390fd5b610b4d610a906060860186613b5e565b6000818110610aa157610aa1613ba8565b9050602002016020810190610ab69190613bbe565b33610b2d610ac76060890189613b5e565b6000818110610ad857610ad8613ba8565b9050602002016020810190610aed9190613bbe565b610afa60608a018a613b5e565b6001818110610b0b57610b0b613ba8565b9050602002016020810190610b209190613bbe565b61055e60808b018b613b5e565b86600081518110610b4057610b40613ba8565b6020026020010151612f15565b6040840135610be984610b636060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610ba2925050506080890189613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610be49250505060c08a0160a08b01613bbe565b613092565b1115610c0857604051634b41cb4560e01b815260040160405180910390fd5b5050919050565b60608160c0013542811015610c3757604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e916610c6e6060850185613b5e565b6001610c7d6060880188613b5e565b610c88929150613c33565b818110610c9757610c97613ba8565b9050602002016020810190610cac9190613bbe565b6001600160a01b031614610cd3576040516320db826760e01b815260040160405180910390fd5b60006001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c16610d0c6060860186613b5e565b6000818110610d1d57610d1d613ba8565b9050602002016020810190610d329190613bbe565b6001600160a01b031614610d4a578360200135610da8565b6103e8610d5a6080860186613b5e565b6000818110610d6b57610d6b613ba8565b9050602002016020810190610d809190613be0565b610d8c906103e8613c63565b610d9e9061ffff166020870135613c89565b610da89190613ca8565b9050610dbc84356109cd6060870187613b5e565b92508083600081518110610dd257610dd2613ba8565b60200260200101511115610df95760405163e1b0da4f60e01b815260040160405180910390fd5b610e09610a906060860186613b5e565b6040840135610e9784610e1f6060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610e5e925050506080890189613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250613092915050565b1115610eb657604051634b41cb4560e01b815260040160405180910390fd5b7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b0316632e1a7d4d8460018651610ef49190613c33565b81518110610f0457610f04613ba8565b60200260200101516040518263ffffffff1660e01b8152600401610f2a91815260200190565b600060405180830381600087803b158015610f4457600080fd5b505af1158015610f58573d6000803e3d6000fd5b50610c089250610f7191505060c0860160a08701613bbe565b8460018651610f809190613c33565b81518110610f9057610f90613ba8565b6020026020010151613492565b60608160c0013542811015610fc557604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c16610ffe6060860186613b5e565b600081811061100f5761100f613ba8565b90506020020160208101906110249190613bbe565b6001600160a01b031614611039578335611094565b6103e86110496080860186613b5e565b600081811061105a5761105a613ba8565b905060200201602081019061106f9190613be0565b61107b906103e8613c63565b61108a9061ffff168635613c89565b6110949190613ca8565b905061111d816110a76060870187613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506110e6925050506080880188613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061186a92505050565b9250836020013583600185516111339190613c33565b8151811061114357611143613ba8565b60200260200101511015610a80576040516342301c2360e01b815260040160405180910390fd5b606060028351101561118f576040516320db826760e01b815260040160405180910390fd5b6000835167ffffffffffffffff8111156111ab576111ab613945565b6040519080825280602002602001820160405280156111d4578160200160208202803683370190505b5090508481600186516111e79190613c33565b815181106111f7576111f7613ba8565b6020026020010181815250506000600185516112139190613c33565b90505b80156114af5760008061128b8761122e600186613c33565b8151811061123e5761123e613ba8565b602002602001015188858151811061125857611258613ba8565b60200260200101518860018761126e9190613c33565b8151811061127e5761127e613ba8565b6020026020010151611b76565b90925090506001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c16876112c6600186613c33565b815181106112d6576112d6613ba8565b60200260200101516001600160a01b0316141561138a576103e8866112fc600186613c33565b8151811061130c5761130c613ba8565b60200260200101516103e86113219190613c63565b61ffff1661134986868151811061133a5761133a613ba8565b6020026020010151858561357a565b6113539190613c89565b61135d9190613ca8565b84611369600186613c33565b8151811061137957611379613ba8565b60200260200101818152505061149a565b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b03168784815181106113c6576113c6613ba8565b60200260200101516001600160a01b0316141561144d5761135d866113ec600186613c33565b815181106113fc576113fc613ba8565b60200260200101516103e86114119190613cca565b61ffff1685858151811061142757611427613ba8565b60200260200101516103e861143c9190613c89565b6114469190613ca8565b838361357a565b61147184848151811061146257611462613ba8565b6020026020010151838361357a565b8461147d600186613c33565b8151811061148d5761148d613ba8565b6020026020010181815250505b505080806114a790613ced565b915050611216565b50949350505050565b60608160a00135428110156114e057604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9166115176040850185613b5e565b600081811061152857611528613ba8565b905060200201602081019061153d9190613bbe565b6001600160a01b031614611564576040516320db826760e01b815260040160405180910390fd5b6115b583356115766040860186613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610a0c925050506060870187613b5e565b915034826000815181106115cb576115cb613ba8565b602002602001015111156115f25760405163e1b0da4f60e01b815260040160405180910390fd5b7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663d0e30db08360008151811061163457611634613ba8565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166757600080fd5b505af115801561167b573d6000803e3d6000fd5b50505050507f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663a9059cbb6116c28580604001906104f89190613b5e565b846000815181106116d5576116d5613ba8565b60200260200101516040518363ffffffff1660e01b815260040161170e9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561172d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117519190613bfb565b61175d5761175d613855565b60208301356117f4836117736040870187613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506117b2925050506060880188613b5e565b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610be49250505060a0890160808a01613bbe565b111561181357604051634b41cb4560e01b815260040160405180910390fd5b8160008151811061182657611826613ba8565b602002602001015134111561186457611864338360008151811061184c5761184c613ba8565b60200260200101513461185f9190613c33565b613492565b50919050565b606060028351101561188f576040516320db826760e01b815260040160405180910390fd5b6000835167ffffffffffffffff8111156118ab576118ab613945565b6040519080825280602002602001820160405280156118d4578160200160208202803683370190505b50905084816000815181106118eb576118eb613ba8565b60200260200101818152505060005b600185516119089190613c33565b8110156114af5760008061196787848151811061192757611927613ba8565b60200260200101518885600161193d9190613d04565b8151811061194d5761194d613ba8565b602002602001015188868151811061127e5761127e613ba8565b915091507f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b03168784815181106119a7576119a7613ba8565b60200260200101516001600160a01b03161415611a5157611a248684815181106119d3576119d3613ba8565b60200260200101516103e86119e89190613c63565b61ffff168585815181106119fe576119fe613ba8565b60200260200101516103e8611a139190613c89565b611a1d9190613ca8565b83836135fe565b84611a30856001613d04565b81518110611a4057611a40613ba8565b602002602001018181525050611b61565b6001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c1687611a87856001613d04565b81518110611a9757611a97613ba8565b60200260200101516001600160a01b03161415611b14576103e8868481518110611ac357611ac3613ba8565b60200260200101516103e8611ad89190613cca565b61ffff16611b00868681518110611af157611af1613ba8565b602002602001015185856135fe565b611b0a9190613c89565b611a249190613ca8565b611b38848481518110611b2957611b29613ba8565b602002602001015183836135fe565b84611b44856001613d04565b81518110611b5457611b54613ba8565b6020026020010181815250505b50508080611b6e90613d1c565b9150506118fa565b6000806000611b858686613686565b509050600080611b96888888611c4e565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf79190613d55565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150826001600160a01b0316886001600160a01b031614611c3c578082611c3f565b81815b90999098509650505050505050565b6000806000611c5d8686613686565b6040516bffffffffffffffffffffffff19606084811b8216602084015283811b821660348401527fffff00000000000000000000000000000000000000000000000000000000000060f08a901b1660488401527f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c901b16604a82015291935091507f0000000000000000000000008af94528fbe3c4c148523e7aad48bcebcc0a71d790605e01604051602081830303815290604052805190602001207f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316846001600160a01b031614611d8d576040518060400160405280602081526020017f3b29ecd4cb06592a81cac4799fb24ef6a176fe95ecb50f304972882b150f3f3a815250611dc4565b6040518060400160405280602081526020017f99c189a5ef3d337612cf0ce2bd055546e23b91fea9e9e54201b23f14d763f3338152505b604051602001611dd693929190613dd1565b60408051601f1981840301815291905280516020909101209695505050505050565b60608160a0013542811015611e2057604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e916611e576040850185613b5e565b6000818110611e6857611e68613ba8565b9050602002016020810190611e7d9190613bbe565b6001600160a01b031614611ea4576040516320db826760e01b815260040160405180910390fd5b611ef434611eb56040860186613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506110e6925050506060870187613b5e565b915082600001358260018451611f0a9190613c33565b81518110611f1a57611f1a613ba8565b60200260200101511015611f41576040516342301c2360e01b815260040160405180910390fd5b7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663d0e30db083600081518110611f8357611f83613ba8565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015611fb657600080fd5b505af1158015611fca573d6000803e3d6000fd5b50505050507f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031663a9059cbb6120118580604001906104f89190613b5e565b8460008151811061202457612024613ba8565b60200260200101516040518363ffffffff1660e01b815260040161205d9291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af115801561207c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a09190613bfb565b6120ac576120ac613855565b60208301356120c2836117736040870187613b5e565b111561186457604051634b41cb4560e01b815260040160405180910390fd5b8060c001354281101561210757604051630407b05b60e31b815260040160405180910390fd5b6121bb6121176060840184613b5e565b600081811061212857612128613ba8565b905060200201602081019061213d9190613bbe565b336121b461214e6060870187613b5e565b600081811061215f5761215f613ba8565b90506020020160208101906121749190613bbe565b6121816060880188613b5e565b600181811061219257612192613ba8565b90506020020160208101906121a79190613bbe565b61055e6080890189613b5e565b8535612f15565b60006121ca6060840184613b5e565b60016121d96060870187613b5e565b6121e4929150613c33565b8181106121f3576121f3613ba8565b90506020020160208101906122089190613bbe565b6001600160a01b03166370a0823161222660c0860160a08701613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561226a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228e9190613c4a565b9050600060405180606001604052808580606001906122ad9190613b5e565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020016122f16080870187613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161233860c0870160a08801613bbe565b6001600160a01b031690529050604084013561235382612968565b111561237257604051634b41cb4560e01b815260040160405180910390fd5b6020840135826123856060870187613b5e565b600161239460608a018a613b5e565b61239f929150613c33565b8181106123ae576123ae613ba8565b90506020020160208101906123c39190613bbe565b6001600160a01b03166370a082316123e160c0890160a08a01613bbe565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124499190613c4a565b6124539190613c33565b1015612472576040516342301c2360e01b815260040160405180910390fd5b50505050565b60608160c00135428110156124a057604051630407b05b60e31b815260040160405180910390fd5b60006001600160a01b037f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c166124d96060860186613b5e565b60008181106124ea576124ea613ba8565b90506020020160208101906124ff9190613bbe565b6001600160a01b03161461251457833561256f565b6103e86125246080860186613b5e565b600081811061253557612535613ba8565b905060200201602081019061254a9190613be0565b612556906103e8613c63565b6125659061ffff168635613c89565b61256f9190613ca8565b90506001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9166125a86060860186613b5e565b60016125b76060890189613b5e565b6125c2929150613c33565b8181106125d1576125d1613ba8565b90506020020160208101906125e69190613bbe565b6001600160a01b03161461260d576040516320db826760e01b815260040160405180910390fd5b61261e816110a76060870187613b5e565b9250836020013583600185516126349190613c33565b8151811061264457612644613ba8565b60200260200101511015610df9576040516342301c2360e01b815260040160405180910390fd5b8060c001354281101561269157604051630407b05b60e31b815260040160405180910390fd5b6001600160a01b037f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9166126c86060840184613b5e565b60016126d76060870187613b5e565b6126e2929150613c33565b8181106126f1576126f1613ba8565b90506020020160208101906127069190613bbe565b6001600160a01b03161461272d576040516320db826760e01b815260040160405180910390fd5b61273d6121176060840184613b5e565b6000604051806060016040528084806060019061275a9190613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060200161279e6080860186613b5e565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525030602090910152905060408301356127e982612968565b111561280857604051634b41cb4560e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000907f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b0316906370a0823190602401602060405180830381865afa15801561286f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128939190613c4a565b905083602001358110156128ba576040516342301c2360e01b815260040160405180910390fd5b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e96001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561293557600080fd5b505af1158015612949573d6000803e3d6000fd5b50612472925061296291505060c0860160a08701613bbe565b82613492565b6000805b82515161297b90600190613c33565b811015611864576000808460000151838151811061299b5761299b613ba8565b602002602001015185600001518460016129b59190613d04565b815181106129c5576129c5613ba8565b6020026020010151915091506000856020015184815181106129e9576129e9613ba8565b602002602001015190506000612a00848484611c4e565b90506000612a0e8585613686565b509050600080600080856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a799190613d55565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600080866001600160a01b03168b6001600160a01b031614612ac1578284612ac4565b83835b6040516370a0823160e01b81526001600160a01b038b8116600483015292945090925083918d16906370a0823190602401602060405180830381865afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190613c4a565b612b409190613c33565b95507f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b03168b6001600160a01b03161415612ba257612b9b612b8b8a6103e8613c63565b61ffff16611a13886103e8613c89565b9450612c1a565b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b03168a6001600160a01b03161415612c0c576103e8612be98a82613cca565b61ffff16612bf88885856135fe565b612c029190613c89565b612b9b9190613ca8565b612c178683836135fe565b94505b50505050600080846001600160a01b0316896001600160a01b031614612c4257826000612c46565b6000835b915091507f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316896001600160a01b03161415612cbf57612c90876103e8613c63565b61ffff168761ffff1685612ca49190613c89565b612cae9190613ca8565b612cb8908c613d04565b9a50612e0f565b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316886001600160a01b03161415612d0a576103e8612ca461ffff891686613c89565b6000866001600160a01b0316632f72563884886001600160a01b03168d6001600160a01b031614612d3c576000612d3e565b875b858a6001600160a01b03168f6001600160a01b031614612d5e5789612d61565b60005b6040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401602060405180830381865afa158015612daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd39190613c4a565b9050612e017f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c338984612f15565b612e0b818d613d04565b9b50505b8b5151600090612e2190600290613c33565b8b10612e31578c60400151612e8b565b8c51612e8b908a90612e448e6002613d04565b81518110612e5457612e54613ba8565b60200260200101518f602001518e6001612e6e9190613d04565b81518110612e7e57612e7e613ba8565b6020026020010151611c4e565b6040516336cd320560e11b815260048101859052602481018490526001600160a01b03808316604483015291925090881690636d9a640a90606401600060405180830381600087803b158015612ee057600080fd5b505af1158015612ef4573d6000803e3d6000fd5b50505050505050505050505050508080612f0d90613d1c565b91505061296c565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612fa79190613e36565b6000604051808303816000865af19150503d8060008114612fe4576040519150601f19603f3d011682016040523d82523d6000602084013e612fe9565b606091505b50915091508180156130135750805115806130135750808060200190518101906130139190613bfb565b61308a5760405162461bcd60e51b815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c656400000000000000000000000000000060648201526084015b60405180910390fd5b505050505050565b6000805b600185516130a49190613c33565b8110156114af576000808683815181106130c0576130c0613ba8565b6020026020010151878460016130d69190613d04565b815181106130e6576130e6613ba8565b602002602001015191509150600086848151811061310657613106613ba8565b60200260200101519050600061311d848484611c4e565b9050600061312b8585613686565b509050600080826001600160a01b0316876001600160a01b031614613175578c613156896001613d04565b8151811061316657613166613ba8565b6020026020010151600061319c565b60008d6131838a6001613d04565b8151811061319357613193613ba8565b60200260200101515b9150915060008d89815181106131b4576131b4613ba8565b602002602001015190507f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316886001600160a01b0316141561323357613204866103e8613c63565b61ffff168661ffff16826132189190613c89565b6132229190613ca8565b61322c908b613d04565b99506133b7565b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316876001600160a01b031614156132b257613279866103e8613cca565b61ffff168661ffff168f8b60016132909190613d04565b815181106132a0576132a0613ba8565b60200260200101516132189190613c89565b6000856001600160a01b0316632f72563885876001600160a01b03168c6001600160a01b0316146132e45760006132e6565b845b86896001600160a01b03168e6001600160a01b0316146133065786613309565b60005b6040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401602060405180830381865afa158015613357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337b9190613c4a565b90506133a97f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c338884612f15565b6133b3818c613d04565b9a50505b50600060028d516133c89190613c33565b89106133d4578a61340a565b61340a878e6133e48c6002613d04565b815181106133f4576133f4613ba8565b60200260200101518e8c6001612e6e9190613d04565b6040516336cd320560e11b815260048101859052602481018490526001600160a01b03808316604483015291925090861690636d9a640a90606401600060405180830381600087803b15801561345f57600080fd5b505af1158015613473573d6000803e3d6000fd5b505050505050505050505050808061348a90613d1c565b915050613096565b604080516000808252602082019092526001600160a01b0384169083906040516134bc9190613e36565b60006040518083038185875af1925050503d80600081146134f9576040519150601f19603f3d011682016040523d82523d6000602084013e6134fe565b606091505b50509050806135755760405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401613081565b505050565b60008361359a576040516342301c2360e01b815260040160405180910390fd5b8215806135a5575081155b156135c35760405163bb55fd2760e01b815260040160405180910390fd5b60006135cf8585613c89565b905060006135dd8685613c33565b90506135e98183613ca8565b6135f4906001613d04565b9695505050505050565b600083613637576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821580613642575081155b156136605760405163bb55fd2760e01b815260040160405180910390fd5b600061366c8386613c89565b9050600061367a8686613d04565b90506135f48183613ca8565b600080826001600160a01b0316846001600160a01b031614156136d5576040517fbd969eb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316846001600160a01b0316148061374657507f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316836001600160a01b0316145b156137ff577f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c6001600160a01b0316846001600160a01b0316146137ab577f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c846137ce565b7f00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c835b90925090506001600160a01b0381166137fa5760405163d92e233d60e01b815260040160405180910390fd5b61384e565b826001600160a01b0316846001600160a01b03161061381f578284613822565b83835b90925090506001600160a01b03821661384e5760405163d92e233d60e01b815260040160405180910390fd5b9250929050565b634e487b7160e01b600052600160045260246000fd5b600060c0828403121561186457600080fd5b60006020828403121561388f57600080fd5b813567ffffffffffffffff8111156138a657600080fd5b6138b28482850161386b565b949350505050565b600060e0828403121561186457600080fd5b6000602082840312156138de57600080fd5b813567ffffffffffffffff8111156138f557600080fd5b6138b2848285016138ba565b6020808252825182820181905260009190848201906040850190845b818110156139395783518352928401929184019160010161391d565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561398457613984613945565b604052919050565b600067ffffffffffffffff8211156139a6576139a6613945565b5060051b60200190565b80356001600160a01b03811681146139c757600080fd5b919050565b803561ffff811681146139c757600080fd5b600082601f8301126139ef57600080fd5b81356020613a046139ff8361398c565b61395b565b82815260059290921b84018101918181019086841115613a2357600080fd5b8286015b84811015613a4557613a38816139cc565b8352918301918301613a27565b509695505050505050565b600080600060608486031215613a6557600080fd5b8335925060208085013567ffffffffffffffff80821115613a8557600080fd5b818701915087601f830112613a9957600080fd5b8135613aa76139ff8261398c565b81815260059190911b8301840190848101908a831115613ac657600080fd5b938501935b82851015613aeb57613adc856139b0565b82529385019390850190613acb565b965050506040870135925080831115613b0357600080fd5b5050613b11868287016139de565b9150509250925092565b600080600060608486031215613b3057600080fd5b613b39846139b0565b9250613b47602085016139b0565b9150613b55604085016139cc565b90509250925092565b6000808335601e19843603018112613b7557600080fd5b83018035915067ffffffffffffffff821115613b9057600080fd5b6020019150600581901b360382131561384e57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215613bd057600080fd5b613bd9826139b0565b9392505050565b600060208284031215613bf257600080fd5b613bd9826139cc565b600060208284031215613c0d57600080fd5b81518015158114613bd957600080fd5b634e487b7160e01b600052601160045260246000fd5b600082821015613c4557613c45613c1d565b500390565b600060208284031215613c5c57600080fd5b5051919050565b600061ffff808316818516808303821115613c8057613c80613c1d565b01949350505050565b6000816000190483118215151615613ca357613ca3613c1d565b500290565b600082613cc557634e487b7160e01b600052601260045260246000fd5b500490565b600061ffff83811690831681811015613ce557613ce5613c1d565b039392505050565b600081613cfc57613cfc613c1d565b506000190190565b60008219821115613d1757613d17613c1d565b500190565b6000600019821415613d3057613d30613c1d565b5060010190565b80516dffffffffffffffffffffffffffff811681146139c757600080fd5b600080600060608486031215613d6a57600080fd5b613d7384613d37565b9250613d8160208501613d37565b9150604084015163ffffffff81168114613d9a57600080fd5b809150509250925092565b60005b83811015613dc0578181015183820152602001613da8565b838111156124725750506000910152565b7fff0000000000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff198460601b16600182015282601582015260008251613e27816035850160208701613da5565b91909101603501949350505050565b60008251613e48818460208701613da5565b919091019291505056fea2646970667358221220035e8a06ff2fb49525cf9f2c1541d7436c7f4a2a69289412e1072cf4ddea72c364736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008af94528fbe3c4c148523e7aad48bcebcc0a71d70000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e900000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c
-----Decoded View---------------
Arg [0] : _factory (address): 0x8aF94528FBE3c4C148523E7aAD48BcEbcC0A71d7
Arg [1] : _WETH (address): 0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9
Arg [2] : _antfarmToken (address): 0x40DF0C3BBAAE5Ea3A509d8F2aa9E086776C98E6c
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000008af94528fbe3c4c148523e7aad48bcebcc0a71d7
Arg [1] : 0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9
Arg [2] : 00000000000000000000000040df0c3bbaae5ea3a509d8f2aa9e086776c98e6c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ZKSYNC | 100.00% | $3,231.67 | 0.00003424 | $0.110652 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.