Contract 0x283e62cfe14b352db8e30a9575481dcbf589ad98

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x77d5c936d05146e73afa0f44000dbdcf6279e77ed57e11cf96e6bd15327a6458Leverage199085582021-10-24 1:18:4911 secs ago0xd131f1bcdd547e067af447dd3c36c99d6be9fdeb IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.1234578878
0xd2941ca96136e8a6b971af87619bb326506d4d622d84b0037f9bc97ab7626696Mint Collateral199085332021-10-24 1:18:2238 secs ago0xd131f1bcdd547e067af447dd3c36c99d6be9fdeb IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.036509523068
0xfce4d98aa76d2dd090b3d7f6ae8caa3dae1062227ff852cdb09feca176ed60a0Leverage199085172021-10-24 1:18:0852 secs ago0x64c10f2aa590cb7fdec0c99cead3bfd1fdd979d8 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.09985256844
0x339d1b32ad19008aa747dba84047ec288ff45ddece46ae88b0ba4964dfe9815aDeleverage199085172021-10-24 1:18:0852 secs ago0x4c1565939c8fd702952f70470b88f5f693d6b9e4 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.1123141545
0xf36c9f577e83f226a7cda201b58113fef544efbcf960c3ee2e716cb88767bfb5Mint Collateral199084392021-10-24 1:16:562 mins ago0x864978ea5ef6fc7f92b00ca0368b04d1fa9cbd63 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.01216227993
0xd94b0460934d959448805479ae394ca030cf875fef06787b77a8a7cb09902d33Mint199084332021-10-24 1:16:512 mins ago0x57fbf388a5ebe5c52b6dbc996c84e525a67fa104 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.021963552356
0xb02c816089a9627eff164ba90e2254c9c5fcd65ef84357dd52b9b8d576723bf2Mint ETH199083942021-10-24 1:16:202 mins ago0x0b78decc589b4f0812941acaa48e4c990bd48d62 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad9820 FTM0.023499043713
0x6e748d18c3c8a7d7702694493876ced6b0e495ffe9069554190d72b7e9603b9aLeverage199083902021-10-24 1:16:172 mins ago0x3f070ccba62b8bd4929e3850f6d8482753944e17 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.115597657283
0xe82bb4bde79b680aa50317c2260e52f6bdc95e3e92bef6e257a4b0224c204c76Mint Collateral199082782021-10-24 1:14:414 mins ago0x3f070ccba62b8bd4929e3850f6d8482753944e17 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.042390046674
0x0d376949bdcb5e27d1bf909dacffcc9896e057796d8b6547fd6b2affeda51769Mint199082712021-10-24 1:14:364 mins ago0x25c08c92496a126391402c8f3b61c44b48f59e67 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.024370345451
0xd4db30839a1a6796cdd2e49f7996fee1593e0c05610632e92b11db755a05f6daMint199082632021-10-24 1:14:274 mins ago0xfa53f48b0bfdc115f8eda45868d8e6a7a1c1f267 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.02442859852
0xf80f70f063a7746a3596ad9be65f896eeab741348f93770f72ce283389fe1b84Mint199082592021-10-24 1:14:244 mins ago0xdc06976a16c24e74dec7cbb55867f208538bf47a IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.02219882006
0x20db067f13224d3331b5dd0fd1101661be7576fe95eb03238eef4f8c1e220a6aBorrow199081682021-10-24 1:13:095 mins ago0x864978ea5ef6fc7f92b00ca0368b04d1fa9cbd63 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.032508838254
0x8bf5048e4eaa8c8911432811fcb7f1d82ee560eb93595951007ea0e2427c257aRedeem199081322021-10-24 1:12:396 mins ago0xafbbde635277f70ab46d13f79ac6a433e7eb2e4b IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.02253183287
0xf720d62c9b85f0b2fc61df051a2722d75c4a0f01fa184e11309b866b5dc20bd1Mint Collateral199081072021-10-24 1:12:206 mins ago0x64c10f2aa590cb7fdec0c99cead3bfd1fdd979d8 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.035128472208
0xe8645e11cbb015a74846b4f0f2e26fc07a2baf241f6287d4b81fc8b265fd9e5bRedeem199080422021-10-24 1:11:177 mins ago0x0fab40a6e43ee85dda2052642330f75c6d86f7a0 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.024454563271
0xedcf7bc3d9b1853f62c03e951b83f4a9d7a258b0c1d04700734063a191046d03Mint199079632021-10-24 1:10:028 mins ago0xbfe24b4d8b1e421ca8794f6416946db505d6dbd7 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.019150294721
0x8c86de37425f01ecc60783cd53b9bd61ffc93431a9ab294423f4977368c36d0eDeleverage199079382021-10-24 1:09:349 mins ago0x70b7d07e5112f48d84c42488ceb29c9058ca8037 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.153902295625
0x48899f577220ac816cd6d1984e7b92520061771fc3b47945ec28bbe51c4a0f1dLeverage199079342021-10-24 1:09:319 mins ago0x864978ea5ef6fc7f92b00ca0368b04d1fa9cbd63 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.084091303769
0x44273491b366c8f31dc7e754720c37967fd23779986db30e40b3130b33444f4eRepay199079212021-10-24 1:09:229 mins ago0xbfe24b4d8b1e421ca8794f6416946db505d6dbd7 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.025332291872
0xda649beab89ac85882349d344f8ae81aa09afd26bfc8ec59d4d285684a735608Mint199078212021-10-24 1:07:5811 mins ago0x31f28f27d653dd4fcc9ca3b29eb17993328cbc15 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.018679099511
0x4b1e7efc4bb08f08f44ea7ef67c943da67638625d6e522a9790dd826c7650330Mint ETH199078072021-10-24 1:07:4611 mins ago0x75c8e2dd57927eb0373e8e201ebf582406adcf45 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad98875 FTM0.02005441457
0x955d685232ae9b44e973af32f4429e46e9b932ec499e3fb20f9b8b3f16c62fe1Mint Collateral199077862021-10-24 1:07:2711 mins ago0x864978ea5ef6fc7f92b00ca0368b04d1fa9cbd63 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.011560845972
0xd7f8000471e276bd04b05685ea602bf7430620a4ed08135780ae5716be2ca966Mint199077732021-10-24 1:07:1611 mins ago0x17e071372ba2c7ec0d21030e27db41e9ab74b2eb IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.018379157262
0xbd124a1552be9f13f633d2a4eb8b5a4b9ed5a477dd5d2df94fc966bb9d19861aMint199077712021-10-24 1:07:1411 mins ago0x8532abc7fef73951555cdb4889868b54eb64c390 IN  0x283e62cfe14b352db8e30a9575481dcbf589ad980 FTM0.02028379465
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xb02c816089a9627eff164ba90e2254c9c5fcd65ef84357dd52b9b8d576723bf2199083942021-10-24 1:16:202 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token20 FTM
0xb02c816089a9627eff164ba90e2254c9c5fcd65ef84357dd52b9b8d576723bf2199083942021-10-24 1:16:202 mins ago 0x0b78decc589b4f0812941acaa48e4c990bd48d62 0x283e62cfe14b352db8e30a9575481dcbf589ad9820 FTM
0x8c86de37425f01ecc60783cd53b9bd61ffc93431a9ab294423f4977368c36d0e199079382021-10-24 1:09:349 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980x70b7d07e5112f48d84c42488ceb29c9058ca8037363.155277034423198116 FTM
0x8c86de37425f01ecc60783cd53b9bd61ffc93431a9ab294423f4977368c36d0e199079382021-10-24 1:09:349 mins ago Fantom Finance: Wrapped Fantom Token 0x283e62cfe14b352db8e30a9575481dcbf589ad98363.155277034423198116 FTM
0x4b1e7efc4bb08f08f44ea7ef67c943da67638625d6e522a9790dd826c7650330199078072021-10-24 1:07:4611 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token875 FTM
0x4b1e7efc4bb08f08f44ea7ef67c943da67638625d6e522a9790dd826c7650330199078072021-10-24 1:07:4611 mins ago 0x75c8e2dd57927eb0373e8e201ebf582406adcf45 0x283e62cfe14b352db8e30a9575481dcbf589ad98875 FTM
0x817041cbfeb908a1f303a88b143b8604133ba7929d4c3cd962863d7f264aa8de199077482021-10-24 1:06:5312 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token1,979 FTM
0x817041cbfeb908a1f303a88b143b8604133ba7929d4c3cd962863d7f264aa8de199077482021-10-24 1:06:5312 mins ago 0xbaac64bc47f5a60793e8e53731c419f287a31852 0x283e62cfe14b352db8e30a9575481dcbf589ad981,979 FTM
0xc75f838418bff0628c7c29e4e65499fa7c84b4627a84cd41cc34a79d8f62a056199077302021-10-24 1:06:1712 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token913 FTM
0xc75f838418bff0628c7c29e4e65499fa7c84b4627a84cd41cc34a79d8f62a056199077302021-10-24 1:06:1712 mins ago 0xa51b0d114792e0120a32db0bd9a9837dd389e6cd 0x283e62cfe14b352db8e30a9575481dcbf589ad98913 FTM
0xb33b27ae4183f15b1cbf2e0cb747ab585e1c0991b63b5fdd1e83f1e8ba556cb8199076532021-10-24 1:05:0713 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980xbaac64bc47f5a60793e8e53731c419f287a318521,979.000421786770942847 FTM
0xb33b27ae4183f15b1cbf2e0cb747ab585e1c0991b63b5fdd1e83f1e8ba556cb8199076532021-10-24 1:05:0713 mins ago Fantom Finance: Wrapped Fantom Token 0x283e62cfe14b352db8e30a9575481dcbf589ad981,979.000421786770942847 FTM
0xbd26d990fa3ca8fc10c6b42750b3b1675ef7f8f34a58946b16fc4ebef04a7630199076232021-10-24 1:04:3614 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token50 FTM
0xbd26d990fa3ca8fc10c6b42750b3b1675ef7f8f34a58946b16fc4ebef04a7630199076232021-10-24 1:04:3614 mins ago 0x76c45f08125dafc30f35ccc0aa784156551f19b4 0x283e62cfe14b352db8e30a9575481dcbf589ad9850 FTM
0x7724f536e3f90bd8a2fe867731f1e489e8f37e4116b525c05e3ac33cb75ffff9199075732021-10-24 1:03:5615 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980xa51b0d114792e0120a32db0bd9a9837dd389e6cd900.103146536875162575 FTM
0x7724f536e3f90bd8a2fe867731f1e489e8f37e4116b525c05e3ac33cb75ffff9199075732021-10-24 1:03:5615 mins ago Fantom Finance: Wrapped Fantom Token 0x283e62cfe14b352db8e30a9575481dcbf589ad98900.103146536875162575 FTM
0xf2d2dca3416f1e59d1ba03e33220c75b101cf761c5e7729b6db70eb43072e8dc199075652021-10-24 1:03:4815 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980x76c45f08125dafc30f35ccc0aa784156551f19b449.9999034239435154 FTM
0xf2d2dca3416f1e59d1ba03e33220c75b101cf761c5e7729b6db70eb43072e8dc199075652021-10-24 1:03:4815 mins ago Fantom Finance: Wrapped Fantom Token 0x283e62cfe14b352db8e30a9575481dcbf589ad9849.9999034239435154 FTM
0xda4e166019c82d329e1a34e48900b6e698310a008b0fa4bf6619cdb557b774e1199073992021-10-24 1:01:1417 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token50 FTM
0xda4e166019c82d329e1a34e48900b6e698310a008b0fa4bf6619cdb557b774e1199073992021-10-24 1:01:1417 mins ago 0x76c45f08125dafc30f35ccc0aa784156551f19b4 0x283e62cfe14b352db8e30a9575481dcbf589ad9850 FTM
0x9a4c75016e933e847673cfb88c4b9ad36536f777392d984bbc7e478fa7f8e5ad199073962021-10-24 1:01:1217 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad98 Fantom Finance: Wrapped Fantom Token25 FTM
0x9a4c75016e933e847673cfb88c4b9ad36536f777392d984bbc7e478fa7f8e5ad199073962021-10-24 1:01:1217 mins ago 0xaf5c41f6a93ec2546eb1c244adb62c686c46ac5f 0x283e62cfe14b352db8e30a9575481dcbf589ad9825 FTM
0x216df7da58fa0b39ac527fd6e60d780b1ee769b4885973282a908eb89f61e92d199073602021-10-24 1:00:4018 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980x76c45f08125dafc30f35ccc0aa784156551f19b450 FTM
0x216df7da58fa0b39ac527fd6e60d780b1ee769b4885973282a908eb89f61e92d199073602021-10-24 1:00:4018 mins ago Fantom Finance: Wrapped Fantom Token 0x283e62cfe14b352db8e30a9575481dcbf589ad9850 FTM
0x80eed487ec4d8692acbcd5e857bfb73bf65b276d840823ef66dbab5652365627199068462021-10-24 0:53:0225 mins ago 0x283e62cfe14b352db8e30a9575481dcbf589ad980xaf5c41f6a93ec2546eb1c244adb62c686c46ac5f60.020510150173524058 FTM
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Router02

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : Router02.sol
pragma solidity =0.6.6;
pragma experimental ABIEncoderV2;

