Contract 0x31f63a33141ffee63d4b26755430a390acdd8a4d 2

 

Contract Overview

Balance:
0 FTM

FTM Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xe9605185722570b5067023e1b53d80a06a4d2ee5a81830857f183870554271ebMulticall477927732022-09-26 13:32:218 secs ago0x88397e6bb821b6687382859b54088f8c32935640 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d2 FTM0.000408124703
0xd390ed1f22827ff0d4ba270b92d1ae8aee62f4d8ad90dff40362681afc271f7bMulticall477927622022-09-26 13:32:0029 secs ago0xa46c003ec3ee8b1eaad9cac32f2835e584261a81 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d95 FTM0.004450724649
0x7dd79a0323485cadbd731eb2066c608a3debe7fcb418f3290a48f8b43a4b49cbMulticall477927442022-09-26 13:31:3059 secs ago0xc817eff12fd883b20b9fd91df00b029390ec1ffb IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000625376
0x953829898cbbc2c194606c35b9d81221ca8e7f187365daac3b8aa3776b13f83dMulticall477927352022-09-26 13:31:201 min ago0x221783cd61a745f50de2672eac63ba6b4ee5c8b8 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000491986447
0xa1a742b46b7ecdcc3b0cf47ecda7eb7ec881c70ce0f1bae271ec95e83850e49dMulticall477925962022-09-26 13:28:214 mins ago0xcee7eae68bb61e47f752af0a0df40ec71f75387c IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.003237517095
0xb03450f4de7d250db2549cb484d1c7de0839bb6d73eb49390abc90f695b5341eMulticall477925912022-09-26 13:28:144 mins ago0x3405495fe14de80a448fe6301cee54760b1a260f IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.002070315491
0x0fa1a2996879a5b4ff215afe777a7c3e572bc3f032c7f4e6a7b52b56fccc66bfMulticall477925892022-09-26 13:28:124 mins ago0x61e3595c550ab7deeb63f27d45f150ff1055f84e IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000723160062
0xc40497d23ef57af361a1e377b1acb18e28af26521bdc285cebd94b2bcbec2c66Multicall477925722022-09-26 13:27:354 mins ago0x7e43412254c693e3f009fe4719ef444c1ba534cf IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000631547233
0x608fc32cd07dbfd83b508c551e2e31bb6646056e9f5677bbd8a7ac6cee1b3c78Multicall477924992022-09-26 13:25:516 mins ago0x75d1620cc8b57908bf45fa895e6a93957db43f34 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d141.872775705234711 FTM0.009757809506
0x83546ea7e675086d30921326a6e1db5d8069418348e049b55b13cafbe839c728Multicall477924742022-09-26 13:24:587 mins ago0xa6370f16c475d80cef6ed781c4601107bf21c0f6 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d100 FTM0.40488496669
0x242f04291001f4c928254f0095d1eb0ef9721a4a974e86c2379cdb7576757d0aMulticall477924572022-09-26 13:24:268 mins ago0xe0014ea1c0040d4acbc087617a457975ff44381e IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000513983729
0x5e68960c31a2723adc1074e92207f1e287b0ffad028b0f046d29db0b264a2cc7Multicall477924072022-09-26 13:23:299 mins ago0xe0014ea1c0040d4acbc087617a457975ff44381e IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.000514361566
0x913d316ac35626c0a6be1c593cce974e5afd323fa665cb5baff3cb3cd85e0d73Multicall477923932022-09-26 13:23:019 mins ago0x4444706d46d5e058bf61e77bada49ac94fe93e50 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.495674969981
0x7ab46342739a2258f41a443e742fc3e6d314d2d64d5ae9993ef4308644fabb71Multicall477923442022-09-26 13:21:3910 mins ago0x9b9e8bc43c15559653868587a193bd014dff5c65 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.059081014479
0xccfaf0b4049c9c7410f8f37981dcd59918ebdb8311fb8e488280fb8e786aa1d0Multicall477923252022-09-26 13:21:0011 mins ago0x28112bb5731d22b80aeaf432094a169a5fe875c7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d1 FTM0.126386513255
0xaa75ca3d16ebf62e7f15beea6e9cf828fdc166b4e9ebcf710a92c61e0c47ff7aMulticall477923102022-09-26 13:20:3811 mins ago0x34237db3bacb51778c91c5557039ff26e97b492d IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.02212782
0x8444689a7cefe27c8523f189b170319dd7114171b5d56c3e281ff6b486570d8fMulticall477922902022-09-26 13:20:0612 mins ago0x34237db3bacb51778c91c5557039ff26e97b492d IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.02867106
0x61df5f381274703c00ff43168b61feda43ec9a175d025a7c88cabc296e999d07Multicall477922882022-09-26 13:20:0312 mins ago0xe4fcb1f9a3eed9b8dc96cb738e95a5b23c55f820 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.4737831875
0x38d9f882fd85bb679d58b658ca40cca452b5a543a13e17f0272a7cad24066726Multicall477922662022-09-26 13:19:2313 mins ago0x34237db3bacb51778c91c5557039ff26e97b492d IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.02791899
0x77e554d0aea87b705f7ca05eaa83b66e5c3c6b90613f0f8cfab2f7dc607a0f26Multicall477922552022-09-26 13:19:0813 mins ago0x0f03f6686794aecbd064a2b1af9506792c684d17 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.012384678516
0xe7121af022aa4202c7d9ead2d08eb2d464360c3c9e3395dbf0879e1a17d6a609Multicall477922432022-09-26 13:18:4413 mins ago0xd86b8f9287577338f65893745caa95959bd62285 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d115 FTM0.313455517836
0x344dd9f74a3214e47a5b8a5c8dfb6fd843235aa36a9edb3d419e96d1f7c2deb5Multicall477922422022-09-26 13:18:4113 mins ago0xe2729953ffb1d6b575c02ecd4d15579bd0353ab2 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.21307792443
0x49e9e30c6c6623caa65ccb237a9ed57acde0884d4628ac98e7e56f64850fc790Multicall477922402022-09-26 13:18:3813 mins ago0x28112bb5731d22b80aeaf432094a169a5fe875c7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d2 FTM0.011530289553
0x7682ab590844d9d1a86dd814b5b7ab356b3e366b48641bcd1f421eb120dcb780Multicall477922132022-09-26 13:17:4214 mins ago0x75d228291f2670546549563569d25ab1840fa897 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.106834187256
0x4fc0edd1b600a7b35889c3b526d62fb314491a64bba95f7cd40ae6036a977328Multicall477921992022-09-26 13:17:1515 mins ago0xbea30b46660b37c7fdd095b23f848967d132deab IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.02816696572
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xe9605185722570b5067023e1b53d80a06a4d2ee5a81830857f183870554271eb477927732022-09-26 13:32:218 secs ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token2 FTM
0xd390ed1f22827ff0d4ba270b92d1ae8aee62f4d8ad90dff40362681afc271f7b477927622022-09-26 13:32:0029 secs ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token95 FTM
0x7dd79a0323485cadbd731eb2066c608a3debe7fcb418f3290a48f8b43a4b49cb477927442022-09-26 13:31:3059 secs ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xc817eff12fd883b20b9fd91df00b029390ec1ffb438.663248414199748478 FTM
0x7dd79a0323485cadbd731eb2066c608a3debe7fcb418f3290a48f8b43a4b49cb477927442022-09-26 13:31:3059 secs ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d438.663248414199748478 FTM
0x953829898cbbc2c194606c35b9d81221ca8e7f187365daac3b8aa3776b13f83d477927352022-09-26 13:31:201 min ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x221783cd61a745f50de2672eac63ba6b4ee5c8b89.525341601844159673 FTM
0x953829898cbbc2c194606c35b9d81221ca8e7f187365daac3b8aa3776b13f83d477927352022-09-26 13:31:201 min ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d9.525341601844159673 FTM
0xb03450f4de7d250db2549cb484d1c7de0839bb6d73eb49390abc90f695b5341e477925912022-09-26 13:28:144 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x3405495fe14de80a448fe6301cee54760b1a260f70.205363937656874242 FTM
0xb03450f4de7d250db2549cb484d1c7de0839bb6d73eb49390abc90f695b5341e477925912022-09-26 13:28:144 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d70.205363937656874242 FTM
0x0fa1a2996879a5b4ff215afe777a7c3e572bc3f032c7f4e6a7b52b56fccc66bf477925892022-09-26 13:28:124 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x61e3595c550ab7deeb63f27d45f150ff1055f84e5.19889079146878025 FTM
0x0fa1a2996879a5b4ff215afe777a7c3e572bc3f032c7f4e6a7b52b56fccc66bf477925892022-09-26 13:28:124 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d5.19889079146878025 FTM
0x608fc32cd07dbfd83b508c551e2e31bb6646056e9f5677bbd8a7ac6cee1b3c78477924992022-09-26 13:25:516 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token141.872775705234711867 FTM
0x83546ea7e675086d30921326a6e1db5d8069418348e049b55b13cafbe839c728477924742022-09-26 13:24:587 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token100 FTM
0x242f04291001f4c928254f0095d1eb0ef9721a4a974e86c2379cdb7576757d0a477924572022-09-26 13:24:268 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xe0014ea1c0040d4acbc087617a457975ff44381e2 FTM
0x242f04291001f4c928254f0095d1eb0ef9721a4a974e86c2379cdb7576757d0a477924572022-09-26 13:24:268 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d2 FTM
0x5e68960c31a2723adc1074e92207f1e287b0ffad028b0f046d29db0b264a2cc7477924072022-09-26 13:23:299 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xe0014ea1c0040d4acbc087617a457975ff44381e2 FTM
0x5e68960c31a2723adc1074e92207f1e287b0ffad028b0f046d29db0b264a2cc7477924072022-09-26 13:23:299 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d2 FTM
0x913d316ac35626c0a6be1c593cce974e5afd323fa665cb5baff3cb3cd85e0d73477923932022-09-26 13:23:019 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x4444706d46d5e058bf61e77bada49ac94fe93e501,129.563658051531591778 FTM
0x913d316ac35626c0a6be1c593cce974e5afd323fa665cb5baff3cb3cd85e0d73477923932022-09-26 13:23:019 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d1,129.563658051531591778 FTM
0x7ab46342739a2258f41a443e742fc3e6d314d2d64d5ae9993ef4308644fabb71477923442022-09-26 13:21:3910 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x9b9e8bc43c15559653868587a193bd014dff5c654.416704913602544056 FTM
0x7ab46342739a2258f41a443e742fc3e6d314d2d64d5ae9993ef4308644fabb71477923442022-09-26 13:21:3910 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d4.416704913602544056 FTM
0xccfaf0b4049c9c7410f8f37981dcd59918ebdb8311fb8e488280fb8e786aa1d0477923252022-09-26 13:21:0011 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token1 FTM
0xaa75ca3d16ebf62e7f15beea6e9cf828fdc166b4e9ebcf710a92c61e0c47ff7a477923102022-09-26 13:20:3811 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x34237db3bacb51778c91c5557039ff26e97b492d193.147209128970839448 FTM
0xaa75ca3d16ebf62e7f15beea6e9cf828fdc166b4e9ebcf710a92c61e0c47ff7a477923102022-09-26 13:20:3811 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d193.147209128970839448 FTM
0x8444689a7cefe27c8523f189b170319dd7114171b5d56c3e281ff6b486570d8f477922902022-09-26 13:20:0612 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x34237db3bacb51778c91c5557039ff26e97b492d11.104809363010809379 FTM
0x8444689a7cefe27c8523f189b170319dd7114171b5d56c3e281ff6b486570d8f477922902022-09-26 13:20:0612 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d11.104809363010809379 FTM
[ Download CSV Export 
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
LiquidityBrewer

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 9999 runs

Other Settings:
default evmVersion
File 1 of 16 : LiquidityBrewer.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.13;

import "./utils/SpookyApprovals.sol";
import "./utils/SelfPermit.sol";
import "./utils/Multicall.sol";
import "./router/UniswapV2Router02.sol";

/// @notice boooo! spooooky!! nyahaha! ₍⸍⸌̣ʷ̣̫⸍̣⸌₎
contract LiquidityBrewer is SpookyApprovals, UniswapV2Router02, SelfPermit, Multicall {
    IMCV2 public MCV21;
    IMCV2 public MCV22;

    constructor(address _factory, address _WETH, address mcv21, address mcv22) UniswapV2Router02(_factory, _WETH) {
        MCV21 = IMCV2(mcv21);
        MCV22 = IMCV2(mcv22);
    }

    //add liquidity and deposit to masterchef v2
    function addLiquidityAndDeposit(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        uint pid,
        bool useMCV22
    ) external {
        (,, uint liquidity) = addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin, address(this), deadline);

        IMCV2 MCV2 = useMCV22 ? MCV22 : MCV21;
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        _approveIfNeeded(pair, address(MCV2));
        MCV2.deposit(pid, liquidity, to);
    }

    //add liquidity eth and deposit to masterchef v2
    function addLiquidityETHAndDeposit(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        uint pid,
        bool useMCV22
    ) external payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
        (amountToken, amountETH) = _addLiquidity(token, WETH, amountTokenDesired, msg.value, amountTokenMin, amountETHMin);
        address pair = UniswapV2Library.pairFor(factory, token, WETH);
        TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
        IWETH(WETH).deposit{value: amountETH}();
        assert(IWETH(WETH).transfer(pair, amountETH));
        liquidity = IUniswapV2Pair(pair).mint(address(this));
        // refund dust eth, if any
        if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);

        IMCV2 MCV2 = useMCV22 ? MCV22 : MCV21;
        _approveIfNeeded(pair, address(MCV2));
        MCV2.deposit(pid, liquidity, to);
    }

    //deposit to masterchef v2
    function deposit(uint pid, uint amount, address to, bool useMCV22) external {
        IMCV2 MCV2 = useMCV22 ? MCV22 : MCV21;
        address token = address(MCV2.lpToken(pid));
        IERC20(token).transferFrom(msg.sender, address(this), amount);
        _approveIfNeeded(token, address(MCV2));
        MCV2.deposit(pid, amount, to);
    }

    //in case more than max_uint wei of a token are transferred in the lifetime
    function reApprove(uint pid, bool useMCV22) external {
        IMCV2 MCV2 = useMCV22 ? MCV22 : MCV21;
        IERC20(address(MCV2.lpToken(pid))).approve(address(MCV2), 2**256 - 1);
    }
}

