Contract 0xa516b9c7378799799e6dfadbdabf45d5b584405f 12

 
Txn Hash Method
Block
From
To
Value
0x5d5385a67152bfbf1001a54cf7e6c3a95a74a5bdaad146f431c7b4d7c0bfa8daRedeem1100818682023-09-26 21:08:331 day 16 hrs ago0x5849723254b4ed550ea20ac03ff9a86b56a47b46 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000817144110.094479763
0x4d2381087ea5735b5cff5b4e3947665f3ab9af069f7a94cd331631b7048c8c1bRedeem1100733912023-09-26 16:25:591 day 21 hrs ago0x7a093ce3c5ed1adf8f32f673e4da5beb9b6de432 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000848908960.058110095
0xa62e3e4a7fbf19185e7ef4a8955aa5bc1d86c4d9d2b4a9e221ecf3acfcca1e51Redeem1100566012023-09-26 7:06:192 days 6 hrs ago0x644b5eccdb246961d246298122a2bafa9a8d9fb2 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000316596680.079875116
0x4b051e3d9a779a2a6d5377a5a315119ff098c7e9f9e9274fa0a9b3e0997dbf27Redeem1100250942023-09-25 13:36:053 days 25 mins ago0x68db64a8cc0aea50b479bdd5bc3b3dd5e5821ed4 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000563097660.0565769
0x2809ebeb28ef2da963f4a0a49849a993e1174990f9a0b86286d49fb156bcf744Redeem1100235272023-09-25 12:43:513 days 1 hr ago0x68db64a8cc0aea50b479bdd5bc3b3dd5e5821ed4 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000348533010.0686509
0x95d6f32cbf21c29ba149674e5167eb4c027022cddfdfa4c7668b8ba146ecf7ecRedeem1097423412023-09-19 0:30:599 days 13 hrs ago0x8868a2eae35f1f53d3f8e464c060be9755c8d51c IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000270187090.055907038
0x43c9c38c9c1e28c1ee4a3be17fc8f091172a253aa80207e3d659b4f906b1fb6aRedeem1097418752023-09-19 0:15:279 days 13 hrs ago0xf59e9192ec0f86152f43e320a68b6537b314bea5 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000398902460.101658531
0x7f2fcb12278d10213789c96556e81202e8470798537e3c206a0122127b9cebf1Redeem1097414582023-09-19 0:01:339 days 13 hrs ago0x3a9bdd0ecf1612cb30442b41b615ebd2987a019d IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000347394260.102261323
0xac662dec0fde67eed8f1822e087858b493814a0dbade70f5834e2a9e94ab1a21Redeem1089299002023-08-31 5:09:3728 days 8 hrs ago0x681c48227361707ae8074699ccb5804966dcb1a2 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000354543740.0000007
0xc6944b8e97c68fe68505b235acdd3d268dbe4f07b754a134c3aadc0476dbb09aRedeem1089204962023-08-30 23:56:0928 days 14 hrs ago0xbebd2364664096c8d194194a209d81b62e37b13e IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000330355570.000239303
0xd21801fd5ce2a8d2a6b97486dca606417077b0057e4be355f80b7366412882b2Redeem1088962032023-08-30 10:26:2329 days 3 hrs ago0x6712b7f12d9d335a15b0cddeee7a061ee522bda0 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000425397120.000008568
0x11711835ec473cd90ffec9f4491d4c8357621e9a78e2ded5e3479f37b5065930Redeem1088709022023-08-29 20:23:0129 days 17 hrs ago0xad036a7e58dfa18a6511e85d29b0341e16bcbd9b IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0001147604780.01
0x1dcd8adfff6086ce4b25c57da413452bcf0e562c2988382810e455d98a4c4882Repay1088708762023-08-29 20:22:0929 days 17 hrs ago0xad036a7e58dfa18a6511e85d29b0341e16bcbd9b IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0001044384330.008
0xd06f86f9930792cd1b8f37198dd2a708329ee7e61798f8164bfc41381913c146Redeem1087857912023-08-27 21:05:5931 days 16 hrs ago0x592e1e16016c25651513591b7ebed5ca803ad39e IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000348273260.000000068
0x5d4567bacee47fff479569869ad817e2823568a1842fc17d1f01ee6e30270e74Redeem ETH1087810102023-08-27 18:26:3731 days 19 hrs ago0x9f620ccbcb854f15575bcefffc41dac3173f2b48 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000328040210.000000081
0x36508f27ee116de4c3e650ac616a42820942dd412c9399248b5d4c89bbadb86fRedeem ETH1087808502023-08-27 18:21:1731 days 19 hrs ago0x9f620ccbcb854f15575bcefffc41dac3173f2b48 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000308810270.000001225
0x338b095e2c331b977b92d0dab93fdce426e8263e10ce227e7793fe76eaa9034bDeleverage1087214662023-08-26 9:21:4933 days 4 hrs ago0x8caef18a4e4c68a1132ae195e628ef68043ccb05 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000315836360.000000065
0x74fee47e8a5140624912e3d30e05837ea01845a44e1af4a4e015323b6b2351a3Redeem1086869642023-08-25 14:11:4533 days 23 hrs ago0xca7fa71073504a399383aa5d6b596378ba6bf0d4 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000816081450.011640243
0x5191a8edb0ef0556feb637b0003bb21d8bbeb740f66df0672ae7079b16b05d47Redeem1086779202023-08-25 9:10:1734 days 4 hrs ago0x94dc0b13e66aba9450b3cc44c2643bbb4c264bc7 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000339989560.000000078
0x0acb28eb0f9b53b7b15464391edf30c97cef8894e31d404417e126da252b6728Repay1086779122023-08-25 9:10:0134 days 4 hrs ago0x94dc0b13e66aba9450b3cc44c2643bbb4c264bc7 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000314753860.000000079
0x23edf6a5990e75c53aad103bd7cc70aa09ac3b9def6aeacbc4c514ef2ca9ee25Redeem1086776612023-08-25 9:01:3934 days 4 hrs ago0x94dc0b13e66aba9450b3cc44c2643bbb4c264bc7 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000415040430.000000087
0x347ce47a19e1a2d70cad2419cf425dbc916653913c0709a577a0b6eba8560e37Redeem1086776382023-08-25 9:00:5334 days 5 hrs ago0x94dc0b13e66aba9450b3cc44c2643bbb4c264bc7 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000350787630.000000085
0x9c259802d6f8d3ab7f543d9229389273ba9a32f5d2ee19f9f028a04700546473Redeem1086575592023-08-24 21:51:3534 days 16 hrs ago 0x2837a728d3f73bb94bafb3b024ffe3a2834bf138 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000525686080.000053209
0xdba3750c3cd27539472151ba5b2ad2646ed0c0a9f718406474d2eabd349bcd5fRedeem1086157582023-08-23 22:38:1335 days 15 hrs ago0x6b6ca48da27304eeeb1d15d355d948f68b852733 IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.0000455707860.005250082
0xb8dccd7b107a1b690c4eaa442e049b401e2fa25500444ef5000d18a27862280fRedeem1085068092023-08-21 10:06:3538 days 3 hrs ago0x7d78ada72bbdad76d6906202f0abbf3c692ca9cf IN  0xa516b9c7378799799e6dfadbdabf45d5b584405f0 ETH0.000034100710.000009781
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x5d4567bacee47fff479569869ad817e2823568a1842fc17d1f01ee6e30270e741087810102023-08-27 18:26:3731 days 19 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f0x9f620ccbcb854f15575bcefffc41dac3173f2b480.000027380325949219 ETH
0x5d4567bacee47fff479569869ad817e2823568a1842fc17d1f01ee6e30270e741087810102023-08-27 18:26:3731 days 19 hrs ago Wrapped Ether 0xa516b9c7378799799e6dfadbdabf45d5b584405f0.000027380325949219 ETH
0x36508f27ee116de4c3e650ac616a42820942dd412c9399248b5d4c89bbadb86f1087808502023-08-27 18:21:1731 days 19 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f0x9f620ccbcb854f15575bcefffc41dac3173f2b480.000053909101050815 ETH
0x36508f27ee116de4c3e650ac616a42820942dd412c9399248b5d4c89bbadb86f1087808502023-08-27 18:21:1731 days 19 hrs ago Wrapped Ether 0xa516b9c7378799799e6dfadbdabf45d5b584405f0.000053909101050815 ETH
0x99ec3c7af1ed89bd1735d850ea6b059f5a5cc964fa37926cf18ca92c46ed36d61083812042023-08-18 12:19:4541 days 1 hr ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f0x88cfada6460030eaa7d06d8d4665e55546eb8dbc0.040436409024475829 ETH
0x99ec3c7af1ed89bd1735d850ea6b059f5a5cc964fa37926cf18ca92c46ed36d61083812042023-08-18 12:19:4541 days 1 hr ago Wrapped Ether 0xa516b9c7378799799e6dfadbdabf45d5b584405f0.040436409024475829 ETH
0xda6eb9dcf8ab34be966aba117e7ec83475020860096a6af0521d258a6637b8ae1079704132023-08-09 0:06:4350 days 13 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f0x70140ee8dd045cf98527ee0df065f41f3b1f62ab0.09339223560045022 ETH
0xda6eb9dcf8ab34be966aba117e7ec83475020860096a6af0521d258a6637b8ae1079704132023-08-09 0:06:4350 days 13 hrs ago Wrapped Ether 0xa516b9c7378799799e6dfadbdabf45d5b584405f0.09339223560045022 ETH
0x4d6915e713068caa83e590469c15ef0f5deafcc2c47d409f0640ebc82646168d1077189562023-08-03 4:24:4956 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f0x681c48227361707ae8074699ccb5804966dcb1a20.100620164579711778 ETH
0x4d6915e713068caa83e590469c15ef0f5deafcc2c47d409f0640ebc82646168d1077189562023-08-03 4:24:4956 days 9 hrs ago Wrapped Ether 0xa516b9c7378799799e6dfadbdabf45d5b584405f0.100620164579711778 ETH
0x670ffc00adef6bccb927a0a911804c9d3c85c6fd0fe5bff941d200e4535ccdda1075485202023-07-30 5:43:3760 days 8 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x1635353098ffb668e049c41e4d1546af682bc7980 ETH
0x670ffc00adef6bccb927a0a911804c9d3c85c6fd0fe5bff941d200e4535ccdda1075485202023-07-30 5:43:3760 days 8 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x7f5c764cbc14f9669b88837ca1490cca17c316070 ETH
0x670ffc00adef6bccb927a0a911804c9d3c85c6fd0fe5bff941d200e4535ccdda1075485202023-07-30 5:43:3760 days 8 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x1635353098ffb668e049c41e4d1546af682bc7980 ETH
0x76b62bc2c9de459ab7e20b224a0d3526629b43db363026b3b2063f1d03ed1d8c1075469722023-07-30 4:52:0160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x7175bf125e3294d19c33b30f256cff90f74149900 ETH
0x76b62bc2c9de459ab7e20b224a0d3526629b43db363026b3b2063f1d03ed1d8c1075469722023-07-30 4:52:0160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405fWrapped Ether0 ETH
0x76b62bc2c9de459ab7e20b224a0d3526629b43db363026b3b2063f1d03ed1d8c1075469722023-07-30 4:52:0160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x7175bf125e3294d19c33b30f256cff90f74149900 ETH
0x4f5a0266131f2b42e8192f68416c794f121112ce3d40cfb6f3c9a96d3fc225671075465272023-07-30 4:37:1160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x1635353098ffb668e049c41e4d1546af682bc7980 ETH
0x4f5a0266131f2b42e8192f68416c794f121112ce3d40cfb6f3c9a96d3fc225671075465272023-07-30 4:37:1160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x7f5c764cbc14f9669b88837ca1490cca17c316070 ETH
0x4f5a0266131f2b42e8192f68416c794f121112ce3d40cfb6f3c9a96d3fc225671075465272023-07-30 4:37:1160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x1635353098ffb668e049c41e4d1546af682bc7980 ETH
0x4f5a0266131f2b42e8192f68416c794f121112ce3d40cfb6f3c9a96d3fc225671075465272023-07-30 4:37:1160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x1635353098ffb668e049c41e4d1546af682bc7980 ETH
0x95cf115bc5db0044f289c383ba8b1982ff405ed7efe8401c8c0e68a1a05d3a8e1075464822023-07-30 4:35:4160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0xdb37a76ffc5aaf97a40c0d542ff7a4eca33380ab0 ETH
0x95cf115bc5db0044f289c383ba8b1982ff405ed7efe8401c8c0e68a1a05d3a8e1075464822023-07-30 4:35:4160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0x7f5c764cbc14f9669b88837ca1490cca17c316070 ETH
0x95cf115bc5db0044f289c383ba8b1982ff405ed7efe8401c8c0e68a1a05d3a8e1075464822023-07-30 4:35:4160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0xdb37a76ffc5aaf97a40c0d542ff7a4eca33380ab0 ETH
0x95cf115bc5db0044f289c383ba8b1982ff405ed7efe8401c8c0e68a1a05d3a8e1075464822023-07-30 4:35:4160 days 9 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0xdb37a76ffc5aaf97a40c0d542ff7a4eca33380ab0 ETH
0xe7bd73fa1a898e2befdee046b352ff424c10de98025cf594db1a16edfbdfc92d1075392452023-07-30 0:34:2760 days 13 hrs ago 0xa516b9c7378799799e6dfadbdabf45d5b584405f 0xce38d8514b234bab4df7ec682ec3419f6c228d8c0 ETH
[ 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
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"0ce222c490e6a979b4b9c9f0123cd04e86cbb4dc2b3e3d0de21ebe638fee6938" // 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"326662b4eab5ef52fa98ce27b557770bbf166e66fe2b9c9877b907cca7504017" // 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",
        "devdoc",
        "userdoc",
        "metadata",
        "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"}]