import "./interfaces/IRouter02.sol";
import "./interfaces/IPoolToken.sol";
import "./interfaces/IBorrowable.sol";
import "./interfaces/ICollateral.sol";
import "./interfaces/ITarotCallee.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IVaultToken.sol";
import "./interfaces/IWETH.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./libraries/SafeMath.sol";
import "./libraries/TransferHelper.sol";

contract Router02 is IRouter02, ITarotCallee {
    using SafeMath for uint256;

    address public immutable override factory;
    address public immutable override bDeployer;
    address public immutable override cDeployer;
    address public immutable override WETH;

    modifier ensure(uint256 deadline) {
        require(deadline >= block.timestamp, "TarotRouter: EXPIRED");
        _;
    }

    modifier checkETH(address poolToken) {
        require(
            WETH == IPoolToken(poolToken).underlying(),
            "TarotRouter: NOT_WETH"
        );
        _;
    }

    constructor(
        address _factory,
        address _bDeployer,
        address _cDeployer,
        address _WETH
    ) public {
        factory = _factory;
        bDeployer = _bDeployer;
        cDeployer = _cDeployer;
        WETH = _WETH;
    }

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

    /*** Mint ***/

    function _mint(
        address poolToken,
        address token,
        uint256 amount,
        address from,
        address to
    ) internal virtual returns (uint256 tokens) {
        if (from == address(this))
            TransferHelper.safeTransfer(token, poolToken, amount);
        else TransferHelper.safeTransferFrom(token, from, poolToken, amount);
        tokens = IPoolToken(poolToken).mint(to);
    }

    function mint(
        address poolToken,
        uint256 amount,
        address to,
        uint256 deadline
    ) external virtual override ensure(deadline) returns (uint256 tokens) {
        return
            _mint(
                poolToken,
                IPoolToken(poolToken).underlying(),
                amount,
                msg.sender,
                to
            );
    }

    function mintETH(
        address poolToken,
        address to,
        uint256 deadline
    )
        external
        payable
        virtual
        override
        ensure(deadline)
        checkETH(poolToken)
        returns (uint256 tokens)
    {
        IWETH(WETH).deposit{value: msg.value}();
        return _mint(poolToken, WETH, msg.value, address(this), to);
    }

    function mintCollateral(
        address poolToken,
        uint256 amount,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external virtual override ensure(deadline) returns (uint256 tokens) {
        address underlying = IPoolToken(poolToken).underlying();
        if (isVaultToken(underlying)) {
            address uniswapV2Pair = IVaultToken(underlying).underlying();
            _permit(uniswapV2Pair, amount, deadline, permitData);
            TransferHelper.safeTransferFrom(
                uniswapV2Pair,
                msg.sender,
                underlying,
                amount
            );
            IVaultToken(underlying).mint(poolToken);
            return IPoolToken(poolToken).mint(to);
        } else {
            _permit(underlying, amount, deadline, permitData);
            return _mint(poolToken, underlying, amount, msg.sender, to);
        }
    }

    /*** Redeem ***/

    function redeem(
        address poolToken,
        uint256 tokens,
        address to,
        uint256 deadline,
        bytes memory permitData
    ) public virtual override ensure(deadline) returns (uint256 amount) {
        _permit(poolToken, tokens, deadline, permitData);
        IPoolToken(poolToken).transferFrom(msg.sender, poolToken, tokens);
        address underlying = IPoolToken(poolToken).underlying();
        if (isVaultToken(underlying)) {
            IPoolToken(poolToken).redeem(underlying);
            return IVaultToken(underlying).redeem(to);
        } else {
            return IPoolToken(poolToken).redeem(to);
        }
    }

    function redeemETH(
        address poolToken,
        uint256 tokens,
        address to,
        uint256 deadline,
        bytes memory permitData
    )
        public
        virtual
        override
        ensure(deadline)
        checkETH(poolToken)
        returns (uint256 amountETH)
    {
        amountETH = redeem(
            poolToken,
            tokens,
            address(this),
            deadline,
            permitData
        );
        IWETH(WETH).withdraw(amountETH);
        TransferHelper.safeTransferETH(to, amountETH);
    }

    /*** Borrow ***/

    function borrow(
        address borrowable,
        uint256 amount,
        address to,
        uint256 deadline,
        bytes memory permitData
    ) public virtual override ensure(deadline) {
        _borrowPermit(borrowable, amount, deadline, permitData);
        IBorrowable(borrowable).borrow(msg.sender, to, amount, new bytes(0));
    }

    function borrowETH(
        address borrowable,
        uint256 amountETH,
        address to,
        uint256 deadline,
        bytes memory permitData
    ) public virtual override ensure(deadline) checkETH(borrowable) {
        borrow(borrowable, amountETH, address(this), deadline, permitData);
        IWETH(WETH).withdraw(amountETH);
        TransferHelper.safeTransferETH(to, amountETH);
    }

    /*** Repay ***/

    function _repayAmount(
        address borrowable,
        uint256 amountMax,
        address borrower
    ) internal virtual returns (uint256 amount) {
        IBorrowable(borrowable).accrueInterest();
        uint256 borrowedAmount = IBorrowable(borrowable).borrowBalance(
            borrower
        );
        amount = amountMax < borrowedAmount ? amountMax : borrowedAmount;
    }

    function repay(
        address borrowable,
        uint256 amountMax,
        address borrower,
        uint256 deadline
    ) external virtual override ensure(deadline) returns (uint256 amount) {
        amount = _repayAmount(borrowable, amountMax, borrower);
        TransferHelper.safeTransferFrom(
            IBorrowable(borrowable).underlying(),
            msg.sender,
            borrowable,
            amount
        );
        IBorrowable(borrowable).borrow(borrower, address(0), 0, new bytes(0));
    }

    function repayETH(
        address borrowable,
        address borrower,
        uint256 deadline
    )
        external
        payable
        virtual
        override
        ensure(deadline)
        checkETH(borrowable)
        returns (uint256 amountETH)
    {
        amountETH = _repayAmount(borrowable, msg.value, borrower);
        IWETH(WETH).deposit{value: amountETH}();
        assert(IWETH(WETH).transfer(borrowable, amountETH));
        IBorrowable(borrowable).borrow(borrower, address(0), 0, new bytes(0));
        // refund surpluss eth, if any
        if (msg.value > amountETH)
            TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
    }

    /*** Liquidate ***/

    function liquidate(
        address borrowable,
        uint256 amountMax,
        address borrower,
        address to,
        uint256 deadline
    )
        external
        virtual
        override
        ensure(deadline)
        returns (uint256 amount, uint256 seizeTokens)
    {
        amount = _repayAmount(borrowable, amountMax, borrower);
        TransferHelper.safeTransferFrom(
            IBorrowable(borrowable).underlying(),
            msg.sender,
            borrowable,
            amount
        );
        seizeTokens = IBorrowable(borrowable).liquidate(borrower, to);
    }

    function liquidateETH(
        address borrowable,
        address borrower,
        address to,
        uint256 deadline
    )
        external
        payable
        virtual
        override
        ensure(deadline)
        checkETH(borrowable)
        returns (uint256 amountETH, uint256 seizeTokens)
    {
        amountETH = _repayAmount(borrowable, msg.value, borrower);
        IWETH(WETH).deposit{value: amountETH}();
        assert(IWETH(WETH).transfer(borrowable, amountETH));
        seizeTokens = IBorrowable(borrowable).liquidate(borrower, to);
        // refund surpluss eth, if any
        if (msg.value > amountETH)
            TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
    }

    /*** Leverage LP Token ***/

    function _leverage(
        address underlying,
        uint256 amountA,
        uint256 amountB,
        address to
    ) internal virtual {
        address borrowableA = getBorrowable(underlying, 0);
        // mint collateral
        bytes memory borrowBData = abi.encode(
            CalleeData({
                callType: CallType.ADD_LIQUIDITY_AND_MINT,
                underlying: underlying,
                borrowableIndex: 1,
                data: abi.encode(
                    AddLiquidityAndMintCalldata({
                        amountA: amountA,
                        amountB: amountB,
                        to: to
                    })
                )
            })
        );
        // borrow borrowableB
        bytes memory borrowAData = abi.encode(
            CalleeData({
                callType: CallType.BORROWB,
                underlying: underlying,
                borrowableIndex: 0,
                data: abi.encode(
                    BorrowBCalldata({
                        borrower: msg.sender,
                        receiver: address(this),
                        borrowAmount: amountB,
                        data: borrowBData
                    })
                )
            })
        );
        // borrow borrowableA
        IBorrowable(borrowableA).borrow(
            msg.sender,
            address(this),
            amountA,
            borrowAData
        );
    }

    function leverage(
        address underlying,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bytes calldata permitDataA,
        bytes calldata permitDataB
    ) external virtual override ensure(deadline) {
        _borrowPermit(
            getBorrowable(underlying, 0),
            amountADesired,
            deadline,
            permitDataA
        );
        _borrowPermit(
            getBorrowable(underlying, 1),
            amountBDesired,
            deadline,
            permitDataB
        );
        address uniswapV2Pair = getUniswapV2Pair(underlying);
        (uint256 amountA, uint256 amountB) = _optimalLiquidity(
            uniswapV2Pair,
            amountADesired,
            amountBDesired,
            amountAMin,
            amountBMin
        );
        _leverage(underlying, amountA, amountB, to);
    }

    function _addLiquidityAndMint(
        address underlying,
        uint256 amountA,
        uint256 amountB,
        address to
    ) internal virtual {
        (
            address collateral,
            address borrowableA,
            address borrowableB
        ) = getLendingPool(underlying);
        address uniswapV2Pair = getUniswapV2Pair(underlying);
        // add liquidity to uniswap pair
        TransferHelper.safeTransfer(
            IBorrowable(borrowableA).underlying(),
            uniswapV2Pair,
            amountA
        );
        TransferHelper.safeTransfer(
            IBorrowable(borrowableB).underlying(),
            uniswapV2Pair,
            amountB
        );
        // mint LP token
        if (isVaultToken(underlying))
            IUniswapV2Pair(uniswapV2Pair).mint(underlying);
        IUniswapV2Pair(underlying).mint(collateral);
        // mint collateral
        ICollateral(collateral).mint(to);
    }

    /*** Deleverage LP Token ***/

    function deleverage(
        address underlying,
        uint256 redeemTokens,
        uint256 amountAMin,
        uint256 amountBMin,
        uint256 deadline,
        bytes calldata permitData
    ) external virtual override ensure(deadline) {
        address collateral = getCollateral(underlying);
        uint256 exchangeRate = ICollateral(collateral).exchangeRate();
        require(redeemTokens > 0, "TarotRouter: REDEEM_ZERO");
        uint256 redeemAmount = (redeemTokens - 1).mul(exchangeRate).div(1e18);
        _permit(collateral, redeemTokens, deadline, permitData);
        bytes memory redeemData = abi.encode(
            CalleeData({
                callType: CallType.REMOVE_LIQ_AND_REPAY,
                underlying: underlying,
                borrowableIndex: 0,
                data: abi.encode(
                    RemoveLiqAndRepayCalldata({
                        borrower: msg.sender,
                        redeemTokens: redeemTokens,
                        redeemAmount: redeemAmount,
                        amountAMin: amountAMin,
                        amountBMin: amountBMin
                    })
                )
            })
        );
        // flashRedeem
        ICollateral(collateral).flashRedeem(
            address(this),
            redeemAmount,
            redeemData
        );
    }

    function _removeLiqAndRepay(
        address underlying,
        address borrower,
        uint256 redeemTokens,
        uint256 redeemAmount,
        uint256 amountAMin,
        uint256 amountBMin
    ) internal virtual {
        (
            address collateral,
            address borrowableA,
            address borrowableB
        ) = getLendingPool(underlying);
        address tokenA = IBorrowable(borrowableA).underlying();
        address tokenB = IBorrowable(borrowableB).underlying();
        address uniswapV2Pair = getUniswapV2Pair(underlying);
        // removeLiquidity
        IUniswapV2Pair(underlying).transfer(underlying, redeemAmount);
        //TransferHelper.safeTransfer(underlying, underlying, redeemAmount);
        if (isVaultToken(underlying))
            IVaultToken(underlying).redeem(uniswapV2Pair);
        (uint256 amountAMax, uint256 amountBMax) = IUniswapV2Pair(uniswapV2Pair)
        .burn(address(this));
        require(amountAMax >= amountAMin, "TarotRouter: INSUFFICIENT_A_AMOUNT");
        require(amountBMax >= amountBMin, "TarotRouter: INSUFFICIENT_B_AMOUNT");
        // repay and refund
        _repayAndRefund(borrowableA, tokenA, borrower, amountAMax);
        _repayAndRefund(borrowableB, tokenB, borrower, amountBMax);
        // repay flash redeem
        ICollateral(collateral).transferFrom(
            borrower,
            collateral,
            redeemTokens
        );
    }

    function _repayAndRefund(
        address borrowable,
        address token,
        address borrower,
        uint256 amountMax
    ) internal virtual {
        //repay
        uint256 amount = _repayAmount(borrowable, amountMax, borrower);
        TransferHelper.safeTransfer(token, borrowable, amount);
        IBorrowable(borrowable).borrow(borrower, address(0), 0, new bytes(0));
        // refund excess
        if (amountMax > amount) {
            uint256 refundAmount = amountMax - amount;
            if (token == WETH) {
                IWETH(WETH).withdraw(refundAmount);
                TransferHelper.safeTransferETH(borrower, refundAmount);
            } else TransferHelper.safeTransfer(token, borrower, refundAmount);
        }
    }

    /*** Tarot Callee ***/

    enum CallType {
        ADD_LIQUIDITY_AND_MINT,
        BORROWB,
        REMOVE_LIQ_AND_REPAY
    }
    struct CalleeData {
        CallType callType;
        address underlying;
        uint8 borrowableIndex;
        bytes data;
    }
    struct AddLiquidityAndMintCalldata {
        uint256 amountA;
        uint256 amountB;
        address to;
    }
    struct BorrowBCalldata {
        address borrower;
        address receiver;
        uint256 borrowAmount;
        bytes data;
    }
    struct RemoveLiqAndRepayCalldata {
        address borrower;
        uint256 redeemTokens;
        uint256 redeemAmount;
        uint256 amountAMin;
        uint256 amountBMin;
    }

    function tarotBorrow(
        address sender,
        address borrower,
        uint256 borrowAmount,
        bytes calldata data
    ) external virtual override {
        borrower;
        borrowAmount;
        CalleeData memory calleeData = abi.decode(data, (CalleeData));
        address declaredCaller = getBorrowable(
            calleeData.underlying,
            calleeData.borrowableIndex
        );
        // only succeeds if called by a borrowable and if that borrowable has been called by the router
        require(sender == address(this), "TarotRouter: SENDER_NOT_ROUTER");
        require(
            msg.sender == declaredCaller,
            "TarotRouter: UNAUTHORIZED_CALLER"
        );
        if (calleeData.callType == CallType.ADD_LIQUIDITY_AND_MINT) {
            AddLiquidityAndMintCalldata memory d = abi.decode(
                calleeData.data,
                (AddLiquidityAndMintCalldata)
            );
            _addLiquidityAndMint(
                calleeData.underlying,
                d.amountA,
                d.amountB,
                d.to
            );
        } else if (calleeData.callType == CallType.BORROWB) {
            BorrowBCalldata memory d = abi.decode(
                calleeData.data,
                (BorrowBCalldata)
            );
            address borrowableB = getBorrowable(calleeData.underlying, 1);
            IBorrowable(borrowableB).borrow(
                d.borrower,
                d.receiver,
                d.borrowAmount,
                d.data
            );
        } else revert();
    }

    function tarotRedeem(
        address sender,
        uint256 redeemAmount,
        bytes calldata data
    ) external virtual override {
        redeemAmount;
        CalleeData memory calleeData = abi.decode(data, (CalleeData));
        address declaredCaller = getCollateral(calleeData.underlying);
        // only succeeds if called by a collateral and if that collateral has been called by the router
        require(sender == address(this), "TarotRouter: SENDER_NOT_ROUTER");
        require(
            msg.sender == declaredCaller,
            "TarotRouter: UNAUTHORIZED_CALLER"
        );
        if (calleeData.callType == CallType.REMOVE_LIQ_AND_REPAY) {
            RemoveLiqAndRepayCalldata memory d = abi.decode(
                calleeData.data,
                (RemoveLiqAndRepayCalldata)
            );
            _removeLiqAndRepay(
                calleeData.underlying,
                d.borrower,
                d.redeemTokens,
                d.redeemAmount,
                d.amountAMin,
                d.amountBMin
            );
        } else revert();
    }

    /*** Utilities ***/

    function _permit(
        address poolToken,
        uint256 amount,
        uint256 deadline,
        bytes memory permitData
    ) internal virtual {
        if (permitData.length == 0) return;
        (bool approveMax, uint8 v, bytes32 r, bytes32 s) = abi.decode(
            permitData,
            (bool, uint8, bytes32, bytes32)
        );
        uint256 value = approveMax ? uint256(-1) : amount;
        IPoolToken(poolToken).permit(
            msg.sender,
            address(this),
            value,
            deadline,
            v,
            r,
            s
        );
    }

    function _borrowPermit(
        address borrowable,
        uint256 amount,
        uint256 deadline,
        bytes memory permitData
    ) internal virtual {
        if (permitData.length == 0) return;
        (bool approveMax, uint8 v, bytes32 r, bytes32 s) = abi.decode(
            permitData,
            (bool, uint8, bytes32, bytes32)
        );
        uint256 value = approveMax ? uint256(-1) : amount;
        IBorrowable(borrowable).borrowPermit(
            msg.sender,
            address(this),
            value,
            deadline,
            v,
            r,
            s
        );
    }

    function _optimalLiquidity(
        address uniswapV2Pair,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin
    ) public view virtual returns (uint256 amountA, uint256 amountB) {
        (uint256 reserveA, uint256 reserveB, ) = IUniswapV2Pair(uniswapV2Pair)
        .getReserves();
        uint256 amountBOptimal = _quote(amountADesired, reserveA, reserveB);
        if (amountBOptimal <= amountBDesired) {
            require(
                amountBOptimal >= amountBMin,
                "TarotRouter: INSUFFICIENT_B_AMOUNT"
            );
            (amountA, amountB) = (amountADesired, amountBOptimal);
        } else {
            uint256 amountAOptimal = _quote(amountBDesired, reserveB, reserveA);
            assert(amountAOptimal <= amountADesired);
            require(
                amountAOptimal >= amountAMin,
                "TarotRouter: INSUFFICIENT_A_AMOUNT"
            );
            (amountA, amountB) = (amountAOptimal, amountBDesired);
        }
    }

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

    function isVaultToken(address underlying)
        public
        view
        virtual
        override
        returns (bool)
    {
        try IVaultToken(underlying).isVaultToken() returns (bool result) {
            return result;
        } catch {
            return false;
        }
    }

    function getUniswapV2Pair(address underlying)
        public
        view
        virtual
        override
        returns (address)
    {
        try IVaultToken(underlying).underlying() returns (address u) {
            if (u != address(0)) return u;
            return underlying;
        } catch {
            return underlying;
        }
    }

    function getBorrowable(address underlying, uint8 index)
        public
        view
        virtual
        override
        returns (address borrowable)
    {
        require(index < 2, "TarotRouter: INDEX_TOO_HIGH");
        borrowable = address(
            uint256(
                keccak256(
                    abi.encodePacked(
                        hex"ff",
                        bDeployer,
                        keccak256(abi.encodePacked(factory, underlying, index)),
                        hex"067f8dd3c5fa034c69b1d9017422ce5a724f7633bb87e2b00437b825ee74da48" // Borrowable bytecode keccak256
                    )
                )
            )
        );
    }

    function getCollateral(address underlying)
        public
        view
        virtual
        override
        returns (address collateral)
    {
        collateral = address(
            uint256(
                keccak256(
                    abi.encodePacked(
                        hex"ff",
                        cDeployer,
                        keccak256(abi.encodePacked(factory, underlying)),
                        hex"f70b21cd5817faae2f81bc35b42bac82c6657ca6c7a29899eff2aa4eb8e18783" // Collateral bytecode keccak256
                    )
                )
            )
        );
    }

    function getLendingPool(address underlying)
        public
        view
        virtual
        override
        returns (
            address collateral,
            address borrowableA,
            address borrowableB
        )
    {
        collateral = getCollateral(underlying);
        borrowableA = getBorrowable(underlying, 0);
        borrowableB = getBorrowable(underlying, 1);
    }
}

File 2 of 14 : IRouter02.sol
pragma solidity >=0.5.0;

interface IRouter02 {
    function factory() external pure returns (address);

    function bDeployer() external pure returns (address);

    function cDeployer() external pure returns (address);

    function WETH() external pure returns (address);

    function mint(
        address poolToken,
        uint256 amount,
        address to,
        uint256 deadline
    ) external returns (uint256 tokens);

    function mintETH(
        address poolToken,
        address to,
        uint256 deadline
    ) external payable returns (uint256 tokens);

    function mintCollateral(
        address poolToken,
        uint256 amount,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external returns (uint256 tokens);

    function redeem(
        address poolToken,
        uint256 tokens,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external returns (uint256 amount);

    function redeemETH(
        address poolToken,
        uint256 tokens,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external returns (uint256 amountETH);

    function borrow(
        address borrowable,
        uint256 amount,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external;

    function borrowETH(
        address borrowable,
        uint256 amountETH,
        address to,
        uint256 deadline,
        bytes calldata permitData
    ) external;

    function repay(
        address borrowable,
        uint256 amountMax,
        address borrower,
        uint256 deadline
    ) external returns (uint256 amount);

    function repayETH(
        address borrowable,
        address borrower,
        uint256 deadline
    ) external payable returns (uint256 amountETH);

    function liquidate(
        address borrowable,
        uint256 amountMax,
        address borrower,
        address to,
        uint256 deadline
    ) external returns (uint256 amount, uint256 seizeTokens);

    function liquidateETH(
        address borrowable,
        address borrower,
        address to,
        uint256 deadline
    ) external payable returns (uint256 amountETH, uint256 seizeTokens);

    function leverage(
        address uniswapV2Pair,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bytes calldata permitDataA,
        bytes calldata permitDataB
    ) external;

    function deleverage(
        address uniswapV2Pair,
        uint256 redeemTokens,
        uint256 amountAMin,
        uint256 amountBMin,
        uint256 deadline,
        bytes calldata permitData
    ) external;

    function isVaultToken(address underlying) external view returns (bool);

    function getUniswapV2Pair(address underlying)
        external
        view
        returns (address);

    function getBorrowable(address uniswapV2Pair, uint8 index)
        external
        view
        returns (address borrowable);

    function getCollateral(address uniswapV2Pair)
        external
        view
        returns (address collateral);

    function getLendingPool(address uniswapV2Pair)
        external
        view
        returns (
            address collateral,
            address borrowableA,
            address borrowableB
        );
}

File 3 of 14 : IPoolToken.sol
pragma solidity >=0.5.0;

interface IPoolToken {
    /*** Tarot ERC20 ***/

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

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

    /*** Pool Token ***/

    event Mint(
        address indexed sender,
        address indexed minter,
        uint256 mintAmount,
        uint256 mintTokens
    );
    event Redeem(
        address indexed sender,
        address indexed redeemer,
        uint256 redeemAmount,
        uint256 redeemTokens
    );
    event Sync(uint256 totalBalance);

    function underlying() external view returns (address);

    function factory() external view returns (address);

    function totalBalance() external view returns (uint256);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function exchangeRate() external returns (uint256);

    function mint(address minter) external returns (uint256 mintTokens);

    function redeem(address redeemer) external returns (uint256 redeemAmount);

    function skim(address to) external;

    function sync() external;

    function _setFactory() external;
}

File 4 of 14 : IBorrowable.sol
pragma solidity >=0.5.0;

interface IBorrowable {
    /*** Tarot ERC20 ***/

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

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

    /*** Pool Token ***/

    event Mint(
        address indexed sender,
        address indexed minter,
        uint256 mintAmount,
        uint256 mintTokens
    );
    event Redeem(
        address indexed sender,
        address indexed redeemer,
        uint256 redeemAmount,
        uint256 redeemTokens
    );
    event Sync(uint256 totalBalance);

    function underlying() external view returns (address);

    function factory() external view returns (address);

    function totalBalance() external view returns (uint256);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function exchangeRate() external returns (uint256);

    function mint(address minter) external returns (uint256 mintTokens);

    function redeem(address redeemer) external returns (uint256 redeemAmount);

    function skim(address to) external;

    function sync() external;

    function _setFactory() external;

    /*** Borrowable ***/

    event BorrowApproval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event Borrow(
        address indexed sender,
        address indexed borrower,
        address indexed receiver,
        uint256 borrowAmount,
        uint256 repayAmount,
        uint256 accountBorrowsPrior,
        uint256 accountBorrows,
        uint256 totalBorrows
    );
    event Liquidate(
        address indexed sender,
        address indexed borrower,
        address indexed liquidator,
        uint256 seizeTokens,
        uint256 repayAmount,
        uint256 accountBorrowsPrior,
        uint256 accountBorrows,
        uint256 totalBorrows
    );

    function BORROW_FEE() external pure returns (uint256);

    function collateral() external view returns (address);

    function reserveFactor() external view returns (uint256);

    function exchangeRateLast() external view returns (uint256);

    function borrowIndex() external view returns (uint256);

    function totalBorrows() external view returns (uint256);

    function borrowAllowance(address owner, address spender)
        external
        view
        returns (uint256);

    function borrowBalance(address borrower) external view returns (uint256);

    function borrowTracker() external view returns (address);

    function BORROW_PERMIT_TYPEHASH() external pure returns (bytes32);

    function borrowApprove(address spender, uint256 value)
        external
        returns (bool);

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

    function borrow(
        address borrower,
        address receiver,
        uint256 borrowAmount,
        bytes calldata data
    ) external;

    function liquidate(address borrower, address liquidator)
        external
        returns (uint256 seizeTokens);

    function trackBorrow(address borrower) external;

    /*** Borrowable Interest Rate Model ***/

    event AccrueInterest(
        uint256 interestAccumulated,
        uint256 borrowIndex,
        uint256 totalBorrows
    );
    event CalculateKink(uint256 kinkRate);
    event CalculateBorrowRate(uint256 borrowRate);

    function KINK_BORROW_RATE_MAX() external pure returns (uint256);

    function KINK_BORROW_RATE_MIN() external pure returns (uint256);

    function KINK_MULTIPLIER() external pure returns (uint256);

    function borrowRate() external view returns (uint256);

    function kinkBorrowRate() external view returns (uint256);

    function kinkUtilizationRate() external view returns (uint256);

    function adjustSpeed() external view returns (uint256);

    function rateUpdateTimestamp() external view returns (uint32);

    function accrualTimestamp() external view returns (uint32);

    function accrueInterest() external;

    /*** Borrowable Setter ***/

    event NewReserveFactor(uint256 newReserveFactor);
    event NewKinkUtilizationRate(uint256 newKinkUtilizationRate);
    event NewAdjustSpeed(uint256 newAdjustSpeed);
    event NewBorrowTracker(address newBorrowTracker);

    function RESERVE_FACTOR_MAX() external pure returns (uint256);

    function KINK_UR_MIN() external pure returns (uint256);

    function KINK_UR_MAX() external pure returns (uint256);

    function ADJUST_SPEED_MIN() external pure returns (uint256);

    function ADJUST_SPEED_MAX() external pure returns (uint256);

    function _initialize(
        string calldata _name,
        string calldata _symbol,
        address _underlying,
        address _collateral
    ) external;

    function _setReserveFactor(uint256 newReserveFactor) external;

    function _setKinkUtilizationRate(uint256 newKinkUtilizationRate) external;

    function _setAdjustSpeed(uint256 newAdjustSpeed) external;

    function _setBorrowTracker(address newBorrowTracker) external;
}

File 5 of 14 : ICollateral.sol
pragma solidity >=0.5.0;

interface ICollateral {
    /*** Tarot ERC20 ***/

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

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

    /*** Pool Token ***/

    event Mint(
        address indexed sender,
        address indexed minter,
        uint256 mintAmount,
        uint256 mintTokens
    );
    event Redeem(
        address indexed sender,
        address indexed redeemer,
        uint256 redeemAmount,
        uint256 redeemTokens
    );
    event Sync(uint256 totalBalance);

    function underlying() external view returns (address);

    function factory() external view returns (address);

    function totalBalance() external view returns (uint256);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function exchangeRate() external returns (uint256);

    function mint(address minter) external returns (uint256 mintTokens);

    function redeem(address redeemer) external returns (uint256 redeemAmount);

    function skim(address to) external;

    function sync() external;

    function _setFactory() external;

    /*** Collateral ***/

    function borrowable0() external view returns (address);

    function borrowable1() external view returns (address);

    function tarotPriceOracle() external view returns (address);

    function safetyMarginSqrt() external view returns (uint256);

    function liquidationIncentive() external view returns (uint256);

    function getPrices() external returns (uint256 price0, uint256 price1);

    function tokensUnlocked(address from, uint256 value)
        external
        returns (bool);

    function accountLiquidityAmounts(
        address account,
        uint256 amount0,
        uint256 amount1
    ) external returns (uint256 liquidity, uint256 shortfall);

    function accountLiquidity(address account)
        external
        returns (uint256 liquidity, uint256 shortfall);

    function canBorrow(
        address account,
        address borrowable,
        uint256 accountBorrows
    ) external returns (bool);

    function seize(
        address liquidator,
        address borrower,
        uint256 repayAmount
    ) external returns (uint256 seizeTokens);

    function flashRedeem(
        address redeemer,
        uint256 redeemAmount,
        bytes calldata data
    ) external;

    /*** Collateral Setter ***/

    event NewSafetyMargin(uint256 newSafetyMarginSqrt);
    event NewLiquidationIncentive(uint256 newLiquidationIncentive);

    function SAFETY_MARGIN_SQRT_MIN() external pure returns (uint256);

    function SAFETY_MARGIN_SQRT_MAX() external pure returns (uint256);

    function LIQUIDATION_INCENTIVE_MIN() external pure returns (uint256);

    function LIQUIDATION_INCENTIVE_MAX() external pure returns (uint256);

    function _initialize(
        string calldata _name,
        string calldata _symbol,
        address _underlying,
        address _borrowable0,
        address _borrowable1
    ) external;

    function _setSafetyMarginSqrt(uint256 newSafetyMarginSqrt) external;

    function _setLiquidationIncentive(uint256 newLiquidationIncentive) external;
}

File 6 of 14 : ITarotCallee.sol
pragma solidity >=0.5.0;

interface ITarotCallee {
    function tarotBorrow(
        address sender,
        address borrower,
        uint256 borrowAmount,
        bytes calldata data
    ) external;

    function tarotRedeem(
        address sender,
        uint256 redeemAmount,
        bytes calldata data
    ) external;
}

File 7 of 14 : IERC20.sol
pragma solidity >=0.5.0;

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

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);
}

File 8 of 14 : IVaultToken.sol
pragma solidity >=0.5.0;

import "./IMasterChef.sol";
import "./IUniswapV2Router01.sol";

interface IVaultToken {
    /*** Tarot ERC20 ***/

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

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

    /*** Pool Token ***/

    event Mint(
        address indexed sender,
        address indexed minter,
        uint256 mintAmount,
        uint256 mintTokens
    );
    event Redeem(
        address indexed sender,
        address indexed redeemer,
        uint256 redeemAmount,
        uint256 redeemTokens
    );
    event Sync(uint256 totalBalance);

    function underlying() external view returns (address);

    function factory() external view returns (address);

    function totalBalance() external view returns (uint256);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function exchangeRate() external view returns (uint256);

    function mint(address minter) external returns (uint256 mintTokens);

    function redeem(address redeemer) external returns (uint256 redeemAmount);

    function skim(address to) external;

    function sync() external;

    function _setFactory() external;

    /*** VaultToken ***/

    event Reinvest(address indexed caller, uint256 reward, uint256 bounty);

    function isVaultToken() external pure returns (bool);

    function router() external view returns (IUniswapV2Router01);

    function masterChef() external view returns (IMasterChef);

    function rewardsToken() external view returns (address);

    function WETH() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function swapFeeFactor() external view returns (uint256);

    function pid() external view returns (uint256);

    function REINVEST_BOUNTY() external pure returns (uint256);

    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function _initialize(
        IUniswapV2Router01 _router,
        IMasterChef _masterChef,
        address _rewardsToken,
        uint256 _swapFeeFactor,
        uint256 _pid
    ) external;

    function reinvest() external;
}

File 9 of 14 : IWETH.sol
pragma solidity >=0.5.0;

interface IWETH {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);

    function withdraw(uint256) external;
}

File 10 of 14 : IUniswapV2Pair.sol
pragma solidity >=0.5.0;

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

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

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

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

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to)
        external
        returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;

    function skim(address to) external;

    function sync() external;

    function initialize(address, address) external;
}