interface IMCV2 {
    function deposit(uint pid, uint amount, address to) external;
    function lpToken(uint) external returns (IERC20);
}

File 2 of 16 : SpookyApprovals.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8;

interface ierc20 {
    function approve(address spender, uint256 amount) external returns (bool);
}

abstract contract SpookyApprovals {
    mapping(address => mapping(address => bool)) isApproved;

    function _approveIfNeeded(address _token, address _spender) internal {
        if(!isApproved[_token][_spender]) {
            ierc20(_token).approve(_spender, 2**256 - 1);
            isApproved[_token][_spender] = true;
        }
    }

}

File 3 of 16 : SelfPermit.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity >=0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";

interface IERC20PermitAllowed {
    function permit(
        address holder,
        address spender,
        uint256 nonce,
        uint256 expiry,
        bool allowed,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

abstract contract SelfPermit {
    function selfPermit(
        address token,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public payable {
        IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s);
    }

    function selfPermitIfNecessary(
        address token,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external payable {
        if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s);
    }

    function selfPermitAllowed(

        address token,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public payable {
        IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s);
    }

    function selfPermitAllowedIfNecessary(
        address token,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external payable {
        if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max)
            selfPermitAllowed(token, nonce, expiry, v, r, s);
    }

    function supportsPermits(address token) external view returns (bytes32 domainSeparator) {
        try IERC20Permit(token).DOMAIN_SEPARATOR() returns (bytes32 separator) {
            return separator;
        } catch {
            return bytes32(0);
        }
    }
}

File 4 of 16 : Multicall.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity >=0.8.0;

/// @notice Helper utility that enables calling multiple local methods in a single call.
/// @author Modified from Uniswap (https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/Multicall.sol)
/// License-Identifier: GPL-2.0-or-later
abstract contract Multicall {
    function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
        results = new bytes[](data.length);

        for (uint256 i; i < data.length;) {
            (bool success, bytes memory result) = address(this).delegatecall(data[i]);

            if (!success) {
                // Next 5 lines from https://ethereum.stackexchange.com/a/83577
                if (result.length < 68) revert();
                assembly {
                    result := add(result, 0x04)
                }
                revert(abi.decode(result, (string)));
            }

            results[i] = result;

            // cannot realistically overflow on human timescales
        unchecked {
            ++i;
        }
        }
    }
}

File 5 of 16 : UniswapV2Router02.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8;

import './interfaces/IUniswapV2Router02.sol';
import './interfaces/IUniswapV2Factory.sol';
import './libraries/UniswapV2Library.sol';
import './libraries/TransferHelper.sol';
import './libraries/SafeMath.sol';
import './interfaces/IERC20.sol';
import './interfaces/IWETH.sol';

contract UniswapV2Router02 is IUniswapV2Router02 {
    using SafeMath for uint;

    address public immutable override factory;
    address public immutable override WETH;

    modifier ensure(uint deadline) {
        require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
        _;
    }

    constructor(address _factory, address _WETH) {
        factory = _factory;
        WETH = _WETH;
    }

    receive() external payable {
        assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract
    }

    // **** ADD LIQUIDITY ****
    function _addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin
    ) internal virtual returns (uint amountA, uint amountB) {
        // create the pair if it doesn't exist yet
        if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
            IUniswapV2Factory(factory).createPair(tokenA, tokenB);
        }
        (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB);
        if (reserveA == 0 && reserveB == 0) {
            (amountA, amountB) = (amountADesired, amountBDesired);
        } else {
            uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);
            if (amountBOptimal <= amountBDesired) {
                require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT');
                (amountA, amountB) = (amountADesired, amountBOptimal);
            } else {
                uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA);
                assert(amountAOptimal <= amountADesired);
                require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT');
                (amountA, amountB) = (amountAOptimal, amountBDesired);
            }
        }
    }
    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) public virtual override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
        (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
        TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
        liquidity = IUniswapV2Pair(pair).mint(to);
    }
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) public virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
        (amountToken, amountETH) = _addLiquidity(
            token,
            WETH,
            amountTokenDesired,
            msg.value,
            amountTokenMin,
            amountETHMin
        );
        address pair = UniswapV2Library.pairFor(factory, token, WETH);
        TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
        IWETH(WETH).deposit{value: amountETH}();
        assert(IWETH(WETH).transfer(pair, amountETH));
        liquidity = IUniswapV2Pair(pair).mint(to);
        // refund dust eth, if any
        if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
    }

    // **** REMOVE LIQUIDITY ****
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) public virtual override ensure(deadline) returns (uint amountA, uint amountB) {
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
        (uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to);
        (address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB);
        (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
        require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT');
        require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT');
    }
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) public virtual override ensure(deadline) returns (uint amountToken, uint amountETH) {
        (amountToken, amountETH) = removeLiquidity(
            token,
            WETH,
            liquidity,
            amountTokenMin,
            amountETHMin,
            address(this),
            deadline
        );
        TransferHelper.safeTransfer(token, to, amountToken);
        IWETH(WETH).withdraw(amountETH);
        TransferHelper.safeTransferETH(to, amountETH);
    }
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external virtual override returns (uint amountA, uint amountB) {
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        uint value = approveMax ? 2**256 - 1 : liquidity;
        IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
        (amountA, amountB) = removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline);
    }
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external virtual override returns (uint amountToken, uint amountETH) {
        address pair = UniswapV2Library.pairFor(factory, token, WETH);
        uint value = approveMax ? 2**256 - 1 : liquidity;
        IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
        (amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline);
    }

    // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) ****
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) public virtual override ensure(deadline) returns (uint amountETH) {
        (, amountETH) = removeLiquidity(
            token,
            WETH,
            liquidity,
            amountTokenMin,
            amountETHMin,
            address(this),
            deadline
        );
        TransferHelper.safeTransfer(token, to, IERC20i(token).balanceOf(address(this)));
        IWETH(WETH).withdraw(amountETH);
        TransferHelper.safeTransferETH(to, amountETH);
    }
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external virtual override returns (uint amountETH) {
        address pair = UniswapV2Library.pairFor(factory, token, WETH);
        uint value = approveMax ? 2**256 - 1 : liquidity;
        IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
        amountETH = removeLiquidityETHSupportingFeeOnTransferTokens(
            token, liquidity, amountTokenMin, amountETHMin, to, deadline
        );
    }

    // **** SWAP ****
    // requires the initial amount to have already been sent to the first pair
    function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
        for (uint i; i < path.length - 1; i++) {
            (address input, address output) = (path[i], path[i + 1]);
            (address token0,) = UniswapV2Library.sortTokens(input, output);
            uint amountOut = amounts[i + 1];
            (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
            address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
            IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap(
                amount0Out, amount1Out, to, new bytes(0)
            );
        }
    }
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external virtual override ensure(deadline) returns (uint[] memory amounts) {
        amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
        );
        _swap(amounts, path, to);
    }
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external virtual override ensure(deadline) returns (uint[] memory amounts) {
        amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
        );
        _swap(amounts, path, to);
    }
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        payable
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        IWETH(WETH).deposit{value: amounts[0]}();
        assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]));
        _swap(amounts, path, to);
    }
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
        );
        _swap(amounts, path, address(this));
        IWETH(WETH).withdraw(amounts[amounts.length - 1]);
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
        );
        _swap(amounts, path, address(this));
        IWETH(WETH).withdraw(amounts[amounts.length - 1]);
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        virtual
        override
        payable
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= msg.value, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
        IWETH(WETH).deposit{value: amounts[0]}();
        assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]));
        _swap(amounts, path, to);
        // refund dust eth, if any
        if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
    }

    // **** SWAP (supporting fee-on-transfer tokens) ****
    // requires the initial amount to have already been sent to the first pair
    function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual {
        for (uint i; i < path.length - 1; i++) {
            (address input, address output) = (path[i], path[i + 1]);
            (address token0,) = UniswapV2Library.sortTokens(input, output);
            IUniswapV2Pair pair = IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output));
            uint amountInput;
            uint amountOutput;
            { // scope to avoid stack too deep errors
            (uint reserve0, uint reserve1,) = pair.getReserves();
            (uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
            amountInput = IERC20i(input).balanceOf(address(pair)).sub(reserveInput);
            amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput);
            }
            (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
            address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
            pair.swap(amount0Out, amount1Out, to, new bytes(0));
        }
    }
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external virtual override ensure(deadline) {
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn
        );
        uint balanceBefore = IERC20i(path[path.length - 1]).balanceOf(to);
        _swapSupportingFeeOnTransferTokens(path, to);
        require(
            IERC20i(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
            'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'
        );
    }
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        virtual
        override
        payable
        ensure(deadline)
    {
        require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH');
        uint amountIn = msg.value;
        IWETH(WETH).deposit{value: amountIn}();
        assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn));
        uint balanceBefore = IERC20i(path[path.length - 1]).balanceOf(to);
        _swapSupportingFeeOnTransferTokens(path, to);
        require(
            IERC20i(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
            'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'
        );
    }
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        virtual
        override
        ensure(deadline)
    {
        require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH');
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn
        );
        _swapSupportingFeeOnTransferTokens(path, address(this));
        uint amountOut = IERC20i(WETH).balanceOf(address(this));
        require(amountOut >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        IWETH(WETH).withdraw(amountOut);
        TransferHelper.safeTransferETH(to, amountOut);
    }

    // **** LIBRARY FUNCTIONS ****
    function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual override returns (uint amountB) {
        return UniswapV2Library.quote(amountA, reserveA, reserveB);
    }

    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
        public
        pure
        virtual
        override
        returns (uint amountOut)
    {
        return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut);
    }

    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
        public
        pure
        virtual
        override
        returns (uint amountIn)
    {
        return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut);
    }

    function getAmountsOut(uint amountIn, address[] memory path)
        public
        view
        virtual
        override
        returns (uint[] memory amounts)
    {
        return UniswapV2Library.getAmountsOut(factory, amountIn, path);
    }

    function getAmountsIn(uint amountOut, address[] memory path)
        public
        view
        virtual
        override
        returns (uint[] memory amounts)
    {
        return UniswapV2Library.getAmountsIn(factory, amountOut, path);
    }
}

