Contract 0x31f63a33141ffee63d4b26755430a390acdd8a4d 6

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x026b664f3f9d538b3973e45602ac1faaa8ae8cf0ab43616cbb31d41e5dc23555Multicall545898512023-01-28 11:03:4917 secs ago0xcc93f2ebe4b9c4bd0fa5e579c55afc19e660e30a IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.006278014087
0xb88aa2dc926c1852f71a407d9ad1c2bbe243e7bbb6231a32647c39f3f41dfc6fSwap Tokens For ...545898482023-01-28 11:03:3234 secs ago0xe8ae9edab43fe2ba66bea77e49755a731873fdb7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.007715574
0xe5b86026f01685c04a3649d9261dbcab565ff201fc4c47b2b538a5e73ffa76deMulticall545898472023-01-28 11:03:3234 secs ago0x7f48247ab597187b0fc4c4d24003b9a9b8435c37 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d67.022395365383578 FTM0.012839840349
0x21a96b1d6d9e47d4eefd5f12d85ac77889eaf9bb8800252008a05d4b8f2776c0Multicall545898382023-01-28 11:03:051 min ago0x323f725a66831a6028f30075e94c9b33e7b7dad7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.012810792224
0xb637ed837d49ffb0a06d68e7e90992946b56802aabe80739addf2e90484335efMulticall545898382023-01-28 11:03:051 min ago0x38274785d72ed15af7c40685e4a54a60bbb14668 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.01004008
0x5359936d867fe737aba6da978ebed3b3069ea4316dabfc50c85ad19f56228af7Multicall545898302023-01-28 11:02:501 min ago0x64ef8f3432bb9da6a5e09abe9377b216ed2e7bb8 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.005658045647
0x5e4119e42d49201b7fe0b100134e9f4964561a622268c94e8a74b06a70c170afSwap Exact Token...545898242023-01-28 11:02:411 min ago0xe8ae9edab43fe2ba66bea77e49755a731873fdb7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.018103755
0xd833ab2188121b6d49c02f31d2fad3354383289868ad913f5282bcddd91b0fc6Multicall545898162023-01-28 11:02:131 min ago0x9952bcc072e132e9486c646d86a08798dccee2df IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.005231027162
0x0a1d5810db2e539d346a522437abe97c5194e799e8cc659ad9b13b7769503b3fMulticall545898122023-01-28 11:02:022 mins ago0xa1f290af8d29024fd64c3fd6cfcc545d2255deb1 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d8.6 FTM0.004936196405
0x71582d47da859cb1f6f57f7742a1a45b2e0f0a8e660e4eb10b77fa3e2f26849aMulticall545898102023-01-28 11:01:542 mins ago0x7f48247ab597187b0fc4c4d24003b9a9b8435c37 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d80 FTM0.005109119284
0x36d3d21b2b80986a88230c9c7c9f89caff029b211b6ae3a5aff7109e2aaa077aMulticall545898012023-01-28 11:01:352 mins ago0x3c176dea5d9cd64b386af8bd0ee971aac250e4a2 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d5,850 FTM0.00596703148
0xdca4a2f0e2789dd71e2bf05e39ad873b53543ab300aa75e43a1ab33dbdd447a7Multicall545897992023-01-28 11:01:322 mins ago0x982458536d6b3c00cb6e9dd0a8d0dc9ed0387855 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.005967785274
0x680c6f4916ce8a894008e41f436ec0d088f3fd9edcaf302e5793f815b3b5c649Multicall545897952023-01-28 11:01:202 mins ago0xcde4283288e071eb9a88bb26077a8bd3abf4d2ef IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.01054962
0x3888d9b70ed0676256ed01274dd0efc1bcf395e734279030dd6c2b3c3f93ca5dSwap Exact Token...545897902023-01-28 11:01:003 mins ago0x07e61058fe2f814801ce2fb996c94cd845da8c7a IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.020402096
0xceadb9c77120a668d65b45e3e84347e2a2121bae042605ad21a4b970f692434bMulticall545897832023-01-28 11:00:393 mins ago0xd3b60a9c344955059bcd02a76e3f590646f137f8 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.007713305412
0xb1d023d24436678d805e95542614a0d812d02e0fccf939afd46a85e4bd55b80eMulticall545897782023-01-28 11:00:233 mins ago0xbe0d56356169cc4e4c9c683b049a233c5c984b20 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d56.105065187707735 FTM0.013869673069
0x1aa781e4cd25fe36eb0749941da4d5241c5986fcbbd4148047d39cf5f97858c0Multicall545897752023-01-28 11:00:103 mins ago0x6bf23777cf99cad7d6f5a01f93cf1f37a8e6dfcd IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d201.812044377791272 FTM0.009096546021
0x906d5d8a5d38f6c6a09ca4a68dcafc5b400eb588e85953a7321dda6af3b64120Swap Exact Token...545897732023-01-28 11:00:054 mins ago0x9c693fcc7b48a50ada580cc06be99b977994a2e8 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.008136218
0xd7e0829e47367cfea2ff163a472b39dcf0d77e4fd0a685ac62d5aa372c7dfbd3Multicall545897732023-01-28 11:00:054 mins ago0x0e3ac76d01824931e76b6d93d3ba96b80e4088e3 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.014998013979
0x9ada0e81c7d880d5527d640fe195bcab6cbddfd3fe97c0fa4933ca257536d639Swap Exact Token...545897732023-01-28 11:00:054 mins ago0xe8ae9edab43fe2ba66bea77e49755a731873fdb7 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.0088311
0x85500f97e9409971ac850456a08e0bd2e2ef4470c10671b0a17a817364235d64Multicall545897692023-01-28 10:59:434 mins ago0x9952bcc072e132e9486c646d86a08798dccee2df IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.009990100368
0xb960f8760448a05d5e8411c5a44fb2e4ac1ce1e6f0b7a6d6c37447b7d1e99428Multicall545897692023-01-28 10:59:434 mins ago0xfdc5b2f481f8c94b92440f7de5052db41820297d IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d109 FTM0.030460615506
0xde81452c6d96d2281ae19f8df1121362b134c8deb5bfbd5553c14825854305dbSwap Exact Token...545897602023-01-28 10:59:264 mins ago0x07e61058fe2f814801ce2fb996c94cd845da8c7a IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.016340976
0xf2287022f9042b45a07b567bdab2fa31b16c4ffc4278cef9eeaad0a2e31b68d9Multicall545897542023-01-28 10:59:094 mins ago0x3c176dea5d9cd64b386af8bd0ee971aac250e4a2 IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.006130361388
0xf8c3e13767a47cb3a79e914b61de522210f53ae15bc48d64e0638ec3966559feMulticall545897422023-01-28 10:58:355 mins ago0x610c95168682e5bafc2d305094810f7d006e258a IN  0x31f63a33141ffee63d4b26755430a390acdd8a4d0 FTM0.005345394994
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xe5b86026f01685c04a3649d9261dbcab565ff201fc4c47b2b538a5e73ffa76de545898472023-01-28 11:03:3234 secs ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token67.022395365383578988 FTM
0x5359936d867fe737aba6da978ebed3b3069ea4316dabfc50c85ad19f56228af7545898302023-01-28 11:02:501 min ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x64ef8f3432bb9da6a5e09abe9377b216ed2e7bb822.665203624360590746 FTM
0x5359936d867fe737aba6da978ebed3b3069ea4316dabfc50c85ad19f56228af7545898302023-01-28 11:02:501 min ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d22.665203624360590746 FTM
0xd833ab2188121b6d49c02f31d2fad3354383289868ad913f5282bcddd91b0fc6545898162023-01-28 11:02:131 min ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x9952bcc072e132e9486c646d86a08798dccee2df2,496.817755440655336516 FTM
0xd833ab2188121b6d49c02f31d2fad3354383289868ad913f5282bcddd91b0fc6545898162023-01-28 11:02:131 min ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d2,496.817755440655336516 FTM
0x0a1d5810db2e539d346a522437abe97c5194e799e8cc659ad9b13b7769503b3f545898122023-01-28 11:02:022 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token8.6 FTM
0x71582d47da859cb1f6f57f7742a1a45b2e0f0a8e660e4eb10b77fa3e2f26849a545898102023-01-28 11:01:542 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token80 FTM
0x36d3d21b2b80986a88230c9c7c9f89caff029b211b6ae3a5aff7109e2aaa077a545898012023-01-28 11:01:352 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token5,850 FTM
0xb1d023d24436678d805e95542614a0d812d02e0fccf939afd46a85e4bd55b80e545897782023-01-28 11:00:233 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token56.105065187707735088 FTM
0x1aa781e4cd25fe36eb0749941da4d5241c5986fcbbd4148047d39cf5f97858c0545897752023-01-28 11:00:103 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x6bf23777cf99cad7d6f5a01f93cf1f37a8e6dfcd1 wei
0x1aa781e4cd25fe36eb0749941da4d5241c5986fcbbd4148047d39cf5f97858c0545897752023-01-28 11:00:103 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token201.812044377791272051 FTM
0x85500f97e9409971ac850456a08e0bd2e2ef4470c10671b0a17a817364235d64545897692023-01-28 10:59:434 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x9952bcc072e132e9486c646d86a08798dccee2df2,504.643501317704772279 FTM
0x85500f97e9409971ac850456a08e0bd2e2ef4470c10671b0a17a817364235d64545897692023-01-28 10:59:434 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d2,504.643501317704772279 FTM
0xb960f8760448a05d5e8411c5a44fb2e4ac1ce1e6f0b7a6d6c37447b7d1e99428545897692023-01-28 10:59:434 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token109 FTM
0x33b986ecc7e5d4184db95f4ca7fecd6542f88093ed4dc512c608a5e7d0be7436545897342023-01-28 10:58:095 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xb803bbee7772798b65f67ec2fc775fdf03354aad84.56963071621897149 FTM
0x33b986ecc7e5d4184db95f4ca7fecd6542f88093ed4dc512c608a5e7d0be7436545897342023-01-28 10:58:095 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d84.56963071621897149 FTM
0x0d1a2de52adfbd688a37117ff050b1c637a4cd2315cb94696bd03710f45e0df4545897292023-01-28 10:57:556 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token70 FTM
0x7513e3f25d184ae87d79cb0587367317629bb4119dc5804ca760d63f96899994545897122023-01-28 10:57:136 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token202.817675775927398907 FTM
0xfcc78dfc5bb506fa00d41d5a3b681eb212dc24fabb0fe734a7cf8765a1e99cc5545897052023-01-28 10:57:007 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token5,000 FTM
0x2a628fc876cfd8753bceaca948d9c316c2912236434657901957b700d643de50545896982023-01-28 10:56:447 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xb7ed47bf3c47e50ef40ce76f8b0845430b9c851337.015820706943429007 FTM
0x2a628fc876cfd8753bceaca948d9c316c2912236434657901957b700d643de50545896982023-01-28 10:56:447 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d37.015820706943429007 FTM
0x15d1b784881ec3c3e3988d2379fd2beee4abdd3c3a380b8ac08cf2ff499dd08f545896452023-01-28 10:54:329 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d Fantom Finance: Wrapped Fantom Token1,040 FTM
0xb81d4990777b687a06a3e97be83cf30c4e5dd835e9fef0b1320418e6846eb0c1545896222023-01-28 10:53:4410 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0xef053ac843ed5945e31882d69528dc3f299735ff190.191588008545531953 FTM
0xb81d4990777b687a06a3e97be83cf30c4e5dd835e9fef0b1320418e6846eb0c1545896222023-01-28 10:53:4410 mins ago Fantom Finance: Wrapped Fantom Token 0x31f63a33141ffee63d4b26755430a390acdd8a4d190.191588008545531953 FTM
0xbe27d8a7fb971a3c9ad9efe08b5d368e2442b2c53c3bfd48d9cea9b2121ee162545896022023-01-28 10:52:5711 mins ago 0x31f63a33141ffee63d4b26755430a390acdd8a4d0x76d6696ab5c75b6edda2ad3048d63138cbc0399f1,057.468619861547246036 FTM
[ Download CSV Export 
Loading

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.