File 11 of 14 : SafeMath.sol
pragma solidity =0.6.6;

// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
// Subject to the MIT license.

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, errorMessage);

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot underflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction underflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot underflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, errorMessage);

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers.
     * Reverts on division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers.
     * Reverts with custom message on division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 12 of 14 : TransferHelper.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity =0.6.6;

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

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

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

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(
            success,
            "TransferHelper::safeTransferETH: ETH transfer failed"
        );
    }
}

File 13 of 14 : IMasterChef.sol
pragma solidity >=0.5.16;

import "./IERC20.sol";

// Making the original MasterChef as an interface leads to compilation fail.
// Use Contract instead of Interface here
contract IMasterChef {
    // Info of each user.
    struct UserInfo {
        uint256 amount; // How many LP tokens the user has provided.
        uint256 rewardDebt; // Reward debt. See explanation below.
    }

    // Info of each pool.
    struct PoolInfo {
        IERC20 lpToken; // Address of LP token contract.
        uint256 allocPoint; // How many allocation points assigned to this pool. Reward tokens to distribute per block.
        uint256 lastRewardBlock; // Last block number that reward token distribution occurs.
        uint256 accRewardTokenPerShare; // Accumulated reward tokens per share, times 1e12. See below.
    }

    // Info of each user that stakes LP tokens.
    mapping(uint256 => PoolInfo) public poolInfo;
    mapping(uint256 => mapping(address => UserInfo)) public userInfo;

    // Deposit LP tokens to MasterChef.
    function deposit(uint256 _pid, uint256 _amount) external {}

    // Withdraw LP tokens from MasterChef.
    function withdraw(uint256 _pid, uint256 _amount) external {}
}