File 6 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 7 of 16 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 8 of 16 : IUniswapV2Router02.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

File 9 of 16 : IUniswapV2Factory.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}

File 10 of 16 : UniswapV2Library.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;

import '../interfaces/IUniswapV2Pair.sol';
import "./SafeMath.sol";

library UniswapV2Library {
    using SafeMath for uint;

    // returns sorted token addresses, used to handle return values from pairs sorted in this order
    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
        require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
    }

    // calculates the CREATE2 address for a pair without making any external calls
    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        pair = address(uint160(uint(keccak256(abi.encodePacked(
                hex'ff',
                factory,
                keccak256(abi.encodePacked(token0, token1)),
                hex'cdf2deca40a0bd56de8e3ce5c7df6727e5b1bf2ac96f283fa9c4b3e6b42ea9d2' // init code hash
            )))));
    }

    // fetches and sorts the reserves for a pair
    function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
        (address token0,) = sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
    function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
        require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
        require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        amountB = amountA.mul(reserveB) / reserveA;
    }

    // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
        require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        uint amountInWithFee = amountIn.mul(998);
        uint numerator = amountInWithFee.mul(reserveOut);
        uint denominator = reserveIn.mul(1000).add(amountInWithFee);
        amountOut = numerator / denominator;
    }

    // given an output amount of an asset and pair reserves, returns a required input amount of the other asset
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
        require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        uint numerator = reserveIn.mul(amountOut).mul(1000);
        uint denominator = reserveOut.sub(amountOut).mul(998);
        amountIn = (numerator / denominator).add(1);
    }

    // performs chained getAmountOut calculations on any number of pairs
    function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
        amounts = new uint[](path.length);
        amounts[0] = amountIn;
        for (uint i; i < path.length - 1; i++) {
            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
        }
    }

    // performs chained getAmountIn calculations on any number of pairs
    function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
        amounts = new uint[](path.length);
        amounts[amounts.length - 1] = amountOut;
        for (uint i = path.length - 1; i > 0; i--) {
            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
            amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
        }
    }
}

