AVAX Price: $22.29 (+3.27%)
Gas: 2.8 nAVAX
 

Overview

AVAX Balance

Avalanche C-Chain LogoAvalanche C-Chain LogoAvalanche C-Chain Logo0 AVAX

AVAX Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0xd4a18269590846092025-03-22 14:18:0632 days ago1742653086IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.000248551.2
0xd4a18269590845972025-03-22 14:17:4232 days ago1742653062IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.000419221.2
0xd4a18269447361132024-04-27 15:56:14361 days ago1714233374IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0029140426.52
0xd4a18269430794272024-03-18 23:47:33400 days ago1710805653IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0027481225.01
0xd4a18269409862602024-01-29 13:04:14450 days ago1706533454IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0028465931.25
0xd4a18269396824842023-12-29 20:16:51480 days ago1703881011IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0024586926.5
0xd4a18269366645372023-10-19 21:51:10551 days ago1697752270IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.3134845226
0xd4a18269362675512023-10-10 8:42:47561 days ago1696927367IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0311640226.5
0xd4a18269362675072023-10-10 8:41:17561 days ago1696927277IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1412329227.14683506
0xd4a18269361597842023-10-07 18:30:19563 days ago1696703419IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.075838626.5
0xd4a18269360893212023-10-06 3:13:28565 days ago1696562008IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0026098726.5
0xd4a18269360893082023-10-06 3:13:02565 days ago1696561982IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0038625326.5
0xd4a18269358747632023-10-01 2:04:34570 days ago1696125874IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1033826226.5
0xd4a18269357792672023-09-28 19:22:09572 days ago1695928929IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0443762326.5
0xd4a18269355630292023-09-23 16:53:08577 days ago1695487988IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1102123826.5
0xd4a18269354231452023-09-20 9:35:50581 days ago1695202550IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.011233426.5
0xd4a18269353288352023-09-18 4:09:40583 days ago1695010180IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0048370126.71746805
0xd4a18269353288312023-09-18 4:09:32583 days ago1695010172IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0050770626.71746805
0xd4a18269353288142023-09-18 4:08:56583 days ago1695010136IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1530686726.825346
0xd4a18269353288032023-09-18 4:08:33583 days ago1695010113IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1285134926.8818
0xd4a18269353287912023-09-18 4:08:06583 days ago1695010086IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1255130826.5
0xd4a18269353287792023-09-18 4:07:42583 days ago1695010062IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1301736126.5
0xd4a18269344045782023-08-26 15:30:28606 days ago1693063828IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1419817526.5
0xd4a18269342770312023-08-23 11:24:09609 days ago1692789849IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.0103274226.5
0xd4a18269342194012023-08-22 1:03:22610 days ago1692666202IN
0xeE206Ce7...9cebcE7B0
0 AVAX0.1448065229.85
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PendleRedeemProxyMulti

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 28 : PendleRedeemProxyMulti.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;
pragma abicoder v2;

import "./PendleRedeemProxyBase.sol";