File 14 of 14 : IUniswapV2Router01.sol
pragma solidity >=0.5.0;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(uint256 amountIn, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_bDeployer","type":"address"},{"internalType":"address","name":"_cDeployer","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"uniswapV2Pair","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"}],"name":"_optimalLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bDeployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"borrowETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cDeployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"redeemTokens","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"deleverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getBorrowable","outputs":[{"internalType":"address","name":"borrowable","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getCollateral","outputs":[{"internalType":"address","name":"collateral","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getLendingPool","outputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"borrowableA","type":"address"},{"internalType":"address","name":"borrowableB","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"getUniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","type":"address"}],"name":"isVaultToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"underlying","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":"bytes","name":"permitDataA","type":"bytes"},{"internalType":"bytes","name":"permitDataB","type":"bytes"}],"name":"leverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"uint256","name":"amountMax","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"liquidate","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"liquidateETH","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"poolToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"tokens","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"mintCollateral","outputs":[{"internalType":"uint256","name":"tokens","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolToken","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"mintETH","outputs":[{"internalType":"uint256","name":"tokens","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"poolToken","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolToken","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"permitData","type":"bytes"}],"name":"redeemETH","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"uint256","name":"amountMax","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"repay","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowable","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"repayETH","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"tarotBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"tarotRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101006040523480156200001257600080fd5b50604051620043d6380380620043d6833981016040819052620000359162000083565b6001600160601b0319606094851b811660805292841b831660a05290831b821660c05290911b1660e052620000e3565b80516001600160a01b03811681146200007d57600080fd5b92915050565b6000806000806080858703121562000099578384fd5b620000a5868662000065565b9350620000b6866020870162000065565b9250620000c7866040870162000065565b9150620000d8866060870162000065565b905092959194509250565b60805160601c60a05160601c60c05160601c60e05160601c61424d620001896000398061017a528061080d5280610879528061098852806109f15280610b8a5280610bde5280610c6452806117fa528061184152806118b95280611be75280611d985280611dec5280611e72528061301e528061306d525080611b285280611b4e525080611c2f5280611fcc525080611b6f5280611c0b5280611fed525061424d6000f3fe60806040526004361061016a5760003560e01c80636b4d4dc1116100d1578063ad5c46481161008a578063dbe5f2fb11610064578063dbe5f2fb1461044f578063eb03419a1461046f578063ef974e9c14610482578063fcb2a895146104a2576101a3565b8063ad5c464814610410578063c45a015514610425578063db5a26901461043a576101a3565b80636b4d4dc1146103685780636d29e7fc14610388578063703de94c146103a857806377370d62146103bb5780637a4660d5146103db5780639b56d6c9146103f0576101a3565b80633970036a116101235780633970036a1461028d5780633c173a4f146102ba57806343e26448146102da5780635c1e6404146102fa57806367bf252f146103285780636aee7c1e14610348576101a3565b80630572bf5f146101a85780631f1cc5bc146101e05780632b005cfc1461020d5780632c3445041461022d578063338c4ccb1461024d57806335bb10591461027a576101a3565b366101a357336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101a157fe5b005b600080fd5b3480156101b457600080fd5b506101c86101c336600461326e565b6104c2565b6040516101d793929190613c88565b60405180910390f35b3480156101ec57600080fd5b506102006101fb3660046134b2565b6104f2565b6040516101d7919061414d565b34801561021957600080fd5b506102006102283660046134b2565b61076d565b34801561023957600080fd5b506101a16102483660046134b2565b6108ea565b34801561025957600080fd5b5061026d61026836600461326e565b610a6b565b6040516101d79190613cc4565b6102006102883660046132f6565b610aea565b34801561029957600080fd5b506102ad6102a836600461326e565b610d83565b6040516101d79190613b9b565b3480156102c657600080fd5b506102006102d5366004613401565b610e18565b3480156102e657600080fd5b506102006102f5366004613438565b610ec2565b34801561030657600080fd5b5061031a6103153660046133a7565b61118f565b6040516101d7929190614156565b34801561033457600080fd5b506101a16103433660046135c3565b6112c9565b34801561035457600080fd5b50610200610363366004613401565b6113c0565b34801561037457600080fd5b506101a1610383366004613526565b6114e5565b34801561039457600080fd5b506101a16103a3366004613336565b6115c1565b6102006103b63660046132f6565b61175a565b3480156103c757600080fd5b506101a16103d6366004613692565b6118e0565b3480156103e757600080fd5b506102ad611b26565b3480156103fc57600080fd5b506102ad61040b36600461326e565b611b4a565b34801561041c57600080fd5b506102ad611be5565b34801561043157600080fd5b506102ad611c09565b34801561044657600080fd5b506102ad611c2d565b34801561045b57600080fd5b506101a161046a3660046134b2565b611c51565b61031a61047d3660046132a6565b611cf7565b34801561048e57600080fd5b506102ad61049d36600461370d565b611fa5565b3480156104ae57600080fd5b5061031a6104bd366004613580565b612066565b60008060006104d084611b4a565b92506104dd846000611fa5565b91506104ea846001611fa5565b929491935050565b6000824281101561051e5760405162461bcd60e51b815260040161051590613f96565b60405180910390fd5b61052a87878686612181565b6040516323b872dd60e01b81526001600160a01b038816906323b872dd9061055a9033908b908b90600401613c23565b602060405180830381600087803b15801561057457600080fd5b505af1158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190613745565b506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156105e857600080fd5b505afa1580156105fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610620919061328a565b905061062b81610a6b565b15610735576040516395a2251f60e01b81526001600160a01b038916906395a2251f9061065c908490600401613b9b565b602060405180830381600087803b15801561067657600080fd5b505af115801561068a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ae9190613a1d565b506040516395a2251f60e01b81526001600160a01b038216906395a2251f906106db908990600401613b9b565b602060405180830381600087803b1580156106f557600080fd5b505af1158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d9190613a1d565b925050610763565b6040516395a2251f60e01b81526001600160a01b038916906395a2251f906106db908990600401613b9b565b505b5095945050505050565b600082428110156107905760405162461bcd60e51b815260040161051590613f96565b86806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610802919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146108525760405162461bcd60e51b815260040161051590613f67565b61085f88883088886104f2565b604051632e1a7d4d60e01b81529093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906108ae90869060040161414d565b600060405180830381600087803b1580156108c857600080fd5b505af11580156108dc573d6000803e3d6000fd5b505050506107618684612238565b814281101561090b5760405162461bcd60e51b815260040161051590613f96565b85806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561094557600080fd5b505afa158015610959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097d919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146109cd5760405162461bcd60e51b815260040161051590613f67565b6109da8787308787611c51565b604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90610a2690899060040161414d565b600060405180830381600087803b158015610a4057600080fd5b505af1158015610a54573d6000803e3d6000fd5b50505050610a628587612238565b50505050505050565b6000816001600160a01b0316636ee272276040518163ffffffff1660e01b815260040160206040518083038186803b158015610aa657600080fd5b505afa925050508015610ad6575060408051601f3d908101601f19168201909252610ad391810190613745565b60015b610ae257506000610ae5565b90505b919050565b60008142811015610b0d5760405162461bcd60e51b815260040161051590613f96565b84806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4757600080fd5b505afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610bcf5760405162461bcd60e51b815260040161051590613f67565b610bda8634876122ca565b92507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250610c9e915089908790600401613cab565b602060405180830381600087803b158015610cb857600080fd5b505af1158015610ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf09190613745565b610cf657fe5b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03881691631e7dcc0d91610d34918991819060248101613baf565b600060405180830381600087803b158015610d4e57600080fd5b505af1158015610d62573d6000803e3d6000fd5b5050505082341115610d7a57610d7a33843403612238565b50509392505050565b6000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610dbe57600080fd5b505afa925050508015610dee575060408051601f3d908101601f19168201909252610deb9181019061328a565b60015b610df9575080610ae5565b6001600160a01b03811615610e0f579050610ae5565b82915050610ae5565b60008142811015610e3b5760405162461bcd60e51b815260040161051590613f96565b610eb886876001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e7857600080fd5b505afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb0919061328a565b8733886123b8565b9695505050505050565b60008342811015610ee55760405162461bcd60e51b815260040161051590613f96565b6000886001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2057600080fd5b505afa158015610f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f58919061328a565b9050610f6381610a6b565b15611131576000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa357600080fd5b505afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061328a565b905061101f818a8989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b61102b8133848c612465565b6040516335313c2160e11b81526001600160a01b03831690636a62784290611057908d90600401613b9b565b602060405180830381600087803b15801561107157600080fd5b505af1158015611085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a99190613a1d565b506040516335313c2160e11b81526001600160a01b038b1690636a627842906110d6908b90600401613b9b565b602060405180830381600087803b1580156110f057600080fd5b505af1158015611104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111289190613a1d565b93505050611184565b61117381898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b61118089828a338b6123b8565b9250505b509695505050505050565b60008082428110156111b35760405162461bcd60e51b815260040161051590613f96565b6111be8888886122ca565b925061123c886001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156111fc57600080fd5b505afa158015611210573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611234919061328a565b338a86612465565b6040516386b9d81f60e01b81526001600160a01b038916906386b9d81f9061126a9089908990600401613c6e565b602060405180830381600087803b15801561128457600080fd5b505af1158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc9190613a1d565b9150509550959350505050565b84428110156112ea5760405162461bcd60e51b815260040161051590613f96565b6113366112f88d6000611fa5565b8c8888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061254e92505050565b6113826113448d6001611fa5565b8b8886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061254e92505050565b600061138d8d610d83565b905060008061139f838f8f8f8f612066565b915091506113af8f83838d6125c7565b505050505050505050505050505050565b600081428110156113e35760405162461bcd60e51b815260040161051590613f96565b6113ee8686866122ca565b915061146c866001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561142c57600080fd5b505afa158015611440573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611464919061328a565b338885612465565b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03881691631e7dcc0d916114aa918891819060248101613baf565b600060405180830381600087803b1580156114c457600080fd5b505af11580156114d8573d6000803e3d6000fd5b5050505050949350505050565b6114ed613125565b6114f9828401846138c4565b9050600061150a8260200151611b4a565b90506001600160a01b03861630146115345760405162461bcd60e51b815260040161051590613d4e565b336001600160a01b0382161461155c5760405162461bcd60e51b815260040161051590613ce2565b60028251600281111561156b57fe5b14156101a35761157961314c565b8260600151806020019051810190611591919061396d565b9050610a6283602001518260000151836020015184604001518560600151866080015161277c565b505050505050565b6115c9613125565b6115d5828401846138c4565b905060006115eb82602001518360400151611fa5565b90506001600160a01b03871630146116155760405162461bcd60e51b815260040161051590613d4e565b336001600160a01b0382161461163d5760405162461bcd60e51b815260040161051590613ce2565b60008251600281111561164c57fe5b14156116965761165a613184565b826060015180602001905181019061167291906137b0565b90506116908360200151826000015183602001518460400151612af5565b50610a62565b6001825160028111156116a557fe5b14156101a3576116b36131ae565b82606001518060200190518101906116cb91906137f3565b905060006116de84602001516001611fa5565b8251602084015160408086015160608701519151631e7dcc0d60e01b81529495506001600160a01b03861694631e7dcc0d94611721949093909291600401613baf565b600060405180830381600087803b15801561173b57600080fd5b505af115801561174f573d6000803e3d6000fd5b505050505050610a62565b6000814281101561177d5760405162461bcd60e51b815260040161051590613f96565b84806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156117b757600080fd5b505afa1580156117cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ef919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461183f5760405162461bcd60e51b815260040161051590613f67565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561189a57600080fd5b505af11580156118ae573d6000803e3d6000fd5b5050505050610eb8867f00000000000000000000000000000000000000000000000000000000000000003430896123b8565b82428110156119015760405162461bcd60e51b815260040161051590613f96565b600061190c89611b4a565b90506000816001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561194b57600080fd5b505af115801561195f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119839190613a1d565b9050600089116119a55760405162461bcd60e51b815260040161051590614011565b60006119d3670de0b6b3a76400006119c76000198d018563ffffffff612da216565b9063ffffffff612de516565b9050611a17838b8989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b604080516080810190915260609080600281526020018d6001600160a01b03168152602001600060ff1681526020016040518060a00160405280336001600160a01b031681526020018e81526020018581526020018d81526020018c815250604051602001611a86919061410f565b60408051601f19818403018152918152915251611aa691906020016140bf565b60408051601f19818403018152908290526319f3400d60e01b825291506001600160a01b038516906319f3400d90611ae690309086908690600401613c47565b600060405180830381600087803b158015611b0057600080fd5b505af1158015611b14573d6000803e3d6000fd5b50505050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083604051602001611ba0929190613a84565b60405160208183030381529060405280519060200120604051602001611bc7929190613af9565b60408051601f19818403018152919052805160209091012092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b8142811015611c725760405162461bcd60e51b815260040161051590613f96565b611c7e8686858561254e565b60408051600081526020810191829052631e7dcc0d60e01b9091526001600160a01b03871690631e7dcc0d90611cbd90339088908a9060248101613baf565b600060405180830381600087803b158015611cd757600080fd5b505af1158015611ceb573d6000803e3d6000fd5b50505050505050505050565b6000808242811015611d1b5760405162461bcd60e51b815260040161051590613f96565b86806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015611d5557600080fd5b505afa158015611d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8d919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611ddd5760405162461bcd60e51b815260040161051590613f67565b611de88834896122ca565b93507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e4557600080fd5b505af1158015611e59573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250611eac91508b908890600401613cab565b602060405180830381600087803b158015611ec657600080fd5b505af1158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe9190613745565b611f0457fe5b6040516386b9d81f60e01b81526001600160a01b038916906386b9d81f90611f32908a908a90600401613c6e565b602060405180830381600087803b158015611f4c57600080fd5b505af1158015611f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f849190613a1d565b925083341115611f9a57611f9a33853403612238565b505094509492505050565b600060028260ff1610611fca5760405162461bcd60e51b815260040161051590613d17565b7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000848460405160200161202093929190613aa6565b60405160208183030381529060405280519060200120604051602001612047929190613b4a565b60408051601f1981840301815291905280516020909101209392505050565b600080600080886001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156120a557600080fd5b505afa1580156120b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120dd91906139c9565b506001600160701b031691506001600160701b031691506000612101898484612e27565b9050878111612135578581101561212a5760405162461bcd60e51b815260040161051590613e6c565b889450925082612174565b6000612142898486612e27565b90508981111561214e57fe5b8781101561216e5760405162461bcd60e51b815260040161051590613e2a565b94508793505b5050509550959350505050565b805161218c57612232565b600080600080848060200190518101906121a69190613765565b93509350935093506000846121bb57876121bf565b6000195b60405163d505accf60e01b81529091506001600160a01b038a169063d505accf906121fa903390309086908d908b908b908b90600401613be2565b600060405180830381600087803b15801561221457600080fd5b505af1158015612228573d6000803e3d6000fd5b5050505050505050505b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516122629190613add565b60006040518083038185875af1925050503d806000811461229f576040519150601f19603f3d011682016040523d82523d6000602084013e6122a4565b606091505b50509050806122c55760405162461bcd60e51b815260040161051590613dd6565b505050565b6000836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b50506040516326b9f4dd60e11b8152600092506001600160a01b0387169150634d73e9ba9061234e908690600401613b9b565b60206040518083038186803b15801561236657600080fd5b505afa15801561237a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239e9190613a1d565b90508084106123ad57806123af565b835b95945050505050565b60006001600160a01b0383163014156123db576123d6858786612e95565b6123e7565b6123e785848887612465565b6040516335313c2160e11b81526001600160a01b03871690636a62784290612413908590600401613b9b565b602060405180830381600087803b15801561242d57600080fd5b505af1158015612441573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb89190613a1d565b60006060856001600160a01b03166323b872dd86868660405160240161248d93929190613c23565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516124c69190613add565b6000604051808303816000865af19150503d8060008114612503576040519150601f19603f3d011682016040523d82523d6000602084013e612508565b606091505b50915091508180156125325750805115806125325750808060200190518101906125329190613745565b6115b95760405162461bcd60e51b815260040161051590613d85565b805161255957612232565b600080600080848060200190518101906125739190613765565b9350935093509350600084612588578761258c565b6000195b60405163279e6d5760e21b81529091506001600160a01b038a1690639e79b55c906121fa903390309086908d908b908b908b90600401613be2565b60006125d4856000611fa5565b905060606040518060800160405280600060028111156125f057fe5b8152602001876001600160a01b03168152602001600160ff1681526020016040518060600160405280888152602001878152602001866001600160a01b03168152506040516020016126429190614048565b60408051601f1981840301815291815291525161266291906020016140bf565b60408051601f198184030181526080830190915291506060908060018152602001886001600160a01b03168152602001600060ff1681526020016040518060800160405280336001600160a01b03168152602001306001600160a01b03168152602001888152602001858152506040516020016126df9190614072565b60408051601f198184030181529181529152516126ff91906020016140bf565b60408051601f1981840301815290829052631e7dcc0d60e01b825291506001600160a01b03841690631e7dcc0d9061274190339030908b908790600401613baf565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b5050505050505050505050565b600080600061278a896104c2565b9250925092506000826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156127cb57600080fd5b505afa1580156127df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612803919061328a565b90506000826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561284057600080fd5b505afa158015612854573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612878919061328a565b905060006128858c610d83565b60405163a9059cbb60e01b81529091506001600160a01b038d169063a9059cbb906128b6908f908d90600401613cab565b602060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129089190613745565b506129128c610a6b565b15612997576040516395a2251f60e01b81526001600160a01b038d16906395a2251f90612943908490600401613b9b565b602060405180830381600087803b15801561295d57600080fd5b505af1158015612971573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129959190613a1d565b505b600080826001600160a01b03166389afcb44306040518263ffffffff1660e01b81526004016129c69190613b9b565b6040805180830381600087803b1580156129df57600080fd5b505af11580156129f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a179190613a35565b9150915089821015612a3b5760405162461bcd60e51b815260040161051590613e2a565b88811015612a5b5760405162461bcd60e51b815260040161051590613e6c565b612a6787868f85612f83565b612a7386858f84612f83565b876001600160a01b03166323b872dd8e8a8f6040518463ffffffff1660e01b8152600401612aa393929190613c23565b602060405180830381600087803b158015612abd57600080fd5b505af1158015612ad1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113af9190613745565b6000806000612b03876104c2565b9250925092506000612b1488610d83565b9050612b91836001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612b5257600080fd5b505afa158015612b66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8a919061328a565b8289612e95565b612c0c826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612bcd57600080fd5b505afa158015612be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c05919061328a565b8288612e95565b612c1588610a6b565b15612c9a576040516335313c2160e11b81526001600160a01b03821690636a62784290612c46908b90600401613b9b565b602060405180830381600087803b158015612c6057600080fd5b505af1158015612c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c989190613a1d565b505b6040516335313c2160e11b81526001600160a01b03891690636a62784290612cc6908790600401613b9b565b602060405180830381600087803b158015612ce057600080fd5b505af1158015612cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d189190613a1d565b506040516335313c2160e11b81526001600160a01b03851690636a62784290612d45908890600401613b9b565b602060405180830381600087803b158015612d5f57600080fd5b505af1158015612d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d979190613a1d565b505050505050505050565b600082612db157506000612ddf565b82820282848281612dbe57fe5b0414612ddc5760405162461bcd60e51b815260040161051590613f26565b90505b92915050565b6000612ddc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130ee565b6000808411612e485760405162461bcd60e51b815260040161051590613eae565b600083118015612e585750600082115b612e745760405162461bcd60e51b815260040161051590613ee3565b82612e85858463ffffffff612da216565b81612e8c57fe5b04949350505050565b60006060846001600160a01b031663a9059cbb8585604051602401612ebb929190613cab565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612ef49190613add565b6000604051808303816000865af19150503d8060008114612f31576040519150601f19603f3d011682016040523d82523d6000602084013e612f36565b606091505b5091509150818015612f60575080511580612f60575080806020019051810190612f609190613745565b612f7c5760405162461bcd60e51b815260040161051590613fc4565b5050505050565b6000612f908583856122ca565b9050612f9d848683612e95565b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03871691631e7dcc0d91612fdb918791819060248101613baf565b600060405180830381600087803b158015612ff557600080fd5b505af1158015613009573d6000803e3d6000fd5b5050505080821115612f7c57600081830390507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b031614156130e357604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906130a290849060040161414d565b600060405180830381600087803b1580156130bc57600080fd5b505af11580156130d0573d6000803e3d6000fd5b505050506130de8482612238565b6115b9565b6115b9858583612e95565b6000818361310f5760405162461bcd60e51b81526004016105159190613ccf565b50600083858161311b57fe5b0495945050505050565b60408051608081019091528060008152600060208201819052604082015260609081015290565b6040518060a0016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6040518060600160405280600081526020016000815260200160006001600160a01b031681525090565b604080516080810182526000808252602082018190529181019190915260608082015290565b60008083601f8401126131e5578182fd5b50813567ffffffffffffffff8111156131fc578182fd5b60208301915083602082850101111561321457600080fd5b9250929050565b600082601f83011261322b578081fd5b813561323e6132398261418b565b614164565b915080825283602082850101111561325557600080fd5b8060208401602084013760009082016020015292915050565b60006020828403121561327f578081fd5b8135612ddc816141db565b60006020828403121561329b578081fd5b8151612ddc816141db565b600080600080608085870312156132bb578283fd5b84356132c6816141db565b935060208501356132d6816141db565b925060408501356132e6816141db565b9396929550929360600135925050565b60008060006060848603121561330a578283fd5b8335613315816141db565b92506020840135613325816141db565b929592945050506040919091013590565b60008060008060006080868803121561334d578081fd5b8535613358816141db565b94506020860135613368816141db565b935060408601359250606086013567ffffffffffffffff81111561338a578182fd5b613396888289016131d4565b969995985093965092949392505050565b600080600080600060a086880312156133be578283fd5b85356133c9816141db565b94506020860135935060408601356133e0816141db565b925060608601356133f0816141db565b949793965091946080013592915050565b60008060008060808587031215613416578182fd5b8435613421816141db565b93506020850135925060408501356132e6816141db565b60008060008060008060a08789031215613450578384fd5b863561345b816141db565b9550602087013594506040870135613472816141db565b935060608701359250608087013567ffffffffffffffff811115613494578182fd5b6134a089828a016131d4565b979a9699509497509295939492505050565b600080600080600060a086880312156134c9578283fd5b85356134d4816141db565b94506020860135935060408601356134eb816141db565b925060608601359150608086013567ffffffffffffffff81111561350d578182fd5b6135198882890161321b565b9150509295509295909350565b6000806000806060858703121561353b578182fd5b8435613546816141db565b935060208501359250604085013567ffffffffffffffff811115613568578283fd5b613574878288016131d4565b95989497509550505050565b600080600080600060a08688031215613597578283fd5b85356135a2816141db565b97602087013597506040870135966060810135965060800135945092505050565b60008060008060008060008060008060006101208c8e0312156135e4578889fd5b6135ee8c356141db565b8b359a5060208c0135995060408c0135985060608c0135975060808c0135965061361b60a08d01356141db565b60a08c0135955060c08c0135945067ffffffffffffffff8060e08e01351115613642578485fd5b6136528e60e08f01358f016131d4565b90955093506101008d0135811015613668578283fd5b5061367a8d6101008e01358e016131d4565b81935080925050509295989b509295989b9093969950565b600080600080600080600060c0888a0312156136ac578081fd5b87356136b7816141db565b96506020880135955060408801359450606088013593506080880135925060a088013567ffffffffffffffff8111156136ee578182fd5b6136fa8a828b016131d4565b989b979a50959850939692959293505050565b6000806040838503121561371f578182fd5b823561372a816141db565b9150602083013561373a81614208565b809150509250929050565b600060208284031215613756578081fd5b81518015158114612ddc578182fd5b6000806000806080858703121561377a578182fd5b84518015158114613789578283fd5b602086015190945061379a81614208565b6040860151606090960151949790965092505050565b6000606082840312156137c1578081fd5b6137cb6060614164565b825181526020830151602082015260408301516137e7816141db565b60408201529392505050565b60006020808385031215613805578182fd5b825167ffffffffffffffff8082111561381c578384fd5b8185016080818803121561382e578485fd5b6138386080614164565b92508051613845816141db565b835280840151613854816141db565b8385015260408181015190840152606081015182811115613873578586fd5b019050601f81018613613884578384fd5b80516138926132398261418b565b81815287858385010111156138a5578586fd5b6138b4828683018786016141af565b6060840152509095945050505050565b6000602082840312156138d5578081fd5b813567ffffffffffffffff808211156138ec578283fd5b818401608081870312156138fe578384fd5b6139086080614164565b9250803560038110613918578485fd5b83526020810135613928816141db565b6020840152604081013561393b81614208565b6040840152606081013582811115613951578485fd5b61395d8782840161321b565b6060850152509195945050505050565b600060a0828403121561397e578081fd5b61398860a0614164565b8251613993816141db565b80825250602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b6000806000606084860312156139dd578081fd5b83516139e8816141f3565b60208501519093506139f9816141f3565b604085015190925063ffffffff81168114613a12578182fd5b809150509250925092565b600060208284031215613a2e578081fd5b5051919050565b60008060408385031215613a47578182fd5b505080516020909101519092909150565b60008151808452613a708160208601602086016141af565b601f01601f19169290920160200192915050565b6001600160601b0319606093841b811682529190921b16601482015260280190565b606093841b6001600160601b031990811682529290931b909116601483015260f81b6001600160f81b031916602882015260290190565b60008251613aef8184602087016141af565b9190910192915050565b6001600160f81b0319815260609290921b6001600160601b031916600183015260158201527ff70b21cd5817faae2f81bc35b42bac82c6657ca6c7a29899eff2aa4eb8e18783603582015260550190565b6001600160f81b0319815260609290921b6001600160601b031916600183015260158201527f067f8dd3c5fa034c69b1d9017422ce5a724f7633bb87e2b00437b825ee74da48603582015260550190565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090610eb890830184613a58565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b0385168252836020830152606060408301526123af6060830184613a58565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612ddc6020830184613a58565b6020808252818101527f5461726f74526f757465723a20554e415554484f52495a45445f43414c4c4552604082015260600190565b6020808252601b908201527f5461726f74526f757465723a20494e4445585f544f4f5f484947480000000000604082015260600190565b6020808252601e908201527f5461726f74526f757465723a2053454e4445525f4e4f545f524f555445520000604082015260600190565b60208082526031908201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604082015270185b9cd9995c919c9bdb4819985a5b1959607a1b606082015260800190565b60208082526034908201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60408201527308115512081d1c985b9cd9995c8819985a5b195960621b606082015260800190565b60208082526022908201527f5461726f74526f757465723a20494e53554646494349454e545f415f414d4f55604082015261139560f21b606082015260800190565b60208082526022908201527f5461726f74526f757465723a20494e53554646494349454e545f425f414d4f55604082015261139560f21b606082015260800190565b6020808252818101527f5461726f74526f757465723a20494e53554646494349454e545f414d4f554e54604082015260600190565b60208082526023908201527f5461726f74526f757465723a20494e53554646494349454e545f4c495155494460408201526249545960e81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601590820152740a8c2e4dee8a4deeae8cae474409c9ea8beae8aa89605b1b604082015260600190565b60208082526014908201527315185c9bdd149bdd5d195c8e881156141254915160621b604082015260600190565b6020808252602d908201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260408201526c185b9cd9995c8819985a5b1959609a1b606082015260800190565b60208082526018908201527f5461726f74526f757465723a2052454445454d5f5a45524f0000000000000000604082015260600190565b81518152602080830151908201526040918201516001600160a01b03169181019190915260600190565b60006020825260018060a01b03808451166020840152806020850151166040840152506040830151606083015260608301516080808401526140b760a0840182613a58565b949350505050565b6000602082528251600381106140d157fe5b8060208401525060018060a01b03602084015116604083015260ff604084015116606083015260608301516080808401526140b760a0840182613a58565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b90815260200190565b918252602082015260400190565b60405181810167ffffffffffffffff8111828210171561418357600080fd5b604052919050565b600067ffffffffffffffff8211156141a1578081fd5b50601f01601f191660200190565b60005b838110156141ca5781810151838201526020016141b2565b838111156122325750506000910152565b6001600160a01b03811681146141f057600080fd5b50565b6001600160701b03811681146141f057600080fd5b60ff811681146141f057600080fdfea26469706673582212202e8a91135556fe380f7faf3879002d0ecd7e30f048f320533ed7838f10be071a64736f6c6343000606003300000000000000000000000035c052bbf8338b06351782a565aa9aad173432ea0000000000000000000000002217aec3440e8fd6d49a118b1502e539f88dba5500000000000000000000000046fcde1b89d61f5cbfaab05c2914c367f8301f3000000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83

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

00000000000000000000000035c052bbf8338b06351782a565aa9aad173432ea0000000000000000000000002217aec3440e8fd6d49a118b1502e539f88dba5500000000000000000000000046fcde1b89d61f5cbfaab05c2914c367f8301f3000000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83

-----Decoded View---------------
Arg [0] : _factory (address): 0x35c052bbf8338b06351782a565aa9aad173432ea
Arg [1] : _bDeployer (address): 0x2217aec3440e8fd6d49a118b1502e539f88dba55
Arg [2] : _cDeployer (address): 0x46fcde1b89d61f5cbfaab05c2914c367f8301f30
Arg [3] : _WETH (address): 0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000035c052bbf8338b06351782a565aa9aad173432ea
Arg [1] : 0000000000000000000000002217aec3440e8fd6d49a118b1502e539f88dba55
Arg [2] : 00000000000000000000000046fcde1b89d61f5cbfaab05c2914c367f8301f30
Arg [3] : 00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83


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.