File 11 of 16 : TransferHelper.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.6.0;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}

File 12 of 16 : SafeMath.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8;

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)

library SafeMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x, 'ds-math-add-overflow');
    }

    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x, 'ds-math-sub-underflow');
    }

    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
    }
}

File 13 of 16 : IERC20.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;

interface IERC20i {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}

File 14 of 16 : IWETH.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;

interface IWETH {
    function deposit() external payable;
    function transfer(address to, uint value) external returns (bool);
    function withdraw(uint) external;
}

File 15 of 16 : IUniswapV2Router01.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external view returns (address);
    function WETH() external view returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

File 16 of 16 : IUniswapV2Pair.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 9999
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"mcv21","type":"address"},{"internalType":"address","name":"mcv22","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"MCV21","outputs":[{"internalType":"contract IMCV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MCV22","outputs":[{"internalType":"contract IMCV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"bool","name":"useMCV22","type":"bool"}],"name":"addLiquidityAndDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"bool","name":"useMCV22","type":"bool"}],"name":"addLiquidityETHAndDeposit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"useMCV22","type":"bool"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"bool","name":"useMCV22","type":"bool"}],"name":"reApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowed","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowedIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"supportsPermits","outputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040523480156200001157600080fd5b50604051620061553803806200615583398101604081905262000034916200008e565b6001600160a01b0393841660805291831660a052600180549184166001600160a01b031992831617905560028054929093169116179055620000eb565b80516001600160a01b03811681146200008957600080fd5b919050565b60008060008060808587031215620000a557600080fd5b620000b08562000071565b9350620000c06020860162000071565b9250620000d06040860162000071565b9150620000e06060860162000071565b905092959194509250565b60805160a051615eae620002a7600039600081816102630152818161057d01528181610791015281816107f9015281816108e501528181610b8e0152818161105e0152818161121f0152818161196d01528181611a9901528181611bb301528181611c7601528181611e1a01528181611ea80152818161219c015281816121f201528181612226015281816122d40152818161281601528181612900015281816129c101528181612a6e01528181612ae20152818161311e015281816134280152818161347e015281816134b2015281816135600152818161374d015281816138e501526139730152600081816106570152818161099101528181610ab901528181610c7401528181610cad01528181610e070152818161110a015281816111fd0152818161139701528181611d2101528181611eda01528181612055015281816121d0015281816124f901528181612b1401528181612dad015281816130cc015281816130fc015281816132f50152818161345c015281816137f8015281816139a501528181614368015281816143b80152818161467d0152818161480c01528181614bd001528181614c8b0152614d020152615eae6000f3fe6080604052600436106102535760003560e01c80639f07fa5111610138578063c2e3140a116100b0578063e1726ccd1161007f578063f305d71911610064578063f305d719146106f9578063f3995c671461070c578063fb3bdb411461071f57600080fd5b8063e1726ccd146106b9578063e8e33700146106d957600080fd5b8063c2e3140a14610632578063c45a015514610645578063d06ca61f14610679578063ded9382a1461069957600080fd5b8063ad615dec11610107578063b6f9de95116100ec578063b6f9de95146105df578063baa2abde146105f2578063c0e82a6e1461061257600080fd5b8063ad615dec1461059f578063af2979eb146105bf57600080fd5b80639f07fa5114610518578063a4a78f0c14610538578063ac9650d81461054b578063ad5c46481461056b57600080fd5b80635c11d795116101cb578063791ac9471161019a57806385f8c2591161017f57806385f8c259146104aa5780638803dbee146104ca5780639a106d14146104ea57600080fd5b8063791ac947146104775780637ff36ab51461049757600080fd5b80635c11d795146103df578063616710fe146103ff578063695f3f5d146104375780636abbed321461045757600080fd5b80632195995c116102225780634659a494116102075780634659a4941461038c5780634a25d94a1461039f5780635b0d5984146103bf57600080fd5b80632195995c1461034c57806338ed17391461036c57600080fd5b806302751cec14610297578063054d50d4146102d157806318cbafe5146102ff5780631f00ca741461032c57600080fd5b3661029257336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146102905761029061524e565b005b600080fd5b3480156102a357600080fd5b506102b76102b2366004615295565b610732565b604080519283526020830191909152015b60405180910390f35b3480156102dd57600080fd5b506102f16102ec3660046152f3565b610873565b6040519081526020016102c8565b34801561030b57600080fd5b5061031f61031a366004615364565b610888565b6040516102c891906153d7565b34801561033857600080fd5b5061031f61034736600461547b565b610c6d565b34801561035857600080fd5b506102b7610367366004615558565b610ca3565b34801561037857600080fd5b5061031f610387366004615364565b610daf565b61029061039a366004615602565b610f53565b3480156103ab57600080fd5b5061031f6103ba366004615364565b611001565b3480156103cb57600080fd5b506102f16103da36600461565c565b6111f5565b3480156103eb57600080fd5b506102906103fa366004615364565b611315565b34801561040b57600080fd5b5060025461041f906001600160a01b031681565b6040516001600160a01b0390911681526020016102c8565b34801561044357600080fd5b506102906104523660046156f2565b61162f565b34801561046357600080fd5b5061029061047236600461573c565b6117d1565b34801561048357600080fd5b50610290610492366004615364565b611912565b61031f6104a536600461576c565b611c21565b3480156104b657600080fd5b506102f16104c53660046152f3565b611ff0565b3480156104d657600080fd5b5061031f6104e5366004615364565b611ffd565b6104fd6104f83660046157d3565b612140565b604080519384526020840192909252908201526060016102c8565b34801561052457600080fd5b5061029061053336600461584f565b6124b5565b610290610546366004615602565b6125bc565b61055e6105593660046158e9565b612663565b6040516102c89190615983565b34801561057757600080fd5b5061041f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105ab57600080fd5b506102f16105ba3660046152f3565b6127b0565b3480156105cb57600080fd5b506102f16105da366004615295565b6127bd565b6102906105ed36600461576c565b61296e565b3480156105fe57600080fd5b506102b761060d366004615a03565b612d52565b34801561061e57600080fd5b5060015461041f906001600160a01b031681565b610290610640366004615602565b613028565b34801561065157600080fd5b5061041f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068557600080fd5b5061031f61069436600461547b565b6130c5565b3480156106a557600080fd5b506102b76106b436600461565c565b6130f2565b3480156106c557600080fd5b506102f16106d4366004615a75565b613218565b3480156106e557600080fd5b506104fd6106f4366004615a99565b613285565b6104fd610707366004615295565b6133cc565b61029061071a366004615602565b613688565b61031f61072d36600461576c565b6136f8565b600080824281101561078b5760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a2045585049524544000000000000000060448201526064015b60405180910390fd5b6107ba897f00000000000000000000000000000000000000000000000000000000000000008a8a8a308a612d52565b90935091506107ca898685613afd565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561084557600080fd5b505af1158015610859573d6000803e3d6000fd5b505050506108678583613c46565b50965096945050505050565b6000610880848484613d2e565b949350505050565b606081428110156108db5760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168686610912600182615b44565b81811061092157610921615b5b565b90506020020160208101906109369190615a75565b6001600160a01b03161461098c5760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b6109ea7f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613e7492505050565b91508682600184516109fc9190615b44565b81518110610a0c57610a0c615b5b565b60200260200101511015610a885760405162461bcd60e51b815260206004820152602b60248201527f556e69737761705632526f757465723a20494e53554646494349454e545f4f5560448201527f545055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b610b4d86866000818110610a9e57610a9e615b5b565b9050602002016020810190610ab39190615a75565b33610b2d7f00000000000000000000000000000000000000000000000000000000000000008a8a6000818110610aeb57610aeb615b5b565b9050602002016020810190610b009190615a75565b8b8b6001818110610b1357610b13615b5b565b9050602002016020810190610b289190615a75565b613fff565b85600081518110610b4057610b40615b5b565b6020026020010151614116565b610b8c82878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250614285915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d8360018551610bca9190615b44565b81518110610bda57610bda615b5b565b60200260200101516040518263ffffffff1660e01b8152600401610c0091815260200190565b600060405180830381600087803b158015610c1a57600080fd5b505af1158015610c2e573d6000803e3d6000fd5b50505050610c62848360018551610c459190615b44565b81518110610c5557610c55615b5b565b6020026020010151613c46565b509695505050505050565b6060610c9a7f00000000000000000000000000000000000000000000000000000000000000008484614487565b90505b92915050565b6000806000610cd37f00000000000000000000000000000000000000000000000000000000000000008f8f613fff565b9050600087610ce2578c610ce6565b6000195b6040517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101829052606481018b905260ff8916608482015260a4810188905260c481018790529091506001600160a01b0383169063d505accf9060e401600060405180830381600087803b158015610d6e57600080fd5b505af1158015610d82573d6000803e3d6000fd5b50505050610d958f8f8f8f8f8f8f612d52565b809450819550505050509b509b9950505050505050505050565b60608142811015610e025760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b610e607f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613e7492505050565b9150868260018451610e729190615b44565b81518110610e8257610e82615b5b565b60200260200101511015610efe5760405162461bcd60e51b815260206004820152602b60248201527f556e69737761705632526f757465723a20494e53554646494349454e545f4f5560448201527f545055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b610f1486866000818110610a9e57610a9e615b5b565b610c6282878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614285915050565b6040517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101869052606481018590526001608482015260ff841660a482015260c4810183905260e481018290526001600160a01b03871690638fcbaf0c90610104015b600060405180830381600087803b158015610fe157600080fd5b505af1158015610ff5573d6000803e3d6000fd5b50505050505050505050565b606081428110156110545760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016868661108b600182615b44565b81811061109a5761109a615b5b565b90506020020160208101906110af9190615a75565b6001600160a01b0316146111055760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b6111637f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061448792505050565b9150868260008151811061117957611179615b5b565b60200260200101511115610a885760405162461bcd60e51b815260206004820152602760248201527f556e69737761705632526f757465723a204558434553534956455f494e50555460448201527f5f414d4f554e54000000000000000000000000000000000000000000000000006064820152608401610782565b6000806112437f00000000000000000000000000000000000000000000000000000000000000008d7f0000000000000000000000000000000000000000000000000000000000000000613fff565b9050600086611252578b611256565b6000195b6040517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101829052606481018a905260ff8816608482015260a4810187905260c481018690529091506001600160a01b0383169063d505accf9060e401600060405180830381600087803b1580156112de57600080fd5b505af11580156112f2573d6000803e3d6000fd5b505050506113048d8d8d8d8d8d6127bd565b9d9c50505050505050505050505050565b80428110156113665760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6113f78585600081811061137c5761137c615b5b565b90506020020160208101906113919190615a75565b336113f17f0000000000000000000000000000000000000000000000000000000000000000898960008181106113c9576113c9615b5b565b90506020020160208101906113de9190615a75565b8a8a6001818110610b1357610b13615b5b565b8a614116565b60008585611406600182615b44565b81811061141557611415615b5b565b905060200201602081019061142a9190615a75565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa15801561148b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114af9190615b8a565b90506114ef868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250614608915050565b866115b1828888611501600182615b44565b81811061151057611510615b5b565b90506020020160208101906115259190615a75565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015291909116906370a08231906024015b602060405180830381865afa158015611587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ab9190615b8a565b906148e1565b10156116255760405162461bcd60e51b815260206004820152602b60248201527f556e69737761705632526f757465723a20494e53554646494349454e545f4f5560448201527f545055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b5050505050505050565b600081611647576001546001600160a01b0316611654565b6002546001600160a01b03165b6040517f78ed5d1f000000000000000000000000000000000000000000000000000000008152600481018790529091506000906001600160a01b038316906378ed5d1f906024016020604051808303816000875af11580156116ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116de9190615ba3565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790529091506001600160a01b038216906323b872dd906064016020604051808303816000875af115801561174d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117719190615bc0565b5061177c818361493f565b6040517f8dbdbe6d00000000000000000000000000000000000000000000000000000000815260048101879052602481018690526001600160a01b038581166044830152831690638dbdbe6d90606401610fc7565b6000816117e9576001546001600160a01b03166117f6565b6002546001600160a01b03165b6040517f78ed5d1f000000000000000000000000000000000000000000000000000000008152600481018590529091506001600160a01b038216906378ed5d1f906024016020604051808303816000875af1158015611859573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187d9190615ba3565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526000196024830152919091169063095ea7b3906044016020604051808303816000875af11580156118e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190c9190615bc0565b50505050565b80428110156119635760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016858561199a600182615b44565b8181106119a9576119a9615b5b565b90506020020160208101906119be9190615a75565b6001600160a01b031614611a145760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b611a2a8585600081811061137c5761137c615b5b565b611a68858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250614608915050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0c9190615b8a565b905086811015611b845760405162461bcd60e51b815260206004820152602b60248201527f556e69737761705632526f757465723a20494e53554646494349454e545f4f5560448201527f545055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611bff57600080fd5b505af1158015611c13573d6000803e3d6000fd5b505050506116258482613c46565b60608142811015611c745760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031686866000818110611cb157611cb1615b5b565b9050602002016020810190611cc69190615a75565b6001600160a01b031614611d1c5760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b611d7a7f000000000000000000000000000000000000000000000000000000000000000034888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613e7492505050565b9150868260018451611d8c9190615b44565b81518110611d9c57611d9c615b5b565b60200260200101511015611e185760405162461bcd60e51b815260206004820152602b60248201527f556e69737761705632526f757465723a20494e53554646494349454e545f4f5560448201527f545055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db083600081518110611e5a57611e5a615b5b565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e8d57600080fd5b505af1158015611ea1573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb611f0c7f0000000000000000000000000000000000000000000000000000000000000000898960008181106113c9576113c9615b5b565b84600081518110611f1f57611f1f615b5b565b60200260200101516040518363ffffffff1660e01b8152600401611f589291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015611f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9b9190615bc0565b611fa757611fa761524e565b611fe682878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614285915050565b5095945050505050565b6000610880848484614a49565b606081428110156120505760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6120ae7f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061448792505050565b915086826000815181106120c4576120c4615b5b565b60200260200101511115610efe5760405162461bcd60e51b815260206004820152602760248201527f556e69737761705632526f757465723a204558434553534956455f494e50555460448201527f5f414d4f554e54000000000000000000000000000000000000000000000000006064820152608401610782565b600080600085428110156121965760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6121c48c7f00000000000000000000000000000000000000000000000000000000000000008d348e8e614b89565b909450925060006122167f00000000000000000000000000000000000000000000000000000000000000008e7f0000000000000000000000000000000000000000000000000000000000000000613fff565b90506122248d338388614116565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561227f57600080fd5b505af1158015612293573d6000803e3d6000fd5b50506040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015612321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123459190615bc0565b6123515761235161524e565b6040517f6a6278420000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03821690636a627842906024016020604051808303816000875af11580156123b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d49190615b8a565b9250833411156123f1576123f1336123ec8634615b44565b613c46565b600086612409576001546001600160a01b0316612416565b6002546001600160a01b03165b9050612422828261493f565b6040517f8dbdbe6d00000000000000000000000000000000000000000000000000000000815260048101899052602481018590526001600160a01b038b81166044830152821690638dbdbe6d90606401600060405180830381600087803b15801561248c57600080fd5b505af11580156124a0573d6000803e3d6000fd5b50505050505050985098509895505050505050565b60006124c78b8b8b8b8b8b308b613285565b925050506000826124e3576001546001600160a01b03166124f0565b6002546001600160a01b03165b9050600061251f7f00000000000000000000000000000000000000000000000000000000000000008e8e613fff565b905061252b818361493f565b6040517f8dbdbe6d00000000000000000000000000000000000000000000000000000000815260048101869052602481018490526001600160a01b038881166044830152831690638dbdbe6d90606401600060405180830381600087803b15801561259557600080fd5b505af11580156125a9573d6000803e3d6000fd5b5050505050505050505050505050505050565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152600019906001600160a01b0388169063dd62ed3e90604401602060405180830381865afa158015612623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126479190615b8a565b101561265b5761265b868686868686610f53565b505050505050565b60608167ffffffffffffffff81111561267e5761267e61541b565b6040519080825280602002602001820160405280156126b157816020015b606081526020019060019003908161269c5790505b50905060005b828110156127a957600080308686858181106126d5576126d5615b5b565b90506020028101906126e79190615bdd565b6040516126f5929190615c42565b600060405180830381855af49150503d8060008114612730576040519150601f19603f3d011682016040523d82523d6000602084013e612735565b606091505b5091509150816127815760448151101561274e57600080fd5b600481019050808060200190518101906127689190615c52565b60405162461bcd60e51b81526004016107829190615ce6565b8084848151811061279457612794615b5b565b602090810291909101015250506001016126b7565b5092915050565b6000610880848484614e8b565b600081428110156128105760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b61283f887f00000000000000000000000000000000000000000000000000000000000000008989893089612d52565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529093506128d19150899086906001600160a01b038316906370a0823190602401602060405180830381865afa1580156128a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cc9190615b8a565b613afd565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b50505050610c628483613c46565b80428110156129bf5760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316858560008181106129fc576129fc615b5b565b9050602002016020810190612a119190615a75565b6001600160a01b031614612a675760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b60003490507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612ac757600080fd5b505af1158015612adb573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb612b467f0000000000000000000000000000000000000000000000000000000000000000898960008181106113c9576113c9615b5b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015612bab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bcf9190615bc0565b612bdb57612bdb61524e565b60008686612bea600182615b44565b818110612bf957612bf9615b5b565b9050602002016020810190612c0e9190615a75565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015291909116906370a0823190602401602060405180830381865afa158015612c6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c939190615b8a565b9050612cd3878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614608915050565b876115b1828989612ce5600182615b44565b818110612cf457612cf4615b5b565b9050602002016020810190612d099190615a75565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015291909116906370a082319060240161156a565b6000808242811015612da65760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6000612dd37f00000000000000000000000000000000000000000000000000000000000000008c8c613fff565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201819052604482018c90529192506323b872dd906064016020604051808303816000875af1158015612e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e669190615bc0565b506040517f89afcb440000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009182918416906389afcb449060240160408051808303816000875af1158015612ecc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef09190615cf9565b915091506000612f008e8e614f99565b509050806001600160a01b03168e6001600160a01b031614612f23578183612f26565b82825b90975095508a871015612fa15760405162461bcd60e51b815260206004820152602660248201527f556e69737761705632526f757465723a20494e53554646494349454e545f415f60448201527f414d4f554e5400000000000000000000000000000000000000000000000000006064820152608401610782565b898610156130175760405162461bcd60e51b815260206004820152602660248201527f556e69737761705632526f757465723a20494e53554646494349454e545f425f60448201527f414d4f554e5400000000000000000000000000000000000000000000000000006064820152608401610782565b505050505097509795505050505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015285906001600160a01b0388169063dd62ed3e90604401602060405180830381865afa15801561308d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b19190615b8a565b101561265b5761265b868686868686613688565b6060610c9a7f00000000000000000000000000000000000000000000000000000000000000008484613e74565b60008060006131427f00000000000000000000000000000000000000000000000000000000000000008e7f0000000000000000000000000000000000000000000000000000000000000000613fff565b9050600087613151578c613155565b6000195b6040517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101829052606481018b905260ff8916608482015260a4810188905260c481018790529091506001600160a01b0383169063d505accf9060e401600060405180830381600087803b1580156131dd57600080fd5b505af11580156131f1573d6000803e3d6000fd5b505050506132038e8e8e8e8e8e610732565b909f909e509c50505050505050505050505050565b6000816001600160a01b0316633644e5156040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613274575060408051601f3d908101601f1916820190925261327191810190615b8a565b60015b610c9d57506000919050565b919050565b600080600083428110156132db5760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6132e98c8c8c8c8c8c614b89565b9094509250600061331b7f00000000000000000000000000000000000000000000000000000000000000008e8e613fff565b90506133298d338388614116565b6133358c338387614116565b6040517f6a6278420000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af1158015613396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ba9190615b8a565b92505050985098509895505050505050565b600080600083428110156134225760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b6134508a7f00000000000000000000000000000000000000000000000000000000000000008b348c8c614b89565b909450925060006134a27f00000000000000000000000000000000000000000000000000000000000000008c7f0000000000000000000000000000000000000000000000000000000000000000613fff565b90506134b08b338388614116565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561350b57600080fd5b505af115801561351f573d6000803e3d6000fd5b50506040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018990527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af11580156135ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135d19190615bc0565b6135dd576135dd61524e565b6040517f6a6278420000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152821690636a627842906024016020604051808303816000875af115801561363e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136629190615b8a565b92508334111561367a5761367a336123ec8634615b44565b505096509650969350505050565b6040517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690526064810185905260ff8416608482015260a4810183905260c481018290526001600160a01b0387169063d505accf9060e401610fc7565b6060814281101561374b5760405162461bcd60e51b815260206004820152601860248201527f556e69737761705632526f757465723a204558504952454400000000000000006044820152606401610782565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168686600081811061378857613788615b5b565b905060200201602081019061379d9190615a75565b6001600160a01b0316146137f35760405162461bcd60e51b815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f504154480000006044820152606401610782565b6138517f00000000000000000000000000000000000000000000000000000000000000008888888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061448792505050565b9150348260008151811061386757613867615b5b565b602002602001015111156138e35760405162461bcd60e51b815260206004820152602760248201527f556e69737761705632526f757465723a204558434553534956455f494e50555460448201527f5f414d4f554e54000000000000000000000000000000000000000000000000006064820152608401610782565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08360008151811061392557613925615b5b565b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561395857600080fd5b505af115801561396c573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6139d77f0000000000000000000000000000000000000000000000000000000000000000898960008181106113c9576113c9615b5b565b846000815181106139ea576139ea615b5b565b60200260200101516040518363ffffffff1660e01b8152600401613a239291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015613a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a669190615bc0565b613a7257613a7261524e565b613ab182878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614285915050565b81600081518110613ac457613ac4615b5b565b6020026020010151341115611fe657611fe63383600081518110613aea57613aea615b5b565b6020026020010151346123ec9190615b44565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613b879190615d1d565b6000604051808303816000865af19150503d8060008114613bc4576040519150601f19603f3d011682016040523d82523d6000602084013e613bc9565b606091505b5091509150818015613bf3575080511580613bf3575080806020019051810190613bf39190615bc0565b613c3f5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610782565b5050505050565b604080516000808252602082019092526001600160a01b038416908390604051613c709190615d1d565b60006040518083038185875af1925050503d8060008114613cad576040519150601f19603f3d011682016040523d82523d6000602084013e613cb2565b606091505b5050905080613d295760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201527f4c454400000000000000000000000000000000000000000000000000000000006064820152608401610782565b505050565b6000808411613da55760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201527f4e5055545f414d4f554e540000000000000000000000000000000000000000006064820152608401610782565b600083118015613db55750600082115b613e275760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401610782565b6000613e35856103e66150a8565b90506000613e4382856150a8565b90506000613e5d83613e57886103e86150a8565b90615118565b9050613e698183615d39565b979650505050505050565b6060600282511015613ec85760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401610782565b815167ffffffffffffffff811115613ee257613ee261541b565b604051908082528060200260200182016040528015613f0b578160200160208202803683370190505b5090508281600081518110613f2257613f22615b5b565b60200260200101818152505060005b60018351613f3f9190615b44565b811015613ff757600080613f9287868581518110613f5f57613f5f615b5b565b602002602001015187866001613f759190615d74565b81518110613f8557613f85615b5b565b6020026020010151615176565b91509150613fba848481518110613fab57613fab615b5b565b60200260200101518383613d2e565b84613fc6856001615d74565b81518110613fd657613fd6615b5b565b60200260200101818152505050508080613fef90615d8c565b915050613f31565b509392505050565b600080600061400e8585614f99565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b16603482015291935091508690604801604051602081830303815290604052805190602001206040516020016140f49291907fff00000000000000000000000000000000000000000000000000000000000000815260609290921b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016600183015260158201527fcdf2deca40a0bd56de8e3ce5c7df6727e5b1bf2ac96f283fa9c4b3e6b42ea9d2603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916141a89190615d1d565b6000604051808303816000865af19150503d80600081146141e5576040519150601f19603f3d011682016040523d82523d6000602084013e6141ea565b606091505b50915091508180156142145750805115806142145750808060200190518101906142149190615bc0565b61265b5760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610782565b60005b600183516142969190615b44565b81101561190c576000808483815181106142b2576142b2615b5b565b6020026020010151858460016142c89190615d74565b815181106142d8576142d8615b5b565b60200260200101519150915060006142f08383614f99565b509050600087614301866001615d74565b8151811061431157614311615b5b565b60200260200101519050600080836001600160a01b0316866001600160a01b03161461433f57826000614343565b6000835b91509150600060028a516143579190615b44565b881061436357886143b1565b6143b17f0000000000000000000000000000000000000000000000000000000000000000878c6143948c6002615d74565b815181106143a4576143a4615b5b565b6020026020010151613fff565b90506143de7f00000000000000000000000000000000000000000000000000000000000000008888613fff565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f19166020018201604052801561441b576020820181803683370190505b506040518563ffffffff1660e01b815260040161443b9493929190615da6565b600060405180830381600087803b15801561445557600080fd5b505af1158015614469573d6000803e3d6000fd5b5050505050505050505050808061447f90615d8c565b915050614288565b60606002825110156144db5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401610782565b815167ffffffffffffffff8111156144f5576144f561541b565b60405190808252806020026020018201604052801561451e578160200160208202803683370190505b5090508281600183516145319190615b44565b8151811061454157614541615b5b565b60200260200101818152505060006001835161455d9190615b44565b90505b8015613ff7576000806145a38786614579600187615b44565b8151811061458957614589615b5b565b6020026020010151878681518110613f8557613f85615b5b565b915091506145cb8484815181106145bc576145bc615b5b565b60200260200101518383614a49565b846145d7600186615b44565b815181106145e7576145e7615b5b565b6020026020010181815250505050808061460090615dd4565b915050614560565b60005b600183516146199190615b44565b811015613d295760008084838151811061463557614635615b5b565b60200260200101518584600161464b9190615d74565b8151811061465b5761465b615b5b565b60200260200101519150915060006146738383614f99565b50905060006146a37f00000000000000000000000000000000000000000000000000000000000000008585613fff565b9050600080600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156146e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061470d9190615e09565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600080876001600160a01b03168a6001600160a01b031614614755578284614758565b83835b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038a811660048301529294509092506147ac918491908d16906370a082319060240161156a565b95506147b9868383613d2e565b945050505050600080856001600160a01b0316886001600160a01b0316146147e3578260006147e7565b6000835b91509150600060028c516147fb9190615b44565b8a10614807578a614838565b6148387f0000000000000000000000000000000000000000000000000000000000000000898e6143948e6002615d74565b604080516000815260208101918290527f022c0d9f000000000000000000000000000000000000000000000000000000009091529091506001600160a01b0387169063022c0d9f906148939086908690869060248101615da6565b600060405180830381600087803b1580156148ad57600080fd5b505af11580156148c1573d6000803e3d6000fd5b5050505050505050505050505080806148d990615d8c565b91505061460b565b6000826148ee8382615b44565b9150811115610c9d5760405162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f7700000000000000000000006044820152606401610782565b6001600160a01b038083166000908152602081815260408083209385168352929052205460ff16614a45576040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152600019602483015283169063095ea7b3906044016020604051808303816000875af11580156149d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149f79190615bc0565b506001600160a01b0380831660009081526020818152604080832093851683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b5050565b6000808411614ac05760405162461bcd60e51b815260206004820152602c60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4f60448201527f55545055545f414d4f554e5400000000000000000000000000000000000000006064820152608401610782565b600083118015614ad05750600082115b614b425760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401610782565b6000614b5a6103e8614b5486886150a8565b906150a8565b90506000614b6e6103e6614b5486896148e1565b9050614b7f6001613e578385615d39565b9695505050505050565b6040517fe6a439050000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528681166024830152600091829182917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a4390590604401602060405180830381865afa158015614c19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c3d9190615ba3565b6001600160a01b031603614cfa576040517fc9c653960000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015288811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063c9c65396906044016020604051808303816000875af1158015614cd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cf89190615ba3565b505b600080614d287f00000000000000000000000000000000000000000000000000000000000000008b8b615176565b91509150816000148015614d3a575080155b15614d4a57879350869250614e7e565b6000614d57898484614e8b565b9050878111614de15785811015614dd65760405162461bcd60e51b815260206004820152602660248201527f556e69737761705632526f757465723a20494e53554646494349454e545f425f60448201527f414d4f554e5400000000000000000000000000000000000000000000000000006064820152608401610782565b889450925082614e7c565b6000614dee898486614e8b565b905089811115614e0057614e0061524e565b87811015614e765760405162461bcd60e51b815260206004820152602660248201527f556e69737761705632526f757465723a20494e53554646494349454e545f415f60448201527f414d4f554e5400000000000000000000000000000000000000000000000000006064820152608401610782565b94508793505b505b5050965096945050505050565b6000808411614f025760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4160448201527f4d4f554e540000000000000000000000000000000000000000000000000000006064820152608401610782565b600083118015614f125750600082115b614f845760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401610782565b82614f8f85846150a8565b6108809190615d39565b600080826001600160a01b0316846001600160a01b0316036150235760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f4144445260448201527f45535345530000000000000000000000000000000000000000000000000000006064820152608401610782565b826001600160a01b0316846001600160a01b031610615043578284615046565b83835b90925090506001600160a01b0382166150a15760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401610782565b9250929050565b60008115806150cc575082826150be8183615e59565b92506150ca9083615d39565b145b610c9d5760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152606401610782565b6000826151258382615d74565b9150811015610c9d5760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152606401610782565b60008060006151858585614f99565b509050600080615196888888613fff565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156151d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151f79190615e09565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150826001600160a01b0316876001600160a01b03161461523c57808261523f565b81815b90999098509650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6001600160a01b038116811461529257600080fd5b50565b60008060008060008060c087890312156152ae57600080fd5b86356152b98161527d565b955060208701359450604087013593506060870135925060808701356152de8161527d565b8092505060a087013590509295509295509295565b60008060006060848603121561530857600080fd5b505081359360208301359350604090920135919050565b60008083601f84011261533157600080fd5b50813567ffffffffffffffff81111561534957600080fd5b6020830191508360208260051b85010111156150a157600080fd5b60008060008060008060a0878903121561537d57600080fd5b8635955060208701359450604087013567ffffffffffffffff8111156153a257600080fd5b6153ae89828a0161531f565b90955093505060608701356153c28161527d565b80925050608087013590509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561540f578351835292840192918401916001016153f3565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156154735761547361541b565b604052919050565b6000806040838503121561548e57600080fd5b8235915060208084013567ffffffffffffffff808211156154ae57600080fd5b818601915086601f8301126154c257600080fd5b8135818111156154d4576154d461541b565b8060051b91506154e584830161544a565b81815291830184019184810190898411156154ff57600080fd5b938501935b8385101561552957843592506155198361527d565b8282529385019390850190615504565b8096505050505050509250929050565b801515811461529257600080fd5b803560ff8116811461328057600080fd5b60008060008060008060008060008060006101608c8e03121561557a57600080fd5b8b356155858161527d565b9a5060208c01356155958161527d565b995060408c0135985060608c0135975060808c0135965060a08c01356155ba8161527d565b955060c08c0135945060e08c01356155d181615539565b93506155e06101008d01615547565b92506101208c013591506101408c013590509295989b509295989b9093969950565b60008060008060008060c0878903121561561b57600080fd5b86356156268161527d565b9550602087013594506040870135935061564260608801615547565b92506080870135915060a087013590509295509295509295565b6000806000806000806000806000806101408b8d03121561567c57600080fd5b8a356156878161527d565b995060208b0135985060408b0135975060608b0135965060808b01356156ac8161527d565b955060a08b0135945060c08b01356156c381615539565b93506156d160e08c01615547565b92506101008b013591506101208b013590509295989b9194979a5092959850565b6000806000806080858703121561570857600080fd5b843593506020850135925060408501356157218161527d565b9150606085013561573181615539565b939692955090935050565b6000806040838503121561574f57600080fd5b82359150602083013561576181615539565b809150509250929050565b60008060008060006080868803121561578457600080fd5b85359450602086013567ffffffffffffffff8111156157a257600080fd5b6157ae8882890161531f565b90955093505060408601356157c28161527d565b949793965091946060013592915050565b600080600080600080600080610100898b0312156157f057600080fd5b88356157fb8161527d565b975060208901359650604089013595506060890135945060808901356158208161527d565b935060a0890135925060c0890135915060e089013561583e81615539565b809150509295985092959890939650565b6000806000806000806000806000806101408b8d03121561586f57600080fd5b8a3561587a8161527d565b995060208b013561588a8161527d565b985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b01356158b68161527d565b935060e08b013592506101008b013591506101208b01356158d681615539565b809150509295989b9194979a5092959850565b600080602083850312156158fc57600080fd5b823567ffffffffffffffff81111561591357600080fd5b61591f8582860161531f565b90969095509350505050565b60005b8381101561594657818101518382015260200161592e565b8381111561190c5750506000910152565b6000815180845261596f81602086016020860161592b565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156159f6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526159e4858351615957565b945092850192908501906001016159aa565b5092979650505050505050565b600080600080600080600060e0888a031215615a1e57600080fd5b8735615a298161527d565b96506020880135615a398161527d565b955060408801359450606088013593506080880135925060a0880135615a5e8161527d565b8092505060c0880135905092959891949750929550565b600060208284031215615a8757600080fd5b8135615a928161527d565b9392505050565b600080600080600080600080610100898b031215615ab657600080fd5b8835615ac18161527d565b97506020890135615ad18161527d565b965060408901359550606089013594506080890135935060a0890135925060c0890135615afd8161527d565b8092505060e089013590509295985092959890939650565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015615b5657615b56615b15565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215615b9c57600080fd5b5051919050565b600060208284031215615bb557600080fd5b8151615a928161527d565b600060208284031215615bd257600080fd5b8151615a9281615539565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c1257600080fd5b83018035915067ffffffffffffffff821115615c2d57600080fd5b6020019150368190038213156150a157600080fd5b8183823760009101908152919050565b600060208284031215615c6457600080fd5b815167ffffffffffffffff80821115615c7c57600080fd5b818401915084601f830112615c9057600080fd5b815181811115615ca257615ca261541b565b615cb56020601f19601f8401160161544a565b9150808252856020828501011115615ccc57600080fd5b615cdd81602084016020860161592b565b50949350505050565b602081526000610c9a6020830184615957565b60008060408385031215615d0c57600080fd5b505080516020909101519092909150565b60008251615d2f81846020870161592b565b9190910192915050565b600082615d6f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008219821115615d8757615d87615b15565b500190565b60006000198203615d9f57615d9f615b15565b5060010190565b8481528360208201526001600160a01b0383166040820152608060608201526000614b7f6080830184615957565b600081615de357615de3615b15565b506000190190565b80516dffffffffffffffffffffffffffff8116811461328057600080fd5b600080600060608486031215615e1e57600080fd5b615e2784615deb565b9250615e3560208501615deb565b9150604084015163ffffffff81168114615e4e57600080fd5b809150509250925092565b6000816000190483118215151615615e7357615e73615b15565b50029056fea2646970667358221220cdaed953eaba66d25ad89d828dd4d887b3c9b4a6043028f108c85fed04ba8ef764736f6c634300080d0033000000000000000000000000152ee697f2e276fa89e96742e9bb9ab1f2e61be300000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c8300000000000000000000000018b4f774fdc7bf685daeef66c2990b1ddd9ea6ad0000000000000000000000009c9c920e51778c4abf727b8bb223e78132f00aa4

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000152ee697f2e276fa89e96742e9bb9ab1f2e61be300000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c8300000000000000000000000018b4f774fdc7bf685daeef66c2990b1ddd9ea6ad0000000000000000000000009c9c920e51778c4abf727b8bb223e78132f00aa4

-----Decoded View---------------
Arg [0] : _factory (address): 0x152ee697f2e276fa89e96742e9bb9ab1f2e61be3
Arg [1] : _WETH (address): 0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83
Arg [2] : mcv21 (address): 0x18b4f774fdc7bf685daeef66c2990b1ddd9ea6ad
Arg [3] : mcv22 (address): 0x9c9c920e51778c4abf727b8bb223e78132f00aa4

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000152ee697f2e276fa89e96742e9bb9ab1f2e61be3
Arg [1] : 00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83
Arg [2] : 00000000000000000000000018b4f774fdc7bf685daeef66c2990b1ddd9ea6ad
Arg [3] : 0000000000000000000000009c9c920e51778c4abf727b8bb223e78132f00aa4


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Validator ID :
0 FTM

Amount Staked
0

Amount Delegated
0

Staking Total
0

Staking Start Epoch
0

Staking Start Time
0

Proof of Importance
0

Origination Score
0

Validation Score
0

Active
0

Online
0

Downtime
0 s
Address Amount claimed Rewards Created On Epoch Created On
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.