6101006040523480156200001257600080fd5b50604051620043d6380380620043d6833981016040819052620000359162000083565b6001600160601b0319606094851b811660805292841b831660a05290831b821660c05290911b1660e052620000e3565b80516001600160a01b03811681146200007d57600080fd5b92915050565b6000806000806080858703121562000099578384fd5b620000a5868662000065565b9350620000b6866020870162000065565b9250620000c7866040870162000065565b9150620000d8866060870162000065565b905092959194509250565b60805160601c60a05160601c60c05160601c60e05160601c61424d620001896000398061017a528061080d5280610879528061098852806109f15280610b8a5280610bde5280610c6452806117fa528061184152806118b95280611be75280611d985280611dec5280611e72528061301e528061306d525080611b285280611b4e525080611c2f5280611fcc525080611b6f5280611c0b5280611fed525061424d6000f3fe60806040526004361061016a5760003560e01c80636b4d4dc1116100d1578063ad5c46481161008a578063dbe5f2fb11610064578063dbe5f2fb1461044f578063eb03419a1461046f578063ef974e9c14610482578063fcb2a895146104a2576101a3565b8063ad5c464814610410578063c45a015514610425578063db5a26901461043a576101a3565b80636b4d4dc1146103685780636d29e7fc14610388578063703de94c146103a857806377370d62146103bb5780637a4660d5146103db5780639b56d6c9146103f0576101a3565b80633970036a116101235780633970036a1461028d5780633c173a4f146102ba57806343e26448146102da5780635c1e6404146102fa57806367bf252f146103285780636aee7c1e14610348576101a3565b80630572bf5f146101a85780631f1cc5bc146101e05780632b005cfc1461020d5780632c3445041461022d578063338c4ccb1461024d57806335bb10591461027a576101a3565b366101a357336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101a157fe5b005b600080fd5b3480156101b457600080fd5b506101c86101c336600461326e565b6104c2565b6040516101d793929190613c88565b60405180910390f35b3480156101ec57600080fd5b506102006101fb3660046134b2565b6104f2565b6040516101d7919061414d565b34801561021957600080fd5b506102006102283660046134b2565b61076d565b34801561023957600080fd5b506101a16102483660046134b2565b6108ea565b34801561025957600080fd5b5061026d61026836600461326e565b610a6b565b6040516101d79190613cc4565b6102006102883660046132f6565b610aea565b34801561029957600080fd5b506102ad6102a836600461326e565b610d83565b6040516101d79190613b9b565b3480156102c657600080fd5b506102006102d5366004613401565b610e18565b3480156102e657600080fd5b506102006102f5366004613438565b610ec2565b34801561030657600080fd5b5061031a6103153660046133a7565b61118f565b6040516101d7929190614156565b34801561033457600080fd5b506101a16103433660046135c3565b6112c9565b34801561035457600080fd5b50610200610363366004613401565b6113c0565b34801561037457600080fd5b506101a1610383366004613526565b6114e5565b34801561039457600080fd5b506101a16103a3366004613336565b6115c1565b6102006103b63660046132f6565b61175a565b3480156103c757600080fd5b506101a16103d6366004613692565b6118e0565b3480156103e757600080fd5b506102ad611b26565b3480156103fc57600080fd5b506102ad61040b36600461326e565b611b4a565b34801561041c57600080fd5b506102ad611be5565b34801561043157600080fd5b506102ad611c09565b34801561044657600080fd5b506102ad611c2d565b34801561045b57600080fd5b506101a161046a3660046134b2565b611c51565b61031a61047d3660046132a6565b611cf7565b34801561048e57600080fd5b506102ad61049d36600461370d565b611fa5565b3480156104ae57600080fd5b5061031a6104bd366004613580565b612066565b60008060006104d084611b4a565b92506104dd846000611fa5565b91506104ea846001611fa5565b929491935050565b6000824281101561051e5760405162461bcd60e51b815260040161051590613f96565b60405180910390fd5b61052a87878686612181565b6040516323b872dd60e01b81526001600160a01b038816906323b872dd9061055a9033908b908b90600401613c23565b602060405180830381600087803b15801561057457600080fd5b505af1158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190613745565b506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156105e857600080fd5b505afa1580156105fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610620919061328a565b905061062b81610a6b565b15610735576040516395a2251f60e01b81526001600160a01b038916906395a2251f9061065c908490600401613b9b565b602060405180830381600087803b15801561067657600080fd5b505af115801561068a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ae9190613a1d565b506040516395a2251f60e01b81526001600160a01b038216906395a2251f906106db908990600401613b9b565b602060405180830381600087803b1580156106f557600080fd5b505af1158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d9190613a1d565b925050610763565b6040516395a2251f60e01b81526001600160a01b038916906395a2251f906106db908990600401613b9b565b505b5095945050505050565b600082428110156107905760405162461bcd60e51b815260040161051590613f96565b86806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610802919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146108525760405162461bcd60e51b815260040161051590613f67565b61085f88883088886104f2565b604051632e1a7d4d60e01b81529093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906108ae90869060040161414d565b600060405180830381600087803b1580156108c857600080fd5b505af11580156108dc573d6000803e3d6000fd5b505050506107618684612238565b814281101561090b5760405162461bcd60e51b815260040161051590613f96565b85806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561094557600080fd5b505afa158015610959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097d919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146109cd5760405162461bcd60e51b815260040161051590613f67565b6109da8787308787611c51565b604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90610a2690899060040161414d565b600060405180830381600087803b158015610a4057600080fd5b505af1158015610a54573d6000803e3d6000fd5b50505050610a628587612238565b50505050505050565b6000816001600160a01b0316636ee272276040518163ffffffff1660e01b815260040160206040518083038186803b158015610aa657600080fd5b505afa925050508015610ad6575060408051601f3d908101601f19168201909252610ad391810190613745565b60015b610ae257506000610ae5565b90505b919050565b60008142811015610b0d5760405162461bcd60e51b815260040161051590613f96565b84806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4757600080fd5b505afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610bcf5760405162461bcd60e51b815260040161051590613f67565b610bda8634876122ca565b92507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250610c9e915089908790600401613cab565b602060405180830381600087803b158015610cb857600080fd5b505af1158015610ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf09190613745565b610cf657fe5b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03881691631e7dcc0d91610d34918991819060248101613baf565b600060405180830381600087803b158015610d4e57600080fd5b505af1158015610d62573d6000803e3d6000fd5b5050505082341115610d7a57610d7a33843403612238565b50509392505050565b6000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610dbe57600080fd5b505afa925050508015610dee575060408051601f3d908101601f19168201909252610deb9181019061328a565b60015b610df9575080610ae5565b6001600160a01b03811615610e0f579050610ae5565b82915050610ae5565b60008142811015610e3b5760405162461bcd60e51b815260040161051590613f96565b610eb886876001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e7857600080fd5b505afa158015610e8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb0919061328a565b8733886123b8565b9695505050505050565b60008342811015610ee55760405162461bcd60e51b815260040161051590613f96565b6000886001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2057600080fd5b505afa158015610f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f58919061328a565b9050610f6381610a6b565b15611131576000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa357600080fd5b505afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061328a565b905061101f818a8989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b61102b8133848c612465565b6040516335313c2160e11b81526001600160a01b03831690636a62784290611057908d90600401613b9b565b602060405180830381600087803b15801561107157600080fd5b505af1158015611085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a99190613a1d565b506040516335313c2160e11b81526001600160a01b038b1690636a627842906110d6908b90600401613b9b565b602060405180830381600087803b1580156110f057600080fd5b505af1158015611104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111289190613a1d565b93505050611184565b61117381898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b61118089828a338b6123b8565b9250505b509695505050505050565b60008082428110156111b35760405162461bcd60e51b815260040161051590613f96565b6111be8888886122ca565b925061123c886001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156111fc57600080fd5b505afa158015611210573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611234919061328a565b338a86612465565b6040516386b9d81f60e01b81526001600160a01b038916906386b9d81f9061126a9089908990600401613c6e565b602060405180830381600087803b15801561128457600080fd5b505af1158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc9190613a1d565b9150509550959350505050565b84428110156112ea5760405162461bcd60e51b815260040161051590613f96565b6113366112f88d6000611fa5565b8c8888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061254e92505050565b6113826113448d6001611fa5565b8b8886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061254e92505050565b600061138d8d610d83565b905060008061139f838f8f8f8f612066565b915091506113af8f83838d6125c7565b505050505050505050505050505050565b600081428110156113e35760405162461bcd60e51b815260040161051590613f96565b6113ee8686866122ca565b915061146c866001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561142c57600080fd5b505afa158015611440573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611464919061328a565b338885612465565b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03881691631e7dcc0d916114aa918891819060248101613baf565b600060405180830381600087803b1580156114c457600080fd5b505af11580156114d8573d6000803e3d6000fd5b5050505050949350505050565b6114ed613125565b6114f9828401846138c4565b9050600061150a8260200151611b4a565b90506001600160a01b03861630146115345760405162461bcd60e51b815260040161051590613d4e565b336001600160a01b0382161461155c5760405162461bcd60e51b815260040161051590613ce2565b60028251600281111561156b57fe5b14156101a35761157961314c565b8260600151806020019051810190611591919061396d565b9050610a6283602001518260000151836020015184604001518560600151866080015161277c565b505050505050565b6115c9613125565b6115d5828401846138c4565b905060006115eb82602001518360400151611fa5565b90506001600160a01b03871630146116155760405162461bcd60e51b815260040161051590613d4e565b336001600160a01b0382161461163d5760405162461bcd60e51b815260040161051590613ce2565b60008251600281111561164c57fe5b14156116965761165a613184565b826060015180602001905181019061167291906137b0565b90506116908360200151826000015183602001518460400151612af5565b50610a62565b6001825160028111156116a557fe5b14156101a3576116b36131ae565b82606001518060200190518101906116cb91906137f3565b905060006116de84602001516001611fa5565b8251602084015160408086015160608701519151631e7dcc0d60e01b81529495506001600160a01b03861694631e7dcc0d94611721949093909291600401613baf565b600060405180830381600087803b15801561173b57600080fd5b505af115801561174f573d6000803e3d6000fd5b505050505050610a62565b6000814281101561177d5760405162461bcd60e51b815260040161051590613f96565b84806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156117b757600080fd5b505afa1580156117cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ef919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461183f5760405162461bcd60e51b815260040161051590613f67565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561189a57600080fd5b505af11580156118ae573d6000803e3d6000fd5b5050505050610eb8867f00000000000000000000000000000000000000000000000000000000000000003430896123b8565b82428110156119015760405162461bcd60e51b815260040161051590613f96565b600061190c89611b4a565b90506000816001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561194b57600080fd5b505af115801561195f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119839190613a1d565b9050600089116119a55760405162461bcd60e51b815260040161051590614011565b60006119d3670de0b6b3a76400006119c76000198d018563ffffffff612da216565b9063ffffffff612de516565b9050611a17838b8989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061218192505050565b604080516080810190915260609080600281526020018d6001600160a01b03168152602001600060ff1681526020016040518060a00160405280336001600160a01b031681526020018e81526020018581526020018d81526020018c815250604051602001611a86919061410f565b60408051601f19818403018152918152915251611aa691906020016140bf565b60408051601f19818403018152908290526319f3400d60e01b825291506001600160a01b038516906319f3400d90611ae690309086908690600401613c47565b600060405180830381600087803b158015611b0057600080fd5b505af1158015611b14573d6000803e3d6000fd5b50505050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083604051602001611ba0929190613a84565b60405160208183030381529060405280519060200120604051602001611bc7929190613b4a565b60408051601f19818403018152919052805160209091012092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b8142811015611c725760405162461bcd60e51b815260040161051590613f96565b611c7e8686858561254e565b60408051600081526020810191829052631e7dcc0d60e01b9091526001600160a01b03871690631e7dcc0d90611cbd90339088908a9060248101613baf565b600060405180830381600087803b158015611cd757600080fd5b505af1158015611ceb573d6000803e3d6000fd5b50505050505050505050565b6000808242811015611d1b5760405162461bcd60e51b815260040161051590613f96565b86806001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015611d5557600080fd5b505afa158015611d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8d919061328a565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611ddd5760405162461bcd60e51b815260040161051590613f67565b611de88834896122ca565b93507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e4557600080fd5b505af1158015611e59573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb9250611eac91508b908890600401613cab565b602060405180830381600087803b158015611ec657600080fd5b505af1158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe9190613745565b611f0457fe5b6040516386b9d81f60e01b81526001600160a01b038916906386b9d81f90611f32908a908a90600401613c6e565b602060405180830381600087803b158015611f4c57600080fd5b505af1158015611f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f849190613a1d565b925083341115611f9a57611f9a33853403612238565b505094509492505050565b600060028260ff1610611fca5760405162461bcd60e51b815260040161051590613d17565b7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000848460405160200161202093929190613aa6565b60405160208183030381529060405280519060200120604051602001612047929190613af9565b60408051601f1981840301815291905280516020909101209392505050565b600080600080886001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156120a557600080fd5b505afa1580156120b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120dd91906139c9565b506001600160701b031691506001600160701b031691506000612101898484612e27565b9050878111612135578581101561212a5760405162461bcd60e51b815260040161051590613e6c565b889450925082612174565b6000612142898486612e27565b90508981111561214e57fe5b8781101561216e5760405162461bcd60e51b815260040161051590613e2a565b94508793505b5050509550959350505050565b805161218c57612232565b600080600080848060200190518101906121a69190613765565b93509350935093506000846121bb57876121bf565b6000195b60405163d505accf60e01b81529091506001600160a01b038a169063d505accf906121fa903390309086908d908b908b908b90600401613be2565b600060405180830381600087803b15801561221457600080fd5b505af1158015612228573d6000803e3d6000fd5b5050505050505050505b50505050565b604080516000808252602082019092526001600160a01b0384169083906040516122629190613add565b60006040518083038185875af1925050503d806000811461229f576040519150601f19603f3d011682016040523d82523d6000602084013e6122a4565b606091505b50509050806122c55760405162461bcd60e51b815260040161051590613dd6565b505050565b6000836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b50506040516326b9f4dd60e11b8152600092506001600160a01b0387169150634d73e9ba9061234e908690600401613b9b565b60206040518083038186803b15801561236657600080fd5b505afa15801561237a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239e9190613a1d565b90508084106123ad57806123af565b835b95945050505050565b60006001600160a01b0383163014156123db576123d6858786612e95565b6123e7565b6123e785848887612465565b6040516335313c2160e11b81526001600160a01b03871690636a62784290612413908590600401613b9b565b602060405180830381600087803b15801561242d57600080fd5b505af1158015612441573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb89190613a1d565b60006060856001600160a01b03166323b872dd86868660405160240161248d93929190613c23565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516124c69190613add565b6000604051808303816000865af19150503d8060008114612503576040519150601f19603f3d011682016040523d82523d6000602084013e612508565b606091505b50915091508180156125325750805115806125325750808060200190518101906125329190613745565b6115b95760405162461bcd60e51b815260040161051590613d85565b805161255957612232565b600080600080848060200190518101906125739190613765565b9350935093509350600084612588578761258c565b6000195b60405163279e6d5760e21b81529091506001600160a01b038a1690639e79b55c906121fa903390309086908d908b908b908b90600401613be2565b60006125d4856000611fa5565b905060606040518060800160405280600060028111156125f057fe5b8152602001876001600160a01b03168152602001600160ff1681526020016040518060600160405280888152602001878152602001866001600160a01b03168152506040516020016126429190614048565b60408051601f1981840301815291815291525161266291906020016140bf565b60408051601f198184030181526080830190915291506060908060018152602001886001600160a01b03168152602001600060ff1681526020016040518060800160405280336001600160a01b03168152602001306001600160a01b03168152602001888152602001858152506040516020016126df9190614072565b60408051601f198184030181529181529152516126ff91906020016140bf565b60408051601f1981840301815290829052631e7dcc0d60e01b825291506001600160a01b03841690631e7dcc0d9061274190339030908b908790600401613baf565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b5050505050505050505050565b600080600061278a896104c2565b9250925092506000826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156127cb57600080fd5b505afa1580156127df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612803919061328a565b90506000826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561284057600080fd5b505afa158015612854573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612878919061328a565b905060006128858c610d83565b60405163a9059cbb60e01b81529091506001600160a01b038d169063a9059cbb906128b6908f908d90600401613cab565b602060405180830381600087803b1580156128d057600080fd5b505af11580156128e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129089190613745565b506129128c610a6b565b15612997576040516395a2251f60e01b81526001600160a01b038d16906395a2251f90612943908490600401613b9b565b602060405180830381600087803b15801561295d57600080fd5b505af1158015612971573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129959190613a1d565b505b600080826001600160a01b03166389afcb44306040518263ffffffff1660e01b81526004016129c69190613b9b565b6040805180830381600087803b1580156129df57600080fd5b505af11580156129f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a179190613a35565b9150915089821015612a3b5760405162461bcd60e51b815260040161051590613e2a565b88811015612a5b5760405162461bcd60e51b815260040161051590613e6c565b612a6787868f85612f83565b612a7386858f84612f83565b876001600160a01b03166323b872dd8e8a8f6040518463ffffffff1660e01b8152600401612aa393929190613c23565b602060405180830381600087803b158015612abd57600080fd5b505af1158015612ad1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113af9190613745565b6000806000612b03876104c2565b9250925092506000612b1488610d83565b9050612b91836001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612b5257600080fd5b505afa158015612b66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8a919061328a565b8289612e95565b612c0c826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612bcd57600080fd5b505afa158015612be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c05919061328a565b8288612e95565b612c1588610a6b565b15612c9a576040516335313c2160e11b81526001600160a01b03821690636a62784290612c46908b90600401613b9b565b602060405180830381600087803b158015612c6057600080fd5b505af1158015612c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c989190613a1d565b505b6040516335313c2160e11b81526001600160a01b03891690636a62784290612cc6908790600401613b9b565b602060405180830381600087803b158015612ce057600080fd5b505af1158015612cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d189190613a1d565b506040516335313c2160e11b81526001600160a01b03851690636a62784290612d45908890600401613b9b565b602060405180830381600087803b158015612d5f57600080fd5b505af1158015612d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d979190613a1d565b505050505050505050565b600082612db157506000612ddf565b82820282848281612dbe57fe5b0414612ddc5760405162461bcd60e51b815260040161051590613f26565b90505b92915050565b6000612ddc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130ee565b6000808411612e485760405162461bcd60e51b815260040161051590613eae565b600083118015612e585750600082115b612e745760405162461bcd60e51b815260040161051590613ee3565b82612e85858463ffffffff612da216565b81612e8c57fe5b04949350505050565b60006060846001600160a01b031663a9059cbb8585604051602401612ebb929190613cab565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612ef49190613add565b6000604051808303816000865af19150503d8060008114612f31576040519150601f19603f3d011682016040523d82523d6000602084013e612f36565b606091505b5091509150818015612f60575080511580612f60575080806020019051810190612f609190613745565b612f7c5760405162461bcd60e51b815260040161051590613fc4565b5050505050565b6000612f908583856122ca565b9050612f9d848683612e95565b6040805160008082526020820192839052631e7dcc0d60e01b9092526001600160a01b03871691631e7dcc0d91612fdb918791819060248101613baf565b600060405180830381600087803b158015612ff557600080fd5b505af1158015613009573d6000803e3d6000fd5b5050505080821115612f7c57600081830390507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b031614156130e357604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d906130a290849060040161414d565b600060405180830381600087803b1580156130bc57600080fd5b505af11580156130d0573d6000803e3d6000fd5b505050506130de8482612238565b6115b9565b6115b9858583612e95565b6000818361310f5760405162461bcd60e51b81526004016105159190613ccf565b50600083858161311b57fe5b0495945050505050565b60408051608081019091528060008152600060208201819052604082015260609081015290565b6040518060a0016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6040518060600160405280600081526020016000815260200160006001600160a01b031681525090565b604080516080810182526000808252602082018190529181019190915260608082015290565b60008083601f8401126131e5578182fd5b50813567ffffffffffffffff8111156131fc578182fd5b60208301915083602082850101111561321457600080fd5b9250929050565b600082601f83011261322b578081fd5b813561323e6132398261418b565b614164565b915080825283602082850101111561325557600080fd5b8060208401602084013760009082016020015292915050565b60006020828403121561327f578081fd5b8135612ddc816141db565b60006020828403121561329b578081fd5b8151612ddc816141db565b600080600080608085870312156132bb578283fd5b84356132c6816141db565b935060208501356132d6816141db565b925060408501356132e6816141db565b9396929550929360600135925050565b60008060006060848603121561330a578283fd5b8335613315816141db565b92506020840135613325816141db565b929592945050506040919091013590565b60008060008060006080868803121561334d578081fd5b8535613358816141db565b94506020860135613368816141db565b935060408601359250606086013567ffffffffffffffff81111561338a578182fd5b613396888289016131d4565b969995985093965092949392505050565b600080600080600060a086880312156133be578283fd5b85356133c9816141db565b94506020860135935060408601356133e0816141db565b925060608601356133f0816141db565b949793965091946080013592915050565b60008060008060808587031215613416578182fd5b8435613421816141db565b93506020850135925060408501356132e6816141db565b60008060008060008060a08789031215613450578384fd5b863561345b816141db565b9550602087013594506040870135613472816141db565b935060608701359250608087013567ffffffffffffffff811115613494578182fd5b6134a089828a016131d4565b979a9699509497509295939492505050565b600080600080600060a086880312156134c9578283fd5b85356134d4816141db565b94506020860135935060408601356134eb816141db565b925060608601359150608086013567ffffffffffffffff81111561350d578182fd5b6135198882890161321b565b9150509295509295909350565b6000806000806060858703121561353b578182fd5b8435613546816141db565b935060208501359250604085013567ffffffffffffffff811115613568578283fd5b613574878288016131d4565b95989497509550505050565b600080600080600060a08688031215613597578283fd5b85356135a2816141db565b97602087013597506040870135966060810135965060800135945092505050565b60008060008060008060008060008060006101208c8e0312156135e4578889fd5b6135ee8c356141db565b8b359a5060208c0135995060408c0135985060608c0135975060808c0135965061361b60a08d01356141db565b60a08c0135955060c08c0135945067ffffffffffffffff8060e08e01351115613642578485fd5b6136528e60e08f01358f016131d4565b90955093506101008d0135811015613668578283fd5b5061367a8d6101008e01358e016131d4565b81935080925050509295989b509295989b9093969950565b600080600080600080600060c0888a0312156136ac578081fd5b87356136b7816141db565b96506020880135955060408801359450606088013593506080880135925060a088013567ffffffffffffffff8111156136ee578182fd5b6136fa8a828b016131d4565b989b979a50959850939692959293505050565b6000806040838503121561371f578182fd5b823561372a816141db565b9150602083013561373a81614208565b809150509250929050565b600060208284031215613756578081fd5b81518015158114612ddc578182fd5b6000806000806080858703121561377a578182fd5b84518015158114613789578283fd5b602086015190945061379a81614208565b6040860151606090960151949790965092505050565b6000606082840312156137c1578081fd5b6137cb6060614164565b825181526020830151602082015260408301516137e7816141db565b60408201529392505050565b60006020808385031215613805578182fd5b825167ffffffffffffffff8082111561381c578384fd5b8185016080818803121561382e578485fd5b6138386080614164565b92508051613845816141db565b835280840151613854816141db565b8385015260408181015190840152606081015182811115613873578586fd5b019050601f81018613613884578384fd5b80516138926132398261418b565b81815287858385010111156138a5578586fd5b6138b4828683018786016141af565b6060840152509095945050505050565b6000602082840312156138d5578081fd5b813567ffffffffffffffff808211156138ec578283fd5b818401608081870312156138fe578384fd5b6139086080614164565b9250803560038110613918578485fd5b83526020810135613928816141db565b6020840152604081013561393b81614208565b6040840152606081013582811115613951578485fd5b61395d8782840161321b565b6060850152509195945050505050565b600060a0828403121561397e578081fd5b61398860a0614164565b8251613993816141db565b80825250602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b6000806000606084860312156139dd578081fd5b83516139e8816141f3565b60208501519093506139f9816141f3565b604085015190925063ffffffff81168114613a12578182fd5b809150509250925092565b600060208284031215613a2e578081fd5b5051919050565b60008060408385031215613a47578182fd5b505080516020909101519092909150565b60008151808452613a708160208601602086016141af565b601f01601f19169290920160200192915050565b6001600160601b0319606093841b811682529190921b16601482015260280190565b606093841b6001600160601b031990811682529290931b909116601483015260f81b6001600160f81b031916602882015260290190565b60008251613aef8184602087016141af565b9190910192915050565b6001600160f81b0319815260609290921b6001600160601b031916600183015260158201527f0ce222c490e6a979b4b9c9f0123cd04e86cbb4dc2b3e3d0de21ebe638fee6938603582015260550190565b6001600160f81b0319815260609290921b6001600160601b031916600183015260158201527f326662b4eab5ef52fa98ce27b557770bbf166e66fe2b9c9877b907cca7504017603582015260550190565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090610eb890830184613a58565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060018060a01b0385168252836020830152606060408301526123af6060830184613a58565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612ddc6020830184613a58565b6020808252818101527f5461726f74526f757465723a20554e415554484f52495a45445f43414c4c4552604082015260600190565b6020808252601b908201527f5461726f74526f757465723a20494e4445585f544f4f5f484947480000000000604082015260600190565b6020808252601e908201527f5461726f74526f757465723a2053454e4445525f4e4f545f524f555445520000604082015260600190565b60208082526031908201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604082015270185b9cd9995c919c9bdb4819985a5b1959607a1b606082015260800190565b60208082526034908201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60408201527308115512081d1c985b9cd9995c8819985a5b195960621b606082015260800190565b60208082526022908201527f5461726f74526f757465723a20494e53554646494349454e545f415f414d4f55604082015261139560f21b606082015260800190565b60208082526022908201527f5461726f74526f757465723a20494e53554646494349454e545f425f414d4f55604082015261139560f21b606082015260800190565b6020808252818101527f5461726f74526f757465723a20494e53554646494349454e545f414d4f554e54604082015260600190565b60208082526023908201527f5461726f74526f757465723a20494e53554646494349454e545f4c495155494460408201526249545960e81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601590820152740a8c2e4dee8a4deeae8cae474409c9ea8beae8aa89605b1b604082015260600190565b60208082526014908201527315185c9bdd149bdd5d195c8e881156141254915160621b604082015260600190565b6020808252602d908201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260408201526c185b9cd9995c8819985a5b1959609a1b606082015260800190565b60208082526018908201527f5461726f74526f757465723a2052454445454d5f5a45524f0000000000000000604082015260600190565b81518152602080830151908201526040918201516001600160a01b03169181019190915260600190565b60006020825260018060a01b03808451166020840152806020850151166040840152506040830151606083015260608301516080808401526140b760a0840182613a58565b949350505050565b6000602082528251600381106140d157fe5b8060208401525060018060a01b03602084015116604083015260ff604084015116606083015260608301516080808401526140b760a0840182613a58565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b90815260200190565b918252602082015260400190565b60405181810167ffffffffffffffff8111828210171561418357600080fd5b604052919050565b600067ffffffffffffffff8211156141a1578081fd5b50601f01601f191660200190565b60005b838110156141ca5781810151838201526020016141b2565b838111156122325750506000910152565b6001600160a01b03811681146141f057600080fd5b50565b6001600160701b03811681146141f057600080fd5b60ff811681146141f057600080fdfea2646970667358221220d840ec919a44ae29b15ca37a5d92a84404bc9716b697eb21393338b06d5e870d64736f6c63430006060033000000000000000000000000d7cabef2c1fd77a31c5ba97c724b82d3e25fc83c000000000000000000000000952e9c6391d9c0f6c6174d395aa9b4ec1030335a000000000000000000000000eb5809eb0f79aab6e53e6374258b29a244dfc12d0000000000000000000000004200000000000000000000000000000000000006

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

000000000000000000000000d7cabef2c1fd77a31c5ba97c724b82d3e25fc83c000000000000000000000000952e9c6391d9c0f6c6174d395aa9b4ec1030335a000000000000000000000000eb5809eb0f79aab6e53e6374258b29a244dfc12d0000000000000000000000004200000000000000000000000000000000000006

-----Decoded View---------------
Arg [0] : _factory (address): 0xD7cABeF2c1fD77a31c5ba97C724B82d3e25fC83C
Arg [1] : _bDeployer (address): 0x952e9c6391d9C0f6C6174D395Aa9B4eC1030335A
Arg [2] : _cDeployer (address): 0xEb5809eb0f79aaB6e53E6374258b29A244Dfc12d
Arg [3] : _WETH (address): 0x4200000000000000000000000000000000000006

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000d7cabef2c1fd77a31c5ba97c724b82d3e25fc83c
Arg [1] : 000000000000000000000000952e9c6391d9c0f6c6174d395aa9b4ec1030335a
Arg [2] : 000000000000000000000000eb5809eb0f79aab6e53e6374258b29a244dfc12d
Arg [3] : 0000000000000000000000004200000000000000000000000000000000000006


Block Transaction Difficulty Gas Used Reward
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.