contract PendleRedeemProxyMulti is PendleRedeemProxyBase {
    constructor(IPendleRouter _router, IPendleRetroactiveDistribution _tokenDistContract)
        PendleRedeemProxyBase(_router, _tokenDistContract)
    {}

    function _redeemLmV1Interest(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        override
        returns (PairTokenUints memory res)
    {
        res.tokens.tokenA = IPendleLiquidityMiningMulti(lm.addr).underlyingYieldToken();
        res.uints.uintA = IPendleLiquidityMiningMulti(lm.addr).redeemLpInterests(lm.expiry, user);
    }

    function _redeemLmV1Rewards(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        override
        returns (PairTokenUints memory res)
    {
        res.tokens = IPendleLiquidityMiningMulti(lm.addr).readRewardTokens();
        res.uints = IPendleLiquidityMiningMulti(lm.addr).redeemRewards(lm.expiry, user);
    }

    function _redeemLmV2Interest(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        override
        returns (PairTokenUints memory res)
    {
        res.tokens = IPendleLiquidityMiningV2Multi(lm.addr).readYieldTokens();
        res.uints = IPendleLiquidityMiningV2Multi(lm.addr).redeemDueInterests(user);
    }

    function _redeemLmV2Rewards(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        override
        returns (PairTokenUints memory res)
    {
        res.tokens = IPendleLiquidityMiningV2Multi(lm.addr).readRewardTokens();
        res.uints = IPendleLiquidityMiningV2Multi(lm.addr).redeemRewards(user);
    }

    function _redeemFromRewardManager(
        address,
        address rewardManager,
        address underlyingAsset,
        uint256 expiry,
        address user
    ) internal virtual override returns (TrioTokenUints memory res) {
        res.tokens = IPendleRewardManagerMulti(rewardManager).readRewardTokensForAsset(
            underlyingAsset
        );
        res.uints = IPendleRewardManagerMulti(rewardManager).redeemRewards(
            underlyingAsset,
            expiry,
            user
        );
    }
}

File 2 of 28 : PendleRedeemProxyBase.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;
pragma abicoder v2;

import "../interfaces/IPendleRouter.sol";
import "../interfaces/IPendleForge.sol";
import "../libraries/TrioTokensLib.sol";
import "../libraries/PairTokensLib.sol";
import "../interfaces/IPendleLiquidityMining.sol";
import "../interfaces/IPendleLiquidityMiningMulti.sol";
import "../interfaces/IPendleLiquidityMiningV2.sol";
import "../interfaces/IPendleLiquidityMiningV2Multi.sol";
import "../interfaces/IPendleYieldToken.sol";
import "../interfaces/IPendleRewardManager.sol";
import "../interfaces/IPendleRewardManagerMulti.sol";
import "../interfaces/IPendleRetroactiveDistribution.sol";
import "../libraries/PairTokensLib.sol";
import "../libraries/TrioTokensLib.sol";

enum LmRedeemMode {
    INTEREST,
    REWARDS,
    BOTH
}

struct LmRedeemRequest {
    address addr;
    uint256 expiry;
    LmRedeemMode mode;
}

struct LmRedeemResult {
    PairTokenUints rewards;
    PairTokenUints interests;
}

struct Args {
    address[] yts;
    address[] ots;
    address[] markets;
    LmRedeemRequest[] lmV1;
    LmRedeemRequest[] lmV2;
    address[] tokensDistribution;
}

abstract contract PendleRedeemProxyBase {
    IPendleRouter public immutable router;
    IPendleRetroactiveDistribution public immutable tokenDistContract;

    constructor(IPendleRouter _router, IPendleRetroactiveDistribution _tokenDistContract) {
        router = _router;
        tokenDistContract = _tokenDistContract;
    }

    /// @dev only OTs that has rewards should be passed in. SushiSimple & JoeSimple OTs shouldn't be passed in
    function redeem(Args calldata args, address user)
        external
        returns (
            uint256[] memory ytInterests,
            TrioTokenUints[] memory otRewards,
            uint256[] memory marketInterests,
            LmRedeemResult[] memory lmV1Returns,
            LmRedeemResult[] memory lmV2Returns,
            uint256[] memory tokenDistReturns
        )
    {
        ytInterests = redeemYts(args.yts, user);
        otRewards = redeemOts(args.ots, user);
        marketInterests = redeemMarkets(args.markets, user);
        lmV1Returns = redeemLmV1(args.lmV1, user);
        lmV2Returns = redeemLmV2(args.lmV2, user);
        tokenDistReturns = redeemTokenDist(args.tokensDistribution, user);
    }

    function redeemYts(address[] calldata yts, address user)
        public
        returns (uint256[] memory ytInterests)
    {
        ytInterests = new uint256[](yts.length);
        for (uint256 i = 0; i < yts.length; i++) {
            IPendleYieldToken yt = IPendleYieldToken(yts[i]);
            bytes32 forgeId = IPendleForge(yt.forge()).forgeId();
            address underlyingAsset = yt.underlyingAsset();
            uint256 expiry = yt.expiry();
            ytInterests[i] = router.redeemDueInterests(forgeId, underlyingAsset, expiry, user);
        }
    }

    function redeemOts(address[] calldata ots, address user)
        public
        returns (TrioTokenUints[] memory otRewards)
    {
        otRewards = new TrioTokenUints[](ots.length);
        for (uint256 i = 0; i < ots.length; i++) {
            IPendleYieldToken ot = IPendleYieldToken(ots[i]);
            IPendleForge forge = IPendleForge(ot.forge());
            address rewardManager = address(forge.rewardManager());
            address underlyingAsset = ot.underlyingAsset();
            uint256 expiry = ot.expiry();
            otRewards[i] = _redeemFromRewardManager(
                address(forge),
                rewardManager,
                underlyingAsset,
                expiry,
                user
            );
        }
    }

    function redeemMarkets(address[] calldata markets, address user)
        public
        returns (uint256[] memory marketInterests)
    {
        uint256 marketCount = markets.length;
        marketInterests = new uint256[](marketCount);
        for (uint256 i = 0; i < marketCount; i++) {
            marketInterests[i] = router.redeemLpInterests(markets[i], user);
        }
    }

    function redeemTokenDist(address[] calldata tokens, address user)
        public
        returns (uint256[] memory results)
    {
        if (tokens.length != 0) results = tokenDistContract.redeem(tokens, payable(user));
    }

    function redeemLmV1(LmRedeemRequest[] calldata lm, address user)
        public
        returns (LmRedeemResult[] memory results)
    {
        uint256 len = lm.length;
        results = new LmRedeemResult[](len);
        for (uint256 i = 0; i < len; i++) {
            if (lm[i].mode == LmRedeemMode.INTEREST || lm[i].mode == LmRedeemMode.BOTH)
                results[i].interests = _redeemLmV1Interest(lm[i], user);
            if (lm[i].mode == LmRedeemMode.REWARDS || lm[i].mode == LmRedeemMode.BOTH)
                results[i].rewards = _redeemLmV1Rewards(lm[i], user);
        }
    }

    function redeemLmV2(LmRedeemRequest[] calldata lm, address user)
        public
        returns (LmRedeemResult[] memory results)
    {
        uint256 len = lm.length;
        results = new LmRedeemResult[](len);
        for (uint256 i = 0; i < len; i++) {
            if (lm[i].mode == LmRedeemMode.INTEREST || lm[i].mode == LmRedeemMode.BOTH)
                results[i].interests = _redeemLmV2Interest(lm[i], user);
            if (lm[i].mode == LmRedeemMode.REWARDS || lm[i].mode == LmRedeemMode.BOTH)
                results[i].rewards = _redeemLmV2Rewards(lm[i], user);
        }
    }

    function _redeemLmV1Interest(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        returns (PairTokenUints memory);

    function _redeemLmV1Rewards(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        returns (PairTokenUints memory);

    function _redeemLmV2Interest(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        returns (PairTokenUints memory);

    function _redeemLmV2Rewards(LmRedeemRequest calldata lm, address user)
        internal
        virtual
        returns (PairTokenUints memory);

    function _redeemFromRewardManager(
        address forge,
        address rewardManager,
        address underlyingAsset,
        uint256 expiry,
        address user
    ) internal virtual returns (TrioTokenUints memory);
}

File 3 of 28 : IPendleRouter.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;
pragma abicoder v2;

import "../interfaces/IWETH.sol";
import "./IPendleData.sol";
import "../libraries/PendleStructs.sol";
import "./IPendleMarketFactory.sol";

interface IPendleRouter {
    /**
     * @notice Emitted when a market for a future yield token and an ERC20 token is created.
     * @param marketFactoryId Forge identifier.
     * @param xyt The address of the tokenized future yield token as the base asset.
     * @param token The address of an ERC20 token as the quote asset.
     * @param market The address of the newly created market.
     **/
    event MarketCreated(
        bytes32 marketFactoryId,
        address indexed xyt,
        address indexed token,
        address indexed market
    );

    /**
     * @notice Emitted when a swap happens on the market.
     * @param trader The address of msg.sender.
     * @param inToken The input token.
     * @param outToken The output token.
     * @param exactIn The exact amount being traded.
     * @param exactOut The exact amount received.
     * @param market The market address.
     **/
    event SwapEvent(
        address indexed trader,
        address inToken,
        address outToken,
        uint256 exactIn,
        uint256 exactOut,
        address market
    );

    /**
     * @dev Emitted when user adds liquidity
     * @param sender The user who added liquidity.
     * @param token0Amount the amount of token0 (xyt) provided by user
     * @param token1Amount the amount of token1 provided by user
     * @param market The market address.
     * @param exactOutLp The exact LP minted
     */
    event Join(
        address indexed sender,
        uint256 token0Amount,
        uint256 token1Amount,
        address market,
        uint256 exactOutLp
    );

    /**
     * @dev Emitted when user removes liquidity
     * @param sender The user who removed liquidity.
     * @param token0Amount the amount of token0 (xyt) given to user
     * @param token1Amount the amount of token1 given to user
     * @param market The market address.
     * @param exactInLp The exact Lp to remove
     */
    event Exit(
        address indexed sender,
        uint256 token0Amount,
        uint256 token1Amount,
        address market,
        uint256 exactInLp
    );

    /**
     * @notice Gets a reference to the PendleData contract.
     * @return Returns the data contract reference.
     **/
    function data() external view returns (IPendleData);

    /**
     * @notice Gets a reference of the WETH9 token contract address.
     * @return WETH token reference.
     **/
    function weth() external view returns (IWETH);

    /***********
     *  FORGE  *
     ***********/

    function newYieldContracts(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external returns (address ot, address xyt);

    function redeemAfterExpiry(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external returns (uint256 redeemedAmount);

    function redeemDueInterests(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        address user
    ) external returns (uint256 interests);

    function redeemUnderlying(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        uint256 amountToRedeem
    ) external returns (uint256 redeemedAmount);

    function renewYield(
        bytes32 forgeId,
        uint256 oldExpiry,
        address underlyingAsset,
        uint256 newExpiry,
        uint256 renewalRate
    )
        external
        returns (
            uint256 redeemedAmount,
            uint256 amountRenewed,
            address ot,
            address xyt,
            uint256 amountTokenMinted
        );

    function tokenizeYield(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        uint256 amountToTokenize,
        address to
    )
        external
        returns (
            address ot,
            address xyt,
            uint256 amountTokenMinted
        );

    /***********
     *  MARKET *
     ***********/

    function addMarketLiquidityDual(
        bytes32 _marketFactoryId,
        address _xyt,
        address _token,
        uint256 _desiredXytAmount,
        uint256 _desiredTokenAmount,
        uint256 _xytMinAmount,
        uint256 _tokenMinAmount
    )
        external
        payable
        returns (
            uint256 amountXytUsed,
            uint256 amountTokenUsed,
            uint256 lpOut
        );

    function addMarketLiquiditySingle(
        bytes32 marketFactoryId,
        address xyt,
        address token,
        bool forXyt,
        uint256 exactInAsset,
        uint256 minOutLp
    ) external payable returns (uint256 exactOutLp);

    function removeMarketLiquidityDual(
        bytes32 marketFactoryId,
        address xyt,
        address token,
        uint256 exactInLp,
        uint256 minOutXyt,
        uint256 minOutToken
    ) external returns (uint256 exactOutXyt, uint256 exactOutToken);

    function removeMarketLiquiditySingle(
        bytes32 marketFactoryId,
        address xyt,
        address token,
        bool forXyt,
        uint256 exactInLp,
        uint256 minOutAsset
    ) external returns (uint256 exactOutXyt, uint256 exactOutToken);

    /**
     * @notice Creates a market given a protocol ID, future yield token, and an ERC20 token.
     * @param marketFactoryId Market Factory identifier.
     * @param xyt Token address of the future yield token as base asset.
     * @param token Token address of an ERC20 token as quote asset.
     * @return market Returns the address of the newly created market.
     **/
    function createMarket(
        bytes32 marketFactoryId,
        address xyt,
        address token
    ) external returns (address market);

    function bootstrapMarket(
        bytes32 marketFactoryId,
        address xyt,
        address token,
        uint256 initialXytLiquidity,
        uint256 initialTokenLiquidity
    ) external payable;

    function swapExactIn(
        address tokenIn,
        address tokenOut,
        uint256 inTotalAmount,
        uint256 minOutTotalAmount,
        bytes32 marketFactoryId
    ) external payable returns (uint256 outTotalAmount);

    function swapExactOut(
        address tokenIn,
        address tokenOut,
        uint256 outTotalAmount,
        uint256 maxInTotalAmount,
        bytes32 marketFactoryId
    ) external payable returns (uint256 inTotalAmount);

    function redeemLpInterests(address market, address user) external returns (uint256 interests);
}

File 4 of 28 : IPendleForge.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

import "./IPendleRouter.sol";
import "./IPendleRewardManager.sol";
import "./IPendleYieldContractDeployer.sol";
import "./IPendleData.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IPendleForge {
    /**
     * @dev Emitted when the Forge has minted the OT and XYT tokens.
     * @param forgeId The forgeId
     * @param underlyingAsset The address of the underlying yield token.
     * @param expiry The expiry of the XYT token
     * @param amountToTokenize The amount of yield bearing assets to tokenize
     * @param amountTokenMinted The amount of OT/XYT minted
     **/
    event MintYieldTokens(
        bytes32 forgeId,
        address indexed underlyingAsset,
        uint256 indexed expiry,
        uint256 amountToTokenize,
        uint256 amountTokenMinted,
        address indexed user
    );

    /**
     * @dev Emitted when the Forge has created new yield token contracts.
     * @param forgeId The forgeId
     * @param underlyingAsset The address of the underlying asset.
     * @param expiry The date in epoch time when the contract will expire.
     * @param ot The address of the ownership token.
     * @param xyt The address of the new future yield token.
     **/
    event NewYieldContracts(
        bytes32 forgeId,
        address indexed underlyingAsset,
        uint256 indexed expiry,
        address ot,
        address xyt,
        address yieldBearingAsset
    );

    /**
     * @dev Emitted when the Forge has redeemed the OT and XYT tokens.
     * @param forgeId The forgeId
     * @param underlyingAsset the address of the underlying asset
     * @param expiry The expiry of the XYT token
     * @param amountToRedeem The amount of OT to be redeemed.
     * @param redeemedAmount The amount of yield token received
     **/
    event RedeemYieldToken(
        bytes32 forgeId,
        address indexed underlyingAsset,
        uint256 indexed expiry,
        uint256 amountToRedeem,
        uint256 redeemedAmount,
        address indexed user
    );

    /**
     * @dev Emitted when interest claim is settled
     * @param forgeId The forgeId
     * @param underlyingAsset the address of the underlying asset
     * @param expiry The expiry of the XYT token
     * @param user Interest receiver Address
     * @param amount The amount of interest claimed
     **/
    event DueInterestsSettled(
        bytes32 forgeId,
        address indexed underlyingAsset,
        uint256 indexed expiry,
        uint256 amount,
        uint256 forgeFeeAmount,
        address indexed user
    );

    /**
     * @dev Emitted when forge fee is withdrawn
     * @param forgeId The forgeId
     * @param underlyingAsset the address of the underlying asset
     * @param expiry The expiry of the XYT token
     * @param amount The amount of interest claimed
     **/
    event ForgeFeeWithdrawn(
        bytes32 forgeId,
        address indexed underlyingAsset,
        uint256 indexed expiry,
        uint256 amount
    );

    function setUpEmergencyMode(
        address _underlyingAsset,
        uint256 _expiry,
        address spender
    ) external;

    function newYieldContracts(address underlyingAsset, uint256 expiry)
        external
        returns (address ot, address xyt);

    function redeemAfterExpiry(
        address user,
        address underlyingAsset,
        uint256 expiry
    ) external returns (uint256 redeemedAmount);

    function redeemDueInterests(
        address user,
        address underlyingAsset,
        uint256 expiry
    ) external returns (uint256 interests);

    function updateDueInterests(
        address underlyingAsset,
        uint256 expiry,
        address user
    ) external;

    function updatePendingRewards(
        address _underlyingAsset,
        uint256 _expiry,
        address _user
    ) external;

    function redeemUnderlying(
        address user,
        address underlyingAsset,
        uint256 expiry,
        uint256 amountToRedeem
    ) external returns (uint256 redeemedAmount);

    function mintOtAndXyt(
        address underlyingAsset,
        uint256 expiry,
        uint256 amountToTokenize,
        address to
    )
        external
        returns (
            address ot,
            address xyt,
            uint256 amountTokenMinted
        );

    function withdrawForgeFee(address underlyingAsset, uint256 expiry) external;

    function getYieldBearingToken(address underlyingAsset) external returns (address);

    /**
     * @notice Gets a reference to the PendleRouter contract.
     * @return Returns the router contract reference.
     **/
    function router() external view returns (IPendleRouter);

    function data() external view returns (IPendleData);

    function rewardManager() external view returns (IPendleRewardManager);

    function yieldContractDeployer() external view returns (IPendleYieldContractDeployer);

    function rewardToken() external view returns (IERC20);

    /**
     * @notice Gets the bytes32 ID of the forge.
     * @return Returns the forge and protocol identifier.
     **/
    function forgeId() external view returns (bytes32);

    function dueInterests(
        address _underlyingAsset,
        uint256 expiry,
        address _user
    ) external view returns (uint256);

    function yieldTokenHolders(address _underlyingAsset, uint256 _expiry)
        external
        view
        returns (address yieldTokenHolder);
}

File 5 of 28 : TrioTokensLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "./MathLib.sol";
import "./TokenUtilsLib.sol";

struct TrioUints {
    uint256 uintA;
    uint256 uintB;
    uint256 uintC;
}

struct TrioTokens {
    address tokenA;
    address tokenB;
    address tokenC;
}

struct TrioTokenUints {
    TrioTokens tokens;
    TrioUints uints;
}

library TrioTokensLib {
    using SafeMath for uint256;
    using Math for uint256;
    using TokenUtils for IERC20;

    address internal constant ZERO = address(0);

    function verify(TrioTokens memory a) internal pure {
        if (a.tokenA != ZERO)
            require(a.tokenA != a.tokenB && a.tokenA != a.tokenC, "DUPLICATED_TOKENS");
        if (a.tokenB != ZERO) require(a.tokenB != a.tokenC, "DUPLICATED_TOKENS");
    }

    function safeTransferFrom(
        TrioTokens memory tokens,
        address from,
        address to,
        TrioUints memory amounts
    ) internal {
        if (tokens.tokenA != ZERO && amounts.uintA != 0)
            IERC20(tokens.tokenA).safeTransferFrom(from, to, amounts.uintA);
        if (tokens.tokenB != ZERO && amounts.uintB != 0)
            IERC20(tokens.tokenB).safeTransferFrom(from, to, amounts.uintB);
        if (tokens.tokenC != ZERO && amounts.uintC != 0)
            IERC20(tokens.tokenC).safeTransferFrom(from, to, amounts.uintC);
    }

    function safeTransfer(
        TrioTokens memory tokens,
        address to,
        TrioUints memory amounts
    ) internal {
        if (tokens.tokenA != ZERO && amounts.uintA != 0)
            IERC20(tokens.tokenA).safeTransfer(to, amounts.uintA);
        if (tokens.tokenB != ZERO && amounts.uintB != 0)
            IERC20(tokens.tokenB).safeTransfer(to, amounts.uintB);
        if (tokens.tokenC != ZERO && amounts.uintC != 0)
            IERC20(tokens.tokenC).safeTransfer(to, amounts.uintC);
    }

    function infinityApprove(TrioTokens memory tokens, address to) internal {
        if (tokens.tokenA != ZERO) IERC20(tokens.tokenA).safeApprove(to, type(uint256).max);
        if (tokens.tokenB != ZERO) IERC20(tokens.tokenB).safeApprove(to, type(uint256).max);
        if (tokens.tokenC != ZERO) IERC20(tokens.tokenC).safeApprove(to, type(uint256).max);
    }

    function allowance(TrioTokens memory tokens, address spender)
        internal
        view
        returns (TrioUints memory res)
    {
        if (tokens.tokenA != ZERO)
            res.uintA = IERC20(tokens.tokenA).allowance(address(this), spender);
        if (tokens.tokenB != ZERO)
            res.uintB = IERC20(tokens.tokenB).allowance(address(this), spender);
        if (tokens.tokenC != ZERO)
            res.uintC = IERC20(tokens.tokenC).allowance(address(this), spender);
    }

    function balanceOf(TrioTokens memory tokens, address account)
        internal
        view
        returns (TrioUints memory balances)
    {
        if (tokens.tokenA != ZERO) balances.uintA = IERC20(tokens.tokenA).balanceOf(account);
        if (tokens.tokenB != ZERO) balances.uintB = IERC20(tokens.tokenB).balanceOf(account);
        if (tokens.tokenC != ZERO) balances.uintC = IERC20(tokens.tokenC).balanceOf(account);
    }

    function add(TrioUints memory a, TrioUints memory b)
        internal
        pure
        returns (TrioUints memory res)
    {
        res.uintA = a.uintA.add(b.uintA);
        res.uintB = a.uintB.add(b.uintB);
        res.uintC = a.uintC.add(b.uintC);
    }

    function sub(TrioUints memory a, TrioUints memory b)
        internal
        pure
        returns (TrioUints memory res)
    {
        res.uintA = a.uintA.sub(b.uintA);
        res.uintB = a.uintB.sub(b.uintB);
        res.uintC = a.uintC.sub(b.uintC);
    }

    function eq(TrioUints memory a, TrioUints memory b) internal pure returns (bool) {
        return a.uintA == b.uintA && a.uintB == b.uintB && a.uintC == b.uintC;
    }

    function min(TrioUints memory a, TrioUints memory b) internal pure returns (TrioUints memory) {
        return
            TrioUints(
                Math.min(a.uintA, b.uintA),
                Math.min(a.uintB, b.uintB),
                Math.min(a.uintC, b.uintC)
            );
    }

    function mul(TrioUints memory a, uint256 b) internal pure returns (TrioUints memory res) {
        res.uintA = a.uintA.mul(b);
        res.uintB = a.uintB.mul(b);
        res.uintC = a.uintC.mul(b);
    }

    function div(TrioUints memory a, uint256 b) internal pure returns (TrioUints memory res) {
        res.uintA = a.uintA.div(b);
        res.uintB = a.uintB.div(b);
        res.uintC = a.uintC.div(b);
    }

    function allZero(TrioUints memory a) internal pure returns (bool) {
        return a.uintA == 0 && a.uintB == 0 && a.uintC == 0;
    }

    function allZero(TrioTokens memory a) internal pure returns (bool) {
        return a.tokenA == ZERO && a.tokenB == ZERO && a.tokenC == ZERO;
    }

    function contains(TrioTokens memory tokens, address _token) internal pure returns (bool) {
        if (_token == ZERO) return false;
        return (_token == tokens.tokenA || _token == tokens.tokenB || _token == tokens.tokenC);
    }

    function toArr(TrioTokens memory tokens) internal pure returns (address[] memory res) {
        res = new address[](3);
        res[0] = tokens.tokenA;
        res[1] = tokens.tokenB;
        res[2] = tokens.tokenC;
    }
}

File 6 of 28 : PairTokensLib.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.6;
pragma abicoder v2;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "./MathLib.sol";
import "./TokenUtilsLib.sol";

struct PairUints {
    uint256 uintA;
    uint256 uintB;
}

struct PairTokens {
    address tokenA;
    address tokenB;
}

struct PairTokenUints {
    PairTokens tokens;
    PairUints uints;
}

library PairTokensLib {
    using SafeMath for uint256;
    using Math for uint256;
    using TokenUtils for IERC20;

    address internal constant ZERO = address(0);

    function verify(PairTokens memory a) internal pure {
        if (a.tokenA != ZERO) require(a.tokenA != a.tokenB, "DUPLICATED_TOKENS");
    }

    function safeTransferFrom(
        PairTokens memory tokens,
        address from,
        address to,
        PairUints memory amounts
    ) internal {
        if (tokens.tokenA != ZERO && amounts.uintA != 0)
            IERC20(tokens.tokenA).safeTransferFrom(from, to, amounts.uintA);
        if (tokens.tokenB != ZERO && amounts.uintB != 0)
            IERC20(tokens.tokenB).safeTransferFrom(from, to, amounts.uintB);
    }

    function safeTransfer(
        PairTokens memory tokens,
        address to,
        PairUints memory amounts
    ) internal {
        if (tokens.tokenA != ZERO && amounts.uintA != 0)
            IERC20(tokens.tokenA).safeTransfer(to, amounts.uintA);
        if (tokens.tokenB != ZERO && amounts.uintB != 0)
            IERC20(tokens.tokenB).safeTransfer(to, amounts.uintB);
    }

    function infinityApprove(PairTokens memory tokens, address to) internal {
        if (tokens.tokenA != ZERO) IERC20(tokens.tokenA).safeApprove(to, type(uint256).max);
        if (tokens.tokenB != ZERO) IERC20(tokens.tokenB).safeApprove(to, type(uint256).max);
    }

    function allowance(PairTokens memory tokens, address spender)
        internal
        view
        returns (PairUints memory res)
    {
        if (tokens.tokenA != ZERO)
            res.uintA = IERC20(tokens.tokenA).allowance(address(this), spender);
        if (tokens.tokenB != ZERO)
            res.uintB = IERC20(tokens.tokenB).allowance(address(this), spender);
    }

    function balanceOf(PairTokens memory tokens, address account)
        internal
        view
        returns (PairUints memory balances)
    {
        if (tokens.tokenA != ZERO) balances.uintA = IERC20(tokens.tokenA).balanceOf(account);
        if (tokens.tokenB != ZERO) balances.uintB = IERC20(tokens.tokenB).balanceOf(account);
    }

    function add(PairUints memory a, PairUints memory b)
        internal
        pure
        returns (PairUints memory res)
    {
        res.uintA = a.uintA.add(b.uintA);
        res.uintB = a.uintB.add(b.uintB);
    }

    function sub(PairUints memory a, PairUints memory b)
        internal
        pure
        returns (PairUints memory res)
    {
        res.uintA = a.uintA.sub(b.uintA);
        res.uintB = a.uintB.sub(b.uintB);
    }

    function eq(PairUints memory a, PairUints memory b) internal pure returns (bool) {
        return a.uintA == b.uintA && a.uintB == b.uintB;
    }

    function eq(PairTokens memory a, PairTokens memory b) internal pure returns (bool) {
        return a.tokenA == b.tokenA && a.tokenB == b.tokenB;
    }

    function min(PairUints memory a, PairUints memory b) internal pure returns (PairUints memory) {
        return PairUints(Math.min(a.uintA, b.uintA), Math.min(a.uintB, b.uintB));
    }

    function mul(PairUints memory a, uint256 b) internal pure returns (PairUints memory res) {
        res.uintA = a.uintA.mul(b);
        res.uintB = a.uintB.mul(b);
    }

    function div(PairUints memory a, uint256 b) internal pure returns (PairUints memory res) {
        res.uintA = a.uintA.div(b);
        res.uintB = a.uintB.div(b);
    }

    function allZero(PairUints memory a) internal pure returns (bool) {
        return a.uintA == 0 && a.uintB == 0;
    }

    function allZero(PairTokens memory a) internal pure returns (bool) {
        return a.tokenA == ZERO && a.tokenB == ZERO;
    }

    function contains(PairTokens memory tokens, address _token) internal pure returns (bool) {
        if (_token == ZERO) return false;
        return (_token == tokens.tokenA || _token == tokens.tokenB);
    }

    function toArr(PairTokens memory tokens) internal pure returns (address[] memory res) {
        res = new address[](2);
        res[0] = tokens.tokenA;
        res[1] = tokens.tokenB;
    }

    function add(PairTokenUints memory a, PairTokenUints memory b)
        internal
        pure
        returns (PairTokenUints memory res)
    {
        require(eq(a.tokens, b.tokens), "PAIR_MISMATCH");
        res.tokens = a.tokens;
        res.uints = add(a.uints, b.uints);
    }

    function mul(PairTokenUints memory a, uint256 b)
        internal
        pure
        returns (PairTokenUints memory res)
    {
        res.tokens = a.tokens;
        res.uints = mul(a.uints, b);
    }

    function div(PairTokenUints memory a, uint256 b)
        internal
        pure
        returns (PairTokenUints memory res)
    {
        res.tokens = a.tokens;
        res.uints = div(a.uints, b);
    }
}

File 7 of 28 : IPendleLiquidityMining.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

interface IPendleLiquidityMining {
    event RedeemLpInterests(uint256 expiry, address user, uint256 interests);
    event Funded(uint256[] _rewards, uint256 numberOfEpochs);
    event RewardsToppedUp(uint256[] _epochIds, uint256[] _rewards);
    event AllocationSettingSet(uint256[] _expiries, uint256[] _allocationNumerators);
    event Staked(uint256 expiry, address user, uint256 amount);
    event Withdrawn(uint256 expiry, address user, uint256 amount);
    event PendleRewardsSettled(uint256 expiry, address user, uint256 amount);

    /**
     * @notice fund new epochs
     */
    function fund(uint256[] calldata rewards) external;

    /**
    @notice top up rewards for any funded future epochs (but not to create new epochs)
    */
    function topUpRewards(uint256[] calldata _epochIds, uint256[] calldata _rewards) external;

    /**
     * @notice Stake an exact amount of LP_expiry
     */
    function stake(uint256 expiry, uint256 amount) external returns (address);

    /**
     * @notice Stake an exact amount of LP_expiry
     */
    function stakeFor(
        address to,
        uint256 expiry,
        uint256 amount
    ) external returns (address);

    /**
     * @notice Stake an exact amount of LP_expiry, using a permit
     */
    function stakeWithPermit(
        uint256 expiry,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (address);

    /**
     * @notice Withdraw an exact amount of LP_expiry
     */
    function withdraw(uint256 expiry, uint256 amount) external;

    /**
     * @notice Withdraw an exact amount of LP_expiry
     */
    function withdrawTo(
        address to,
        uint256 expiry,
        uint256 amount
    ) external;

    /**
     * @notice Get the pending rewards for a user
     * @return rewards Returns rewards[0] as the rewards available now, as well as rewards
     that can be claimed for subsequent epochs (size of rewards array is numberOfEpochs)
     */
    function redeemRewards(uint256 expiry, address user) external returns (uint256 rewards);

    /**
     * @notice Get the pending LP interests for a staker
     * @return dueInterests Returns the interest amount
     */
    function redeemLpInterests(uint256 expiry, address user)
        external
        returns (uint256 dueInterests);

    /**
     * @notice Let the liqMiningEmergencyHandler call to approve spender to spend tokens from liqMiningContract
     *          and to spend tokensForLpHolder from the respective lp holders for expiries specified
     */
    function setUpEmergencyMode(uint256[] calldata expiries, address spender) external;

    /**
     * @notice Read the all the expiries that user has staked LP for
     */
    function readUserExpiries(address user) external view returns (uint256[] memory expiries);

    /**
     * @notice Read the amount of LP_expiry staked for a user
     */
    function getBalances(uint256 expiry, address user) external view returns (uint256);

    function lpHolderForExpiry(uint256 expiry) external view returns (address);

    function startTime() external view returns (uint256);

    function epochDuration() external view returns (uint256);

    function totalRewardsForEpoch(uint256) external view returns (uint256);

    function numberOfEpochs() external view returns (uint256);

    function vestingEpochs() external view returns (uint256);

    function baseToken() external view returns (address);

    function underlyingAsset() external view returns (address);

    function underlyingYieldToken() external view returns (address);

    function pendleTokenAddress() external view returns (address);

    function marketFactoryId() external view returns (bytes32);

    function forgeId() external view returns (bytes32);

    function forge() external view returns (address);

    function readAllExpiriesLength() external view returns (uint256);
}

File 8 of 28 : IPendleLiquidityMiningMulti.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;
pragma abicoder v2;

import "./IWETH.sol";
import "../libraries/PairTokensLib.sol";

interface IPendleLiquidityMiningMulti {
    event RedeemLpInterests(uint256 expiry, address user, uint256 interests);
    event Funded(PairUints[] _rewards, uint256 numberOfEpochs);
    event RewardsToppedUp(uint256[] _epochIds, PairUints[] _rewards);
    event AllocationSettingSet(uint256[] _expiries, uint256[] _allocationNumerators);
    event Staked(uint256 expiry, address user, uint256 amount);
    event Withdrawn(uint256 expiry, address user, uint256 amount);
    event PendleRewardsSettled(uint256 expiry, address user, PairUints amount);

    /**
     * @notice fund new epochs
     */
    function fund(PairUints[] calldata rewards) external;

    /**
    @notice top up rewards for any funded future epochs (but not to create new epochs)
    */
    function topUpRewards(uint256[] calldata _epochIds, PairUints[] calldata _rewards) external;

    /**
     * @notice Stake an exact amount of LP_expiry
     */
    function stakeFor(
        address forAddr,
        uint256 expiry,
        uint256 amount
    ) external returns (address);

    /**
     * @notice Stake an exact amount of LP_expiry, using a permit
     */
    function stakeWithPermit(
        uint256 expiry,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (address);

    /**
     * @notice Withdraw an exact amount of LP_expiry
     */
    function withdrawTo(
        address to,
        uint256 expiry,
        uint256 amount
    ) external;

    /**
     * @notice Get the pending rewards for a user
     * @return rewards Returns rewards[0] as the rewards available now, as well as rewards
     that can be claimed for subsequent epochs (size of rewards array is numberOfEpochs)
     */
    function redeemRewards(uint256 expiry, address user)
        external
        returns (PairUints memory rewards);

    /**
     * @notice Get the pending LP interests for a staker
     * @return dueInterests Returns the interest amount
     */
    function redeemLpInterests(uint256 expiry, address user)
        external
        returns (uint256 dueInterests);

    /**
     * @notice Let the liqMiningEmergencyHandler call to approve spender to spend tokens from liqMiningContract
     *          and to spend tokensForLpHolder from the respective lp holders for expiries specified
     */
    function setUpEmergencyMode(uint256[] calldata expiries, address spender) external;

    /**
     * @notice Read the all the expiries that user has staked LP for
     */
    function readUserExpiries(address user) external view returns (uint256[] memory expiries);

    /**
     * @notice Read the amount of LP_expiry staked for a user
     */
    function getBalances(uint256 expiry, address user) external view returns (uint256);

    function lpHolderForExpiry(uint256 expiry) external view returns (address);

    function startTime() external view returns (uint256);

    function epochDuration() external view returns (uint256);

    function totalRewardsForEpoch(uint256) external view returns (PairUints memory);

    function readRewardTokens() external view returns (PairTokens memory);

    function numberOfEpochs() external view returns (uint256);

    function vestingEpochs() external view returns (uint256);

    function baseToken() external view returns (address);

    function underlyingAsset() external view returns (address);

    function underlyingYieldToken() external view returns (address);

    function marketFactoryId() external view returns (bytes32);

    function forgeId() external view returns (bytes32);

    function forge() external view returns (address);

    function readAllExpiriesLength() external view returns (uint256);
}

File 9 of 28 : IPendleLiquidityMiningV2.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

interface IPendleLiquidityMiningV2 {
    event Funded(uint256[] rewards, uint256 numberOfEpochs);
    event RewardsToppedUp(uint256[] epochIds, uint256[] rewards);
    event Staked(address user, uint256 amount);
    event Withdrawn(address user, uint256 amount);
    event PendleRewardsSettled(address user, uint256 amount);

    function fund(uint256[] calldata rewards) external;

    function topUpRewards(uint256[] calldata epochIds, uint256[] calldata rewards) external;

    function stake(address forAddr, uint256 amount) external;

    function withdraw(address toAddr, uint256 amount) external;

    function redeemRewards(address user) external returns (uint256 rewards);

    function redeemDueInterests(address user) external returns (uint256 amountOut);

    function setUpEmergencyMode(address spender, bool) external;

    function updateAndReadEpochData(uint256 epochId, address user)
        external
        returns (
            uint256 totalStakeUnits,
            uint256 totalRewards,
            uint256 lastUpdated,
            uint256 stakeUnitsForUser,
            uint256 availableRewardsForUser
        );

    function balances(address user) external view returns (uint256);

    function startTime() external view returns (uint256);

    function epochDuration() external view returns (uint256);

    function readEpochData(uint256 epochId, address user)
        external
        view
        returns (
            uint256 totalStakeUnits,
            uint256 totalRewards,
            uint256 lastUpdated,
            uint256 stakeUnitsForUser,
            uint256 availableRewardsForUser
        );

    function numberOfEpochs() external view returns (uint256);

    function vestingEpochs() external view returns (uint256);

    function stakeToken() external view returns (address);

    function yieldToken() external view returns (address);

    function pendleTokenAddress() external view returns (address);

    function totalStake() external view returns (uint256);

    function dueInterests(address) external view returns (uint256);

    function lastParamL(address) external view returns (uint256);

    function lastNYield() external view returns (uint256);

    function paramL() external view returns (uint256);
}

File 10 of 28 : IPendleLiquidityMiningV2Multi.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;
pragma abicoder v2;

import "../libraries/PairTokensLib.sol";
import "../interfaces/IWETH.sol";

interface IPendleLiquidityMiningV2Multi {
    event Funded(PairUints[] rewards, uint256 numberOfEpochs);
    event RewardsToppedUp(uint256[] epochIds, PairUints[] rewards);
    event Staked(address user, uint256 amount);
    event Withdrawn(address user, uint256 amount);
    event PendleRewardsSettled(address user, PairUints amount);

    function fund(PairUints[] calldata rewards) external;

    function topUpRewards(uint256[] calldata epochIds, PairUints[] calldata rewards) external;

    function stake(address forAddr, uint256 amount) external;

    function withdraw(address toAddr, uint256 amount) external;

    function redeemRewards(address user) external returns (PairUints memory rewards);

    function redeemDueInterests(address user) external returns (PairUints memory amountOut);

    function setUpEmergencyMode(address spender, bool) external;

    function updateAndReadEpochData(uint256 epochId, address user)
        external
        returns (
            uint256 totalStakeUnits,
            PairUints memory totalRewards,
            uint256 lastUpdated,
            uint256 stakeUnitsForUser,
            PairUints memory availableRewardsForUser
        );

    function balances(address user) external view returns (uint256);

    function startTime() external view returns (uint256);

    function epochDuration() external view returns (uint256);

    function readEpochData(uint256 epochId, address user)
        external
        view
        returns (
            uint256 totalStakeUnits,
            PairUints memory totalRewards,
            uint256 lastUpdated,
            uint256 stakeUnitsForUser,
            PairUints memory availableRewardsForUser
        );

    function numberOfEpochs() external view returns (uint256);

    function vestingEpochs() external view returns (uint256);

    function stakeToken() external view returns (address);

    function totalStake() external view returns (uint256);

    function readYieldTokens() external view returns (PairTokens memory);

    function readRewardTokens() external view returns (PairTokens memory);
}

File 11 of 28 : IPendleYieldToken.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IPendleBaseToken.sol";
import "./IPendleForge.sol";

interface IPendleYieldToken is IERC20, IPendleBaseToken {
    /**
     * @notice Emitted when burning OT or XYT tokens.
     * @param user The address performing the burn.
     * @param amount The amount to be burned.
     **/
    event Burn(address indexed user, uint256 amount);

    /**
     * @notice Emitted when minting OT or XYT tokens.
     * @param user The address performing the mint.
     * @param amount The amount to be minted.
     **/
    event Mint(address indexed user, uint256 amount);

    /**
     * @notice Burns OT or XYT tokens from user, reducing the total supply.
     * @param user The address performing the burn.
     * @param amount The amount to be burned.
     **/
    function burn(address user, uint256 amount) external;

    /**
     * @notice Mints new OT or XYT tokens for user, increasing the total supply.
     * @param user The address to send the minted tokens.
     * @param amount The amount to be minted.
     **/
    function mint(address user, uint256 amount) external;

    /**
     * @notice Gets the forge address of the PendleForge contract for this yield token.
     * @return Retuns the forge address.
     **/
    function forge() external view returns (IPendleForge);

    /**
     * @notice Returns the address of the underlying asset.
     * @return Returns the underlying asset address.
     **/
    function underlyingAsset() external view returns (address);

    /**
     * @notice Returns the address of the underlying yield token.
     * @return Returns the underlying yield token address.
     **/
    function underlyingYieldToken() external view returns (address);

    /**
     * @notice let the router approve itself to spend OT/XYT/LP from any wallet
     * @param user user to approve
     **/
    function approveRouter(address user) external;
}

File 12 of 28 : IPendleRewardManager.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;

interface IPendleRewardManager {
    event UpdateFrequencySet(address[], uint256[]);
    event SkippingRewardsSet(bool);

    event DueRewardsSettled(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        uint256 amountOut,
        address user
    );

    function redeemRewards(
        address _underlyingAsset,
        uint256 _expiry,
        address _user
    ) external returns (uint256 dueRewards);

    function updatePendingRewards(
        address _underlyingAsset,
        uint256 _expiry,
        address _user
    ) external;

    function updateParamLManual(address _underlyingAsset, uint256 _expiry) external;

    function setUpdateFrequency(
        address[] calldata underlyingAssets,
        uint256[] calldata frequencies
    ) external;

    function setSkippingRewards(bool skippingRewards) external;

    function forgeId() external returns (bytes32);
}

File 13 of 28 : IPendleRewardManagerMulti.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;
pragma abicoder v2;

import "../libraries/TrioTokensLib.sol";

interface IPendleRewardManagerMulti {
    event UpdateFrequencySet(address[], uint256[]);
    event SkippingRewardsSet(bool);
    event RedeemRewards(address user, TrioUints amounts);

    event DueRewardsSettled(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        TrioUints amounts,
        address user
    );

    function redeemRewards(
        address _underlyingAsset,
        uint256 _expiry,
        address _user
    ) external returns (TrioUints memory amounts);

    function registerNewUnderlyingAsset(address _underlyingAsset, TrioTokens memory _rewardTokens)
        external;

    function readRewardTokensForAsset(address asset) external returns (TrioTokens memory);
}

File 14 of 28 : IPendleRetroactiveDistribution.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;
pragma abicoder v2;

interface IPendleRetroactiveDistribution {
    event DistributeReward(
        bytes32 indexed rewardType,
        address rewardToken,
        uint256 totalAmount
    );
    event UndistributeReward(
        bytes32 indexed rewardType,
        address rewardToken,
        uint256 totalAmount
    );
    event RedeemReward(
        address indexed user,
        address rewardToken,
        uint256 amount
    );
    function redeem(address[] calldata tokens, address payable forAddr)
        external
        returns (uint256[] memory);
}

File 15 of 28 : IWETH.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IWETH is IERC20 {
    function deposit() external payable;

    function withdraw(uint256 wad) external;
}

File 16 of 28 : IPendleData.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

import "./IPendleRouter.sol";
import "./IPendleYieldToken.sol";
import "./IPendlePausingManager.sol";
import "./IPendleMarket.sol";

interface IPendleData {
    /**
     * @notice Emitted when validity of a forge-factory pair is updated
     * @param _forgeId the forge id
     * @param _marketFactoryId the market factory id
     * @param _valid valid or not
     **/
    event ForgeFactoryValiditySet(bytes32 _forgeId, bytes32 _marketFactoryId, bool _valid);

    /**
     * @notice Emitted when Pendle and PendleFactory addresses have been updated.
     * @param treasury The address of the new treasury contract.
     **/
    event TreasurySet(address treasury);

    /**
     * @notice Emitted when LockParams is changed
     **/
    event LockParamsSet(uint256 lockNumerator, uint256 lockDenominator);

    /**
     * @notice Emitted when ExpiryDivisor is changed
     **/
    event ExpiryDivisorSet(uint256 expiryDivisor);

    /**
     * @notice Emitted when forge fee is changed
     **/
    event ForgeFeeSet(uint256 forgeFee);

    /**
     * @notice Emitted when interestUpdateRateDeltaForMarket is changed
     * @param interestUpdateRateDeltaForMarket new interestUpdateRateDeltaForMarket setting
     **/
    event InterestUpdateRateDeltaForMarketSet(uint256 interestUpdateRateDeltaForMarket);

    /**
     * @notice Emitted when market fees are changed
     * @param _swapFee new swapFee setting
     * @param _protocolSwapFee new protocolSwapFee setting
     **/
    event MarketFeesSet(uint256 _swapFee, uint256 _protocolSwapFee);

    /**
     * @notice Emitted when the curve shift block delta is changed
     * @param _blockDelta new block delta setting
     **/
    event CurveShiftBlockDeltaSet(uint256 _blockDelta);

    /**
     * @dev Emitted when new forge is added
     * @param marketFactoryId Human Readable Market Factory ID in Bytes
     * @param marketFactoryAddress The Market Factory Address
     */
    event NewMarketFactory(bytes32 indexed marketFactoryId, address indexed marketFactoryAddress);

    /**
     * @notice Set/update validity of a forge-factory pair
     * @param _forgeId the forge id
     * @param _marketFactoryId the market factory id
     * @param _valid valid or not
     **/
    function setForgeFactoryValidity(
        bytes32 _forgeId,
        bytes32 _marketFactoryId,
        bool _valid
    ) external;

    /**
     * @notice Sets the PendleTreasury contract addresses.
     * @param newTreasury Address of new treasury contract.
     **/
    function setTreasury(address newTreasury) external;

    /**
     * @notice Gets a reference to the PendleRouter contract.
     * @return Returns the router contract reference.
     **/
    function router() external view returns (IPendleRouter);

    /**
     * @notice Gets a reference to the PendleRouter contract.
     * @return Returns the router contract reference.
     **/
    function pausingManager() external view returns (IPendlePausingManager);

    /**
     * @notice Gets the treasury contract address where fees are being sent to.
     * @return Address of the treasury contract.
     **/
    function treasury() external view returns (address);

    /***********
     *  FORGE  *
     ***********/

    /**
     * @notice Emitted when a forge for a protocol is added.
     * @param forgeId Forge and protocol identifier.
     * @param forgeAddress The address of the added forge.
     **/
    event ForgeAdded(bytes32 indexed forgeId, address indexed forgeAddress);

    /**
     * @notice Adds a new forge for a protocol.
     * @param forgeId Forge and protocol identifier.
     * @param forgeAddress The address of the added forge.
     **/
    function addForge(bytes32 forgeId, address forgeAddress) external;

    /**
     * @notice Store new OT and XYT details.
     * @param forgeId Forge and protocol identifier.
     * @param ot The address of the new XYT.
     * @param xyt The address of the new XYT.
     * @param underlyingAsset Token address of the underlying asset.
     * @param expiry Yield contract expiry in epoch time.
     **/
    function storeTokens(
        bytes32 forgeId,
        address ot,
        address xyt,
        address underlyingAsset,
        uint256 expiry
    ) external;

    /**
     * @notice Set a new forge fee
     * @param _forgeFee new forge fee
     **/
    function setForgeFee(uint256 _forgeFee) external;

    /**
     * @notice Gets the OT and XYT tokens.
     * @param forgeId Forge and protocol identifier.
     * @param underlyingYieldToken Token address of the underlying yield token.
     * @param expiry Yield contract expiry in epoch time.
     * @return ot The OT token references.
     * @return xyt The XYT token references.
     **/
    function getPendleYieldTokens(
        bytes32 forgeId,
        address underlyingYieldToken,
        uint256 expiry
    ) external view returns (IPendleYieldToken ot, IPendleYieldToken xyt);

    /**
     * @notice Gets a forge given the identifier.
     * @param forgeId Forge and protocol identifier.
     * @return forgeAddress Returns the forge address.
     **/
    function getForgeAddress(bytes32 forgeId) external view returns (address forgeAddress);

    /**
     * @notice Checks if an XYT token is valid.
     * @param forgeId The forgeId of the forge.
     * @param underlyingAsset Token address of the underlying asset.
     * @param expiry Yield contract expiry in epoch time.
     * @return True if valid, false otherwise.
     **/
    function isValidXYT(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external view returns (bool);

    /**
     * @notice Checks if an OT token is valid.
     * @param forgeId The forgeId of the forge.
     * @param underlyingAsset Token address of the underlying asset.
     * @param expiry Yield contract expiry in epoch time.
     * @return True if valid, false otherwise.
     **/
    function isValidOT(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external view returns (bool);

    function validForgeFactoryPair(bytes32 _forgeId, bytes32 _marketFactoryId)
        external
        view
        returns (bool);

    /**
     * @notice Gets a reference to a specific OT.
     * @param forgeId Forge and protocol identifier.
     * @param underlyingYieldToken Token address of the underlying yield token.
     * @param expiry Yield contract expiry in epoch time.
     * @return ot Returns the reference to an OT.
     **/
    function otTokens(
        bytes32 forgeId,
        address underlyingYieldToken,
        uint256 expiry
    ) external view returns (IPendleYieldToken ot);

    /**
     * @notice Gets a reference to a specific XYT.
     * @param forgeId Forge and protocol identifier.
     * @param underlyingAsset Token address of the underlying asset
     * @param expiry Yield contract expiry in epoch time.
     * @return xyt Returns the reference to an XYT.
     **/
    function xytTokens(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external view returns (IPendleYieldToken xyt);

    /***********
     *  MARKET *
     ***********/

    event MarketPairAdded(address indexed market, address indexed xyt, address indexed token);

    function addMarketFactory(bytes32 marketFactoryId, address marketFactoryAddress) external;

    function isMarket(address _addr) external view returns (bool result);

    function isXyt(address _addr) external view returns (bool result);

    function addMarket(
        bytes32 marketFactoryId,
        address xyt,
        address token,
        address market
    ) external;

    function setMarketFees(uint256 _swapFee, uint256 _protocolSwapFee) external;

    function setInterestUpdateRateDeltaForMarket(uint256 _interestUpdateRateDeltaForMarket)
        external;

    function setLockParams(uint256 _lockNumerator, uint256 _lockDenominator) external;

    function setExpiryDivisor(uint256 _expiryDivisor) external;

    function setCurveShiftBlockDelta(uint256 _blockDelta) external;

    /**
     * @notice Displays the number of markets currently existing.
     * @return Returns markets length,
     **/
    function allMarketsLength() external view returns (uint256);

    function forgeFee() external view returns (uint256);

    function interestUpdateRateDeltaForMarket() external view returns (uint256);

    function expiryDivisor() external view returns (uint256);

    function lockNumerator() external view returns (uint256);

    function lockDenominator() external view returns (uint256);

    function swapFee() external view returns (uint256);

    function protocolSwapFee() external view returns (uint256);

    function curveShiftBlockDelta() external view returns (uint256);

    function getMarketByIndex(uint256 index) external view returns (address market);

    /**
     * @notice Gets a market given a future yield token and an ERC20 token.
     * @param xyt Token address of the future yield token as base asset.
     * @param token Token address of an ERC20 token as quote asset.
     * @return market Returns the market address.
     **/
    function getMarket(
        bytes32 marketFactoryId,
        address xyt,
        address token
    ) external view returns (address market);

    /**
     * @notice Gets a market factory given the identifier.
     * @param marketFactoryId MarketFactory identifier.
     * @return marketFactoryAddress Returns the factory address.
     **/
    function getMarketFactoryAddress(bytes32 marketFactoryId)
        external
        view
        returns (address marketFactoryAddress);

    function getMarketFromKey(
        address xyt,
        address token,
        bytes32 marketFactoryId
    ) external view returns (address market);
}

File 17 of 28 : PendleStructs.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

struct TokenReserve {
    uint256 weight;
    uint256 balance;
}

struct PendingTransfer {
    uint256 amount;
    bool isOut;
}

File 18 of 28 : IPendleMarketFactory.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

import "./IPendleRouter.sol";

interface IPendleMarketFactory {
    /**
     * @notice Creates a market given a protocol ID, future yield token, and an ERC20 token.
     * @param xyt Token address of the futuonlyCorere yield token as base asset.
     * @param token Token address of an ERC20 token as quote asset.
     * @return market Returns the address of the newly created market.
     **/
    function createMarket(address xyt, address token) external returns (address market);

    /**
     * @notice Gets a reference to the PendleRouter contract.
     * @return Returns the router contract reference.
     **/
    function router() external view returns (IPendleRouter);

    function marketFactoryId() external view returns (bytes32);
}

File 19 of 28 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

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

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

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

File 20 of 28 : IPendlePausingManager.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;

interface IPendlePausingManager {
    event AddPausingAdmin(address admin);
    event RemovePausingAdmin(address admin);
    event PendingForgeEmergencyHandler(address _pendingForgeHandler);
    event PendingMarketEmergencyHandler(address _pendingMarketHandler);
    event PendingLiqMiningEmergencyHandler(address _pendingLiqMiningHandler);
    event ForgeEmergencyHandlerSet(address forgeEmergencyHandler);
    event MarketEmergencyHandlerSet(address marketEmergencyHandler);
    event LiqMiningEmergencyHandlerSet(address liqMiningEmergencyHandler);

    event PausingManagerLocked();
    event ForgeHandlerLocked();
    event MarketHandlerLocked();
    event LiqMiningHandlerLocked();

    event SetForgePaused(bytes32 forgeId, bool settingToPaused);
    event SetForgeAssetPaused(bytes32 forgeId, address underlyingAsset, bool settingToPaused);
    event SetForgeAssetExpiryPaused(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        bool settingToPaused
    );

    event SetForgeLocked(bytes32 forgeId);
    event SetForgeAssetLocked(bytes32 forgeId, address underlyingAsset);
    event SetForgeAssetExpiryLocked(bytes32 forgeId, address underlyingAsset, uint256 expiry);

    event SetMarketFactoryPaused(bytes32 marketFactoryId, bool settingToPaused);
    event SetMarketPaused(bytes32 marketFactoryId, address market, bool settingToPaused);

    event SetMarketFactoryLocked(bytes32 marketFactoryId);
    event SetMarketLocked(bytes32 marketFactoryId, address market);

    event SetLiqMiningPaused(address liqMiningContract, bool settingToPaused);
    event SetLiqMiningLocked(address liqMiningContract);

    function forgeEmergencyHandler()
        external
        view
        returns (
            address handler,
            address pendingHandler,
            uint256 timelockDeadline
        );

    function marketEmergencyHandler()
        external
        view
        returns (
            address handler,
            address pendingHandler,
            uint256 timelockDeadline
        );

    function liqMiningEmergencyHandler()
        external
        view
        returns (
            address handler,
            address pendingHandler,
            uint256 timelockDeadline
        );

    function permLocked() external view returns (bool);

    function permForgeHandlerLocked() external view returns (bool);

    function permMarketHandlerLocked() external view returns (bool);

    function permLiqMiningHandlerLocked() external view returns (bool);

    function isPausingAdmin(address) external view returns (bool);

    function setPausingAdmin(address admin, bool isAdmin) external;

    function requestForgeHandlerChange(address _pendingForgeHandler) external;

    function requestMarketHandlerChange(address _pendingMarketHandler) external;

    function requestLiqMiningHandlerChange(address _pendingLiqMiningHandler) external;

    function applyForgeHandlerChange() external;

    function applyMarketHandlerChange() external;

    function applyLiqMiningHandlerChange() external;

    function lockPausingManagerPermanently() external;

    function lockForgeHandlerPermanently() external;

    function lockMarketHandlerPermanently() external;

    function lockLiqMiningHandlerPermanently() external;

    function setForgePaused(bytes32 forgeId, bool paused) external;

    function setForgeAssetPaused(
        bytes32 forgeId,
        address underlyingAsset,
        bool paused
    ) external;

    function setForgeAssetExpiryPaused(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry,
        bool paused
    ) external;

    function setForgeLocked(bytes32 forgeId) external;

    function setForgeAssetLocked(bytes32 forgeId, address underlyingAsset) external;

    function setForgeAssetExpiryLocked(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external;

    function checkYieldContractStatus(
        bytes32 forgeId,
        address underlyingAsset,
        uint256 expiry
    ) external returns (bool _paused, bool _locked);

    function setMarketFactoryPaused(bytes32 marketFactoryId, bool paused) external;

    function setMarketPaused(
        bytes32 marketFactoryId,
        address market,
        bool paused
    ) external;

    function setMarketFactoryLocked(bytes32 marketFactoryId) external;

    function setMarketLocked(bytes32 marketFactoryId, address market) external;

    function checkMarketStatus(bytes32 marketFactoryId, address market)
        external
        returns (bool _paused, bool _locked);

    function setLiqMiningPaused(address liqMiningContract, bool settingToPaused) external;

    function setLiqMiningLocked(address liqMiningContract) external;

    function checkLiqMiningStatus(address liqMiningContract)
        external
        returns (bool _paused, bool _locked);
}

File 21 of 28 : IPendleMarket.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;
pragma abicoder v2;

import "./IPendleRouter.sol";
import "./IPendleBaseToken.sol";
import "../libraries/PendleStructs.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IPendleMarket is IERC20 {
    /**
     * @notice Emitted when reserves pool has been updated
     * @param reserve0 The XYT reserves.
     * @param weight0  The XYT weight
     * @param reserve1 The generic token reserves.
     * For the generic Token weight it can be inferred by (2^40) - weight0
     **/
    event Sync(uint256 reserve0, uint256 weight0, uint256 reserve1);
    event RedeemLpInterests(address user, uint256 interests);

    function setUpEmergencyMode(address spender) external;

    function bootstrap(
        address user,
        uint256 initialXytLiquidity,
        uint256 initialTokenLiquidity
    ) external returns (PendingTransfer[2] memory transfers, uint256 exactOutLp);

    function addMarketLiquiditySingle(
        address user,
        address inToken,
        uint256 inAmount,
        uint256 minOutLp
    ) external returns (PendingTransfer[2] memory transfers, uint256 exactOutLp);

    function addMarketLiquidityDual(
        address user,
        uint256 _desiredXytAmount,
        uint256 _desiredTokenAmount,
        uint256 _xytMinAmount,
        uint256 _tokenMinAmount
    ) external returns (PendingTransfer[2] memory transfers, uint256 lpOut);

    function removeMarketLiquidityDual(
        address user,
        uint256 inLp,
        uint256 minOutXyt,
        uint256 minOutToken
    ) external returns (PendingTransfer[2] memory transfers);

    function removeMarketLiquiditySingle(
        address user,
        address outToken,
        uint256 exactInLp,
        uint256 minOutToken
    ) external returns (PendingTransfer[2] memory transfers);

    function swapExactIn(
        address inToken,
        uint256 inAmount,
        address outToken,
        uint256 minOutAmount
    ) external returns (uint256 outAmount, PendingTransfer[2] memory transfers);

    function swapExactOut(
        address inToken,
        uint256 maxInAmount,
        address outToken,
        uint256 outAmount
    ) external returns (uint256 inAmount, PendingTransfer[2] memory transfers);

    function redeemLpInterests(address user) external returns (uint256 interests);

    function getReserves()
        external
        view
        returns (
            uint256 xytBalance,
            uint256 xytWeight,
            uint256 tokenBalance,
            uint256 tokenWeight,
            uint256 currentBlock
        );

    function factoryId() external view returns (bytes32);

    function token() external view returns (address);

    function xyt() external view returns (address);
}

File 22 of 28 : IPendleBaseToken.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity 0.7.6;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IPendleBaseToken is IERC20 {
    /**
     * @notice Decreases the allowance granted to spender by the caller.
     * @param spender The address to reduce the allowance from.
     * @param subtractedValue The amount allowance to subtract.
     * @return Returns true if allowance has decreased, otherwise false.
     **/
    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**
     * @notice The yield contract start in epoch time.
     * @return Returns the yield start date.
     **/
    function start() external view returns (uint256);

    /**
     * @notice The yield contract expiry in epoch time.
     * @return Returns the yield expiry date.
     **/
    function expiry() external view returns (uint256);

    /**
     * @notice Increases the allowance granted to spender by the caller.
     * @param spender The address to increase the allowance from.
     * @param addedValue The amount allowance to add.
     * @return Returns true if allowance has increased, otherwise false
     **/
    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);

    /**
     * @notice Returns the number of decimals the token uses.
     * @return Returns the token's decimals.
     **/
    function decimals() external view returns (uint8);

    /**
     * @notice Returns the name of the token.
     * @return Returns the token's name.
     **/
    function name() external view returns (string memory);

    /**
     * @notice Returns the symbol of the token.
     * @return Returns the token's symbol.
     **/
    function symbol() external view returns (string memory);

    /**
     * @notice approve using the owner's signature
     **/
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

File 23 of 28 : IPendleYieldContractDeployer.sol
// SPDX-License-Identifier: MIT
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */
pragma solidity 0.7.6;

interface IPendleYieldContractDeployer {
    function forgeId() external returns (bytes32);

    function forgeOwnershipToken(
        address _underlyingAsset,
        string memory _name,
        string memory _symbol,
        uint8 _decimals,
        uint256 _expiry
    ) external returns (address ot);

    function forgeFutureYieldToken(
        address _underlyingAsset,
        string memory _name,
        string memory _symbol,
        uint8 _decimals,
        uint256 _expiry
    ) external returns (address xyt);

    function deployYieldTokenHolder(address yieldToken, uint256 expiry)
        external
        returns (address yieldTokenHolder);
}

File 24 of 28 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @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, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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 subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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 25 of 28 : MathLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.0;
pragma abicoder v2;

import "@openzeppelin/contracts/math/SafeMath.sol";

library Math {
    using SafeMath for uint256;

    uint256 internal constant BIG_NUMBER = (uint256(1) << uint256(200));
    uint256 internal constant PRECISION_BITS = 40;
    uint256 internal constant RONE = uint256(1) << PRECISION_BITS;
    uint256 internal constant PI = (314 * RONE) / 10**2;
    uint256 internal constant PI_PLUSONE = (414 * RONE) / 10**2;
    uint256 internal constant PRECISION_POW = 1e2;

    function checkMultOverflow(uint256 _x, uint256 _y) internal pure returns (bool) {
        if (_y == 0) return false;
        return (((_x * _y) / _y) != _x);
    }

    /**
    @notice find the integer part of log2(p/q)
        => find largest x s.t p >= q * 2^x
        => find largest x s.t 2^x <= p / q
     */
    function log2Int(uint256 _p, uint256 _q) internal pure returns (uint256) {
        uint256 res = 0;
        uint256 remain = _p / _q;
        while (remain > 0) {
            res++;
            remain /= 2;
        }
        return res - 1;
    }

    /**
    @notice log2 for a number that it in [1,2)
    @dev _x is FP, return a FP
    @dev function is from Kyber. Long modified the condition to be (_x >= one) && (_x < two)
    to avoid the case where x = 2 may lead to incorrect result
     */
    function log2ForSmallNumber(uint256 _x) internal pure returns (uint256) {
        uint256 res = 0;
        uint256 one = (uint256(1) << PRECISION_BITS);
        uint256 two = 2 * one;
        uint256 addition = one;

        require((_x >= one) && (_x < two), "MATH_ERROR");
        require(PRECISION_BITS < 125, "MATH_ERROR");

        for (uint256 i = PRECISION_BITS; i > 0; i--) {
            _x = (_x * _x) / one;
            addition = addition / 2;
            if (_x >= two) {
                _x = _x / 2;
                res += addition;
            }
        }

        return res;
    }

    /**
    @notice log2 of (p/q). returns result in FP form
    @dev function is from Kyber.
    @dev _p & _q is FP, return a FP
     */
    function logBase2(uint256 _p, uint256 _q) internal pure returns (uint256) {
        uint256 n = 0;

        if (_p > _q) {
            n = log2Int(_p, _q);
        }

        require(n * RONE <= BIG_NUMBER, "MATH_ERROR");
        require(!checkMultOverflow(_p, RONE), "MATH_ERROR");
        require(!checkMultOverflow(n, RONE), "MATH_ERROR");
        require(!checkMultOverflow(uint256(1) << n, _q), "MATH_ERROR");

        uint256 y = (_p * RONE) / (_q * (uint256(1) << n));
        uint256 log2Small = log2ForSmallNumber(y);

        assert(log2Small <= BIG_NUMBER);

        return n * RONE + log2Small;
    }

    /**
    @notice calculate ln(p/q). returned result >= 0
    @dev function is from Kyber.
    @dev _p & _q is FP, return a FP
    */
    function ln(uint256 p, uint256 q) internal pure returns (uint256) {
        uint256 ln2Numerator = 6931471805599453094172;
        uint256 ln2Denomerator = 10000000000000000000000;

        uint256 log2x = logBase2(p, q);

        require(!checkMultOverflow(ln2Numerator, log2x), "MATH_ERROR");

        return (ln2Numerator * log2x) / ln2Denomerator;
    }

    /**
    @notice extract the fractional part of a FP
    @dev value is a FP, return a FP
     */
    function fpart(uint256 value) internal pure returns (uint256) {
        return value % RONE;
    }

    /**
    @notice convert a FP to an Int
    @dev value is a FP, return an Int
     */
    function toInt(uint256 value) internal pure returns (uint256) {
        return value / RONE;
    }

    /**
    @notice convert an Int to a FP
    @dev value is an Int, return a FP
     */
    function toFP(uint256 value) internal pure returns (uint256) {
        return value * RONE;
    }

    /**
    @notice return e^exp in FP form
    @dev estimation by formula at http://pages.mtu.edu/~shene/COURSES/cs201/NOTES/chap04/exp.html
        the function is based on exp function of:
        https://github.com/NovakDistributed/macroverse/blob/master/contracts/RealMath.sol
    @dev the function is expected to converge quite fast, after about 20 iteration
    @dev exp is a FP, return a FP
     */
    function rpowe(uint256 exp) internal pure returns (uint256) {
        uint256 res = 0;

        uint256 curTerm = RONE;

        for (uint256 n = 0; ; n++) {
            res += curTerm;
            curTerm = rmul(curTerm, rdiv(exp, toFP(n + 1)));
            if (curTerm == 0) {
                break;
            }
            if (n == 500) {
                /*
                testing shows that in the most extreme case, it will take 430 turns to converge.
                however, it's expected that the numbers will not exceed 2^120 in normal situation
                the most extreme case is rpow((1<<256)-1,(1<<40)-1) (equal to rpow((2^256-1)/2^40,0.99..9))
                */
                revert("RPOWE_SLOW_CONVERGE");
            }
        }

        return res;
    }

    /**
    @notice calculate base^exp with base and exp being FP int
    @dev to improve accuracy, base^exp = base^(int(exp)+frac(exp))
                                       = base^int(exp) * base^frac
    @dev base & exp are FP, return a FP
     */
    function rpow(uint256 base, uint256 exp) internal pure returns (uint256) {
        if (exp == 0) {
            // Anything to the 0 is 1
            return RONE;
        }
        if (base == 0) {
            // 0 to anything except 0 is 0
            return 0;
        }

        uint256 frac = fpart(exp); // get the fractional part
        uint256 whole = exp - frac;

        uint256 wholePow = rpowi(base, toInt(whole)); // whole is a FP, convert to Int
        uint256 fracPow;

        // instead of calculating base ^ frac, we will calculate e ^ (frac*ln(base))
        if (base < RONE) {
            /* since the base is smaller than 1.0, ln(base) < 0.
            Since 1 / (e^(frac*ln(1/base))) = e ^ (frac*ln(base)),
            we will calculate 1 / (e^(frac*ln(1/base))) instead.
            */
            uint256 newExp = rmul(frac, ln(rdiv(RONE, base), RONE));
            fracPow = rdiv(RONE, rpowe(newExp));
        } else {
            /* base is greater than 1, calculate normally */
            uint256 newExp = rmul(frac, ln(base, RONE));
            fracPow = rpowe(newExp);
        }
        return rmul(wholePow, fracPow);
    }

    /**
    @notice return base^exp with base in FP form and exp in Int
    @dev this function use a technique called: exponentiating by squaring
        complexity O(log(q))
    @dev function is from Kyber.
    @dev base is a FP, exp is an Int, return a FP
     */
    function rpowi(uint256 base, uint256 exp) internal pure returns (uint256) {
        uint256 res = exp % 2 != 0 ? base : RONE;

        for (exp /= 2; exp != 0; exp /= 2) {
            base = rmul(base, base);

            if (exp % 2 != 0) {
                res = rmul(res, base);
            }
        }
        return res;
    }

    /**
    @dev y is an Int, returns an Int
    @dev babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    @dev from Uniswap
     */
    function sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    /**
    @notice divide 2 FP, return a FP
    @dev function is from Balancer.
    @dev x & y are FP, return a FP
     */
    function rdiv(uint256 x, uint256 y) internal pure returns (uint256) {
        return (y / 2).add(x.mul(RONE)).div(y);
    }

    /**
    @notice multiply 2 FP, return a FP
    @dev function is from Balancer.
    @dev x & y are FP, return a FP
     */
    function rmul(uint256 x, uint256 y) internal pure returns (uint256) {
        return (RONE / 2).add(x.mul(y)).div(RONE);
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    function subMax0(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a - b : 0;
    }
}

File 26 of 28 : TokenUtilsLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.7.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";

library TokenUtils {
    using SafeERC20 for IERC20;

    function requireERC20(address tokenAddr) internal view {
        require(IERC20(tokenAddr).totalSupply() > 0, "INVALID_ERC20");
    }

    function requireERC20(IERC20 token) internal view {
        require(token.totalSupply() > 0, "INVALID_ERC20");
    }

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        token.safeTransfer(to, value);
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        token.safeTransferFrom(from, to, value);
    }

    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        token.approve(spender, 0);
        token.approve(spender, value);
    }
}

File 27 of 28 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 28 of 28 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IPendleRouter","name":"_router","type":"address"},{"internalType":"contract IPendleRetroactiveDistribution","name":"_tokenDistContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"internalType":"address[]","name":"yts","type":"address[]"},{"internalType":"address[]","name":"ots","type":"address[]"},{"internalType":"address[]","name":"markets","type":"address[]"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"enum LmRedeemMode","name":"mode","type":"uint8"}],"internalType":"struct LmRedeemRequest[]","name":"lmV1","type":"tuple[]"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"enum LmRedeemMode","name":"mode","type":"uint8"}],"internalType":"struct LmRedeemRequest[]","name":"lmV2","type":"tuple[]"},{"internalType":"address[]","name":"tokensDistribution","type":"address[]"}],"internalType":"struct Args","name":"args","type":"tuple"},{"internalType":"address","name":"user","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256[]","name":"ytInterests","type":"uint256[]"},{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"address","name":"tokenC","type":"address"}],"internalType":"struct TrioTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"},{"internalType":"uint256","name":"uintC","type":"uint256"}],"internalType":"struct TrioUints","name":"uints","type":"tuple"}],"internalType":"struct TrioTokenUints[]","name":"otRewards","type":"tuple[]"},{"internalType":"uint256[]","name":"marketInterests","type":"uint256[]"},{"components":[{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"rewards","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"interests","type":"tuple"}],"internalType":"struct LmRedeemResult[]","name":"lmV1Returns","type":"tuple[]"},{"components":[{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"rewards","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"interests","type":"tuple"}],"internalType":"struct LmRedeemResult[]","name":"lmV2Returns","type":"tuple[]"},{"internalType":"uint256[]","name":"tokenDistReturns","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"enum LmRedeemMode","name":"mode","type":"uint8"}],"internalType":"struct LmRedeemRequest[]","name":"lm","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemLmV1","outputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"rewards","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"interests","type":"tuple"}],"internalType":"struct LmRedeemResult[]","name":"results","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"enum LmRedeemMode","name":"mode","type":"uint8"}],"internalType":"struct LmRedeemRequest[]","name":"lm","type":"tuple[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemLmV2","outputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"rewards","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"internalType":"struct PairTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"}],"internalType":"struct PairUints","name":"uints","type":"tuple"}],"internalType":"struct PairTokenUints","name":"interests","type":"tuple"}],"internalType":"struct LmRedeemResult[]","name":"results","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"markets","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemMarkets","outputs":[{"internalType":"uint256[]","name":"marketInterests","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"ots","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemOts","outputs":[{"components":[{"components":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"address","name":"tokenC","type":"address"}],"internalType":"struct TrioTokens","name":"tokens","type":"tuple"},{"components":[{"internalType":"uint256","name":"uintA","type":"uint256"},{"internalType":"uint256","name":"uintB","type":"uint256"},{"internalType":"uint256","name":"uintC","type":"uint256"}],"internalType":"struct TrioUints","name":"uints","type":"tuple"}],"internalType":"struct TrioTokenUints[]","name":"otRewards","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemTokenDist","outputs":[{"internalType":"uint256[]","name":"results","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"yts","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"redeemYts","outputs":[{"internalType":"uint256[]","name":"ytInterests","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IPendleRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenDistContract","outputs":[{"internalType":"contract IPendleRetroactiveDistribution","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b5060405162001b7138038062001b71833981016040819052620000349162000053565b6001600160601b0319606092831b8116608052911b1660a052620000aa565b6000806040838503121562000066578182fd5b8251620000738162000091565b6020840151909250620000868162000091565b809150509250929050565b6001600160a01b0381168114620000a757600080fd5b50565b60805160601c60a05160601c611a8e620000e3600039806108d35280610a0c5250806104665280610c8a5280610d405250611a8e6000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063d352dfd611610066578063d352dfd614610114578063d4a1826914610127578063de103a5b1461014c578063eb16262a14610161578063f887ea401461017457610093565b80634431fdce146100985780636d5ee809146100c157806377fd6294146100e1578063c188e68f14610101575b600080fd5b6100ab6100a6366004611351565b61017c565b6040516100b891906118a4565b60405180910390f35b6100d46100cf366004611351565b610413565b6040516100b891906118b7565b6100f46100ef3660046113d0565b61054c565b6040516100b89190611891565b6100f461010f3660046113d0565b610700565b6100d4610122366004611351565b6108b4565b61013a610135366004611506565b61096c565b6040516100b8969594939291906118ca565b610154610a0a565b6040516100b891906117dd565b6100d461016f366004611351565b610a2e565b610154610d3e565b6060826001600160401b038111801561019457600080fd5b506040519080825280602002602001820160405280156101ce57816020015b6101bb611246565b8152602001906001900390816101b35790505b50905060005b8381101561040b5760008585838181106101ea57fe5b90506020020160208101906101ff9190611319565b90506000816001600160a01b0316636c6f42396040518163ffffffff1660e01b815260040160206040518083038186803b15801561023c57600080fd5b505afa158015610250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102749190611335565b90506000816001600160a01b0316630f4ef8a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156102b157600080fd5b505afa1580156102c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e99190611335565b90506000836001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561032657600080fd5b505afa15801561033a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035e9190611335565b90506000846001600160a01b031663e184c9be6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039b57600080fd5b505afa1580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d391906114cf565b90506103e2848484848c610d62565b8787815181106103ee57fe5b6020026020010181905250505050505080806001019150506101d4565b509392505050565b606082806001600160401b038111801561042c57600080fd5b50604051908082528060200260200182016040528015610456578160200160208202803683370190505b50915060005b81811015610543577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356c132cf87878481811061049f57fe5b90506020020160208101906104b49190611319565b866040518363ffffffff1660e01b81526004016104d29291906117f1565b602060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052491906114cf565b83828151811061053057fe5b602090810291909101015260010161045c565b50509392505050565b606082806001600160401b038111801561056557600080fd5b5060405190808252806020026020018201604052801561059f57816020015b61058c61126b565b8152602001906001900390816105845790505b50915060005b818110156105435760008686838181106105bb57fe5b90506060020160400160208101906105d391906114e7565b60028111156105de57fe5b1480610618575060028686838181106105f357fe5b905060600201604001602081019061060b91906114e7565b600281111561061657fe5b145b156106545761063886868381811061062c57fe5b90506060020185610e7a565b83828151811061064457fe5b6020026020010151602001819052505b600186868381811061066257fe5b905060600201604001602081019061067a91906114e7565b600281111561068557fe5b14806106bf5750600286868381811061069a57fe5b90506060020160400160208101906106b291906114e7565b60028111156106bd57fe5b145b156106f8576106df8686838181106106d357fe5b90506060020185610faa565b8382815181106106eb57fe5b6020908102919091010151525b6001016105a5565b606082806001600160401b038111801561071957600080fd5b5060405190808252806020026020018201604052801561075357816020015b61074061126b565b8152602001906001900390816107385790505b50915060005b8181101561054357600086868381811061076f57fe5b905060600201604001602081019061078791906114e7565b600281111561079257fe5b14806107cc575060028686838181106107a757fe5b90506060020160400160208101906107bf91906114e7565b60028111156107ca57fe5b145b15610808576107ec8686838181106107e057fe5b905060600201856110ca565b8382815181106107f857fe5b6020026020010151602001819052505b600186868381811061081657fe5b905060600201604001602081019061082e91906114e7565b600281111561083957fe5b14806108735750600286868381811061084e57fe5b905060600201604001602081019061086691906114e7565b600281111561087157fe5b145b156108ac5761089386868381811061088757fe5b90506060020185611188565b83828151811061089f57fe5b6020908102919091010151525b600101610759565b6060821561096557604051637c3a6c7b60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f874d8f69061090c9087908790879060040161182e565b600060405180830381600087803b15801561092657600080fd5b505af115801561093a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610962919081019061142f565b90505b9392505050565b60608080808080610986610980898061198a565b89610a2e565b955061099e61099860208a018a61198a565b8961017c565b94506109b66109b060408a018a61198a565b89610413565b93506109ce6109c860608a018a6119d7565b8961054c565b92506109e66109e060808a018a6119d7565b89610700565b91506109fe6109f860a08a018a61198a565b896108b4565b90509295509295509295565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060826001600160401b0381118015610a4657600080fd5b50604051908082528060200260200182016040528015610a70578160200160208202803683370190505b50905060005b8381101561040b576000858583818110610a8c57fe5b9050602002016020810190610aa19190611319565b90506000816001600160a01b0316636c6f42396040518163ffffffff1660e01b815260040160206040518083038186803b158015610ade57600080fd5b505afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190611335565b6001600160a01b031663beb9a9736040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4e57600080fd5b505afa158015610b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8691906114cf565b90506000826001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610bc357600080fd5b505afa158015610bd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfb9190611335565b90506000836001600160a01b031663e184c9be6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c3857600080fd5b505afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7091906114cf565b6040516304946b9f60e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631251ae7c90610cc5908690869086908d9060040161194c565b602060405180830381600087803b158015610cdf57600080fd5b505af1158015610cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1791906114cf565b868681518110610d2357fe5b6020908102919091010152505060019092019150610a769050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610d6a611246565b604051636d18d09960e11b81526001600160a01b0386169063da31a13290610d969087906004016117dd565b606060405180830381600087803b158015610db057600080fd5b505af1158015610dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de891906115f7565b8152604051632ab77f9b60e11b81526001600160a01b0386169063556eff3690610e1a9087908790879060040161180b565b606060405180830381600087803b158015610e3457600080fd5b505af1158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190611661565b602082015295945050505050565b610e82611287565b610e8f6020840184611319565b6001600160a01b031663ddf0fa836040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec757600080fd5b505afa158015610edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eff9190611335565b81516001600160a01b039091169052610f1b6020840184611319565b6001600160a01b0316632cbb18708460200135846040518363ffffffff1660e01b8152600401610f4c929190611973565b602060405180830381600087803b158015610f6657600080fd5b505af1158015610f7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9e91906114cf565b60208201515292915050565b610fb2611287565b610fbf6020840184611319565b6001600160a01b031663248169fe6040518163ffffffff1660e01b8152600401604080518083038186803b158015610ff657600080fd5b505afa15801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e9190611559565b815261103d6020840184611319565b6001600160a01b031663c6323c268460200135846040518363ffffffff1660e01b815260040161106e929190611973565b6040805180830381600087803b15801561108757600080fd5b505af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf91906115b0565b602082015292915050565b6110d2611287565b6110df6020840184611319565b6001600160a01b031663b3cccfe36040518163ffffffff1660e01b8152600401604080518083038186803b15801561111657600080fd5b505afa15801561112a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114e9190611559565b815261115d6020840184611319565b6001600160a01b0316636304a6bc836040518263ffffffff1660e01b815260040161106e91906117dd565b611190611287565b61119d6020840184611319565b6001600160a01b031663248169fe6040518163ffffffff1660e01b8152600401604080518083038186803b1580156111d457600080fd5b505afa1580156111e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120c9190611559565b815261121b6020840184611319565b6001600160a01b0316639262187b836040518263ffffffff1660e01b815260040161106e91906117dd565b60405180604001604052806112596112a7565b81526020016112666112c7565b905290565b604051806040016040528061127e611287565b81526020016112665b604051806040016040528061129a6112e8565b81526020016112666112ff565b604080516060810182526000808252602082018190529181019190915290565b60405180606001604052806000815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b604051806040016040528060008152602001600081525090565b60006020828403121561132a578081fd5b813561096581611a40565b600060208284031215611346578081fd5b815161096581611a40565b600080600060408486031215611365578182fd5b83356001600160401b038082111561137b578384fd5b818601915086601f83011261138e578384fd5b81358181111561139c578485fd5b87602080830285010111156113af578485fd5b602092830195509350508401356113c581611a40565b809150509250925092565b6000806000604084860312156113e4578283fd5b83356001600160401b03808211156113fa578485fd5b818601915086601f83011261140d578485fd5b81358181111561141b578586fd5b8760206060830285010111156113af578586fd5b60006020808385031215611441578182fd5b82516001600160401b0380821115611457578384fd5b818501915085601f83011261146a578384fd5b81518181111561147657fe5b8381029150611486848301611a1d565b8181528481019084860184860187018a10156114a0578788fd5b8795505b838610156114c25780518352600195909501949186019186016114a4565b5098975050505050505050565b6000602082840312156114e0578081fd5b5051919050565b6000602082840312156114f8578081fd5b813560038110610965578182fd5b60008060408385031215611518578182fd5b82356001600160401b0381111561152d578283fd5b830160c0818603121561153e578283fd5b9150602083013561154e81611a40565b809150509250929050565b60006040828403121561156a578081fd5b604051604081018181106001600160401b038211171561158657fe5b604052825161159481611a40565b815260208301516115a481611a40565b60208201529392505050565b6000604082840312156115c1578081fd5b604051604081018181106001600160401b03821117156115dd57fe5b604052825181526020928301519281019290925250919050565b600060608284031215611608578081fd5b604051606081018181106001600160401b038211171561162457fe5b604052825161163281611a40565b8152602083015161164281611a40565b6020820152604083015161165581611a40565b60408201529392505050565b600060608284031215611672578081fd5b604051606081018181106001600160401b038211171561168e57fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000815180845260208085019450808401835b838110156117025781516116dd8882516117ac565b8301516116ed60808901826117ac565b506101009690960195908201906001016116c8565b509495945050505050565b6000815180845260208085019450808401835b83811015611702578151805180516001600160a01b039081168a52858201518116868b015260409182015116818a015290840151805160608a01528085015160808a0152015160a088015260c09096019590820190600101611720565b6000815180845260208085019450808401835b8381101561170257815187529582019590820190600101611790565b805180516001600160a01b039081168452602091820151168184015290810151805160408401520151606090910152565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6040808252810183905260008460608301825b8681101561187157823561185481611a40565b6001600160a01b0316825260209283019290910190600101611841565b506001600160a01b03949094166020939093019290925250909392505050565b60006020825261096560208301846116b5565b600060208252610965602083018461170d565b600060208252610965602083018461177d565b600060c082526118dd60c083018961177d565b82810360208401526118ef818961170d565b90508281036040840152611903818861177d565b9050828103606084015261191781876116b5565b9050828103608084015261192b81866116b5565b905082810360a084015261193f818561177d565b9998505050505050505050565b9384526001600160a01b039283166020850152604084019190915216606082015260800190565b9182526001600160a01b0316602082015260400190565b6000808335601e198436030181126119a0578283fd5b8301803591506001600160401b038211156119b9578283fd5b60209081019250810236038213156119d057600080fd5b9250929050565b6000808335601e198436030181126119ed578182fd5b8301803591506001600160401b03821115611a06578283fd5b60200191506060810236038213156119d057600080fd5b6040518181016001600160401b0381118282101715611a3857fe5b604052919050565b6001600160a01b0381168114611a5557600080fd5b5056fea2646970667358221220d9791d71347d9c7544016056d70a18a9b7676f378a56448612c6819d8675d22264736f6c63430007060033000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b52000000000000000000000000cfa2cd04c0a34793c25cda392147ce463ea50cab

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063d352dfd611610066578063d352dfd614610114578063d4a1826914610127578063de103a5b1461014c578063eb16262a14610161578063f887ea401461017457610093565b80634431fdce146100985780636d5ee809146100c157806377fd6294146100e1578063c188e68f14610101575b600080fd5b6100ab6100a6366004611351565b61017c565b6040516100b891906118a4565b60405180910390f35b6100d46100cf366004611351565b610413565b6040516100b891906118b7565b6100f46100ef3660046113d0565b61054c565b6040516100b89190611891565b6100f461010f3660046113d0565b610700565b6100d4610122366004611351565b6108b4565b61013a610135366004611506565b61096c565b6040516100b8969594939291906118ca565b610154610a0a565b6040516100b891906117dd565b6100d461016f366004611351565b610a2e565b610154610d3e565b6060826001600160401b038111801561019457600080fd5b506040519080825280602002602001820160405280156101ce57816020015b6101bb611246565b8152602001906001900390816101b35790505b50905060005b8381101561040b5760008585838181106101ea57fe5b90506020020160208101906101ff9190611319565b90506000816001600160a01b0316636c6f42396040518163ffffffff1660e01b815260040160206040518083038186803b15801561023c57600080fd5b505afa158015610250573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102749190611335565b90506000816001600160a01b0316630f4ef8a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156102b157600080fd5b505afa1580156102c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e99190611335565b90506000836001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561032657600080fd5b505afa15801561033a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035e9190611335565b90506000846001600160a01b031663e184c9be6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039b57600080fd5b505afa1580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d391906114cf565b90506103e2848484848c610d62565b8787815181106103ee57fe5b6020026020010181905250505050505080806001019150506101d4565b509392505050565b606082806001600160401b038111801561042c57600080fd5b50604051908082528060200260200182016040528015610456578160200160208202803683370190505b50915060005b81811015610543577f000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b526001600160a01b03166356c132cf87878481811061049f57fe5b90506020020160208101906104b49190611319565b866040518363ffffffff1660e01b81526004016104d29291906117f1565b602060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052491906114cf565b83828151811061053057fe5b602090810291909101015260010161045c565b50509392505050565b606082806001600160401b038111801561056557600080fd5b5060405190808252806020026020018201604052801561059f57816020015b61058c61126b565b8152602001906001900390816105845790505b50915060005b818110156105435760008686838181106105bb57fe5b90506060020160400160208101906105d391906114e7565b60028111156105de57fe5b1480610618575060028686838181106105f357fe5b905060600201604001602081019061060b91906114e7565b600281111561061657fe5b145b156106545761063886868381811061062c57fe5b90506060020185610e7a565b83828151811061064457fe5b6020026020010151602001819052505b600186868381811061066257fe5b905060600201604001602081019061067a91906114e7565b600281111561068557fe5b14806106bf5750600286868381811061069a57fe5b90506060020160400160208101906106b291906114e7565b60028111156106bd57fe5b145b156106f8576106df8686838181106106d357fe5b90506060020185610faa565b8382815181106106eb57fe5b6020908102919091010151525b6001016105a5565b606082806001600160401b038111801561071957600080fd5b5060405190808252806020026020018201604052801561075357816020015b61074061126b565b8152602001906001900390816107385790505b50915060005b8181101561054357600086868381811061076f57fe5b905060600201604001602081019061078791906114e7565b600281111561079257fe5b14806107cc575060028686838181106107a757fe5b90506060020160400160208101906107bf91906114e7565b60028111156107ca57fe5b145b15610808576107ec8686838181106107e057fe5b905060600201856110ca565b8382815181106107f857fe5b6020026020010151602001819052505b600186868381811061081657fe5b905060600201604001602081019061082e91906114e7565b600281111561083957fe5b14806108735750600286868381811061084e57fe5b905060600201604001602081019061086691906114e7565b600281111561087157fe5b145b156108ac5761089386868381811061088757fe5b90506060020185611188565b83828151811061089f57fe5b6020908102919091010151525b600101610759565b6060821561096557604051637c3a6c7b60e11b81526001600160a01b037f000000000000000000000000cfa2cd04c0a34793c25cda392147ce463ea50cab169063f874d8f69061090c9087908790879060040161182e565b600060405180830381600087803b15801561092657600080fd5b505af115801561093a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610962919081019061142f565b90505b9392505050565b60608080808080610986610980898061198a565b89610a2e565b955061099e61099860208a018a61198a565b8961017c565b94506109b66109b060408a018a61198a565b89610413565b93506109ce6109c860608a018a6119d7565b8961054c565b92506109e66109e060808a018a6119d7565b89610700565b91506109fe6109f860a08a018a61198a565b896108b4565b90509295509295509295565b7f000000000000000000000000cfa2cd04c0a34793c25cda392147ce463ea50cab81565b6060826001600160401b0381118015610a4657600080fd5b50604051908082528060200260200182016040528015610a70578160200160208202803683370190505b50905060005b8381101561040b576000858583818110610a8c57fe5b9050602002016020810190610aa19190611319565b90506000816001600160a01b0316636c6f42396040518163ffffffff1660e01b815260040160206040518083038186803b158015610ade57600080fd5b505afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190611335565b6001600160a01b031663beb9a9736040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4e57600080fd5b505afa158015610b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8691906114cf565b90506000826001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610bc357600080fd5b505afa158015610bd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfb9190611335565b90506000836001600160a01b031663e184c9be6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c3857600080fd5b505afa158015610c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7091906114cf565b6040516304946b9f60e21b81529091506001600160a01b037f000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b521690631251ae7c90610cc5908690869086908d9060040161194c565b602060405180830381600087803b158015610cdf57600080fd5b505af1158015610cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1791906114cf565b868681518110610d2357fe5b6020908102919091010152505060019092019150610a769050565b7f000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b5281565b610d6a611246565b604051636d18d09960e11b81526001600160a01b0386169063da31a13290610d969087906004016117dd565b606060405180830381600087803b158015610db057600080fd5b505af1158015610dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de891906115f7565b8152604051632ab77f9b60e11b81526001600160a01b0386169063556eff3690610e1a9087908790879060040161180b565b606060405180830381600087803b158015610e3457600080fd5b505af1158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190611661565b602082015295945050505050565b610e82611287565b610e8f6020840184611319565b6001600160a01b031663ddf0fa836040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec757600080fd5b505afa158015610edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eff9190611335565b81516001600160a01b039091169052610f1b6020840184611319565b6001600160a01b0316632cbb18708460200135846040518363ffffffff1660e01b8152600401610f4c929190611973565b602060405180830381600087803b158015610f6657600080fd5b505af1158015610f7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9e91906114cf565b60208201515292915050565b610fb2611287565b610fbf6020840184611319565b6001600160a01b031663248169fe6040518163ffffffff1660e01b8152600401604080518083038186803b158015610ff657600080fd5b505afa15801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e9190611559565b815261103d6020840184611319565b6001600160a01b031663c6323c268460200135846040518363ffffffff1660e01b815260040161106e929190611973565b6040805180830381600087803b15801561108757600080fd5b505af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf91906115b0565b602082015292915050565b6110d2611287565b6110df6020840184611319565b6001600160a01b031663b3cccfe36040518163ffffffff1660e01b8152600401604080518083038186803b15801561111657600080fd5b505afa15801561112a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114e9190611559565b815261115d6020840184611319565b6001600160a01b0316636304a6bc836040518263ffffffff1660e01b815260040161106e91906117dd565b611190611287565b61119d6020840184611319565b6001600160a01b031663248169fe6040518163ffffffff1660e01b8152600401604080518083038186803b1580156111d457600080fd5b505afa1580156111e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120c9190611559565b815261121b6020840184611319565b6001600160a01b0316639262187b836040518263ffffffff1660e01b815260040161106e91906117dd565b60405180604001604052806112596112a7565b81526020016112666112c7565b905290565b604051806040016040528061127e611287565b81526020016112665b604051806040016040528061129a6112e8565b81526020016112666112ff565b604080516060810182526000808252602082018190529181019190915290565b60405180606001604052806000815260200160008152602001600081525090565b604080518082019091526000808252602082015290565b604051806040016040528060008152602001600081525090565b60006020828403121561132a578081fd5b813561096581611a40565b600060208284031215611346578081fd5b815161096581611a40565b600080600060408486031215611365578182fd5b83356001600160401b038082111561137b578384fd5b818601915086601f83011261138e578384fd5b81358181111561139c578485fd5b87602080830285010111156113af578485fd5b602092830195509350508401356113c581611a40565b809150509250925092565b6000806000604084860312156113e4578283fd5b83356001600160401b03808211156113fa578485fd5b818601915086601f83011261140d578485fd5b81358181111561141b578586fd5b8760206060830285010111156113af578586fd5b60006020808385031215611441578182fd5b82516001600160401b0380821115611457578384fd5b818501915085601f83011261146a578384fd5b81518181111561147657fe5b8381029150611486848301611a1d565b8181528481019084860184860187018a10156114a0578788fd5b8795505b838610156114c25780518352600195909501949186019186016114a4565b5098975050505050505050565b6000602082840312156114e0578081fd5b5051919050565b6000602082840312156114f8578081fd5b813560038110610965578182fd5b60008060408385031215611518578182fd5b82356001600160401b0381111561152d578283fd5b830160c0818603121561153e578283fd5b9150602083013561154e81611a40565b809150509250929050565b60006040828403121561156a578081fd5b604051604081018181106001600160401b038211171561158657fe5b604052825161159481611a40565b815260208301516115a481611a40565b60208201529392505050565b6000604082840312156115c1578081fd5b604051604081018181106001600160401b03821117156115dd57fe5b604052825181526020928301519281019290925250919050565b600060608284031215611608578081fd5b604051606081018181106001600160401b038211171561162457fe5b604052825161163281611a40565b8152602083015161164281611a40565b6020820152604083015161165581611a40565b60408201529392505050565b600060608284031215611672578081fd5b604051606081018181106001600160401b038211171561168e57fe5b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000815180845260208085019450808401835b838110156117025781516116dd8882516117ac565b8301516116ed60808901826117ac565b506101009690960195908201906001016116c8565b509495945050505050565b6000815180845260208085019450808401835b83811015611702578151805180516001600160a01b039081168a52858201518116868b015260409182015116818a015290840151805160608a01528085015160808a0152015160a088015260c09096019590820190600101611720565b6000815180845260208085019450808401835b8381101561170257815187529582019590820190600101611790565b805180516001600160a01b039081168452602091820151168184015290810151805160408401520151606090910152565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6040808252810183905260008460608301825b8681101561187157823561185481611a40565b6001600160a01b0316825260209283019290910190600101611841565b506001600160a01b03949094166020939093019290925250909392505050565b60006020825261096560208301846116b5565b600060208252610965602083018461170d565b600060208252610965602083018461177d565b600060c082526118dd60c083018961177d565b82810360208401526118ef818961170d565b90508281036040840152611903818861177d565b9050828103606084015261191781876116b5565b9050828103608084015261192b81866116b5565b905082810360a084015261193f818561177d565b9998505050505050505050565b9384526001600160a01b039283166020850152604084019190915216606082015260800190565b9182526001600160a01b0316602082015260400190565b6000808335601e198436030181126119a0578283fd5b8301803591506001600160401b038211156119b9578283fd5b60209081019250810236038213156119d057600080fd5b9250929050565b6000808335601e198436030181126119ed578182fd5b8301803591506001600160401b03821115611a06578283fd5b60200191506060810236038213156119d057600080fd5b6040518181016001600160401b0381118282101715611a3857fe5b604052919050565b6001600160a01b0381168114611a5557600080fd5b5056fea2646970667358221220d9791d71347d9c7544016056d70a18a9b7676f378a56448612c6819d8675d22264736f6c63430007060033

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

000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b52000000000000000000000000cfa2cd04c0a34793c25cda392147ce463ea50cab

-----Decoded View---------------
Arg [0] : _router (address): 0x771ad65bF2837C89A1CC0A0FC601d9De7f217b52
Arg [1] : _tokenDistContract (address): 0xcfa2Cd04C0a34793c25CDa392147ce463eA50CaB

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000771ad65bf2837c89a1cc0a0fc601d9de7f217b52
Arg [1] : 000000000000000000000000cfa2cd04c0a34793c25cda392147ce463ea50cab


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.