Mumbai Testnet

Contract

0x5DC2cbf16c8500DC05061fF0FBA933a3F2C06EF8

Overview

MATIC Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0 MATIC

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value
Liquidity Given ...271162722022-07-10 19:14:29627 days ago1657480469IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.00117824.19752614
Liquidity Given ...271162152022-07-10 19:09:43627 days ago1657480183IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0123666944.05803881
Liquidity Given ...271162022022-07-10 19:08:38627 days ago1657480118IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0134417447.88806125
Liquidity Given ...271161592022-07-10 19:05:02627 days ago1657479902IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0100358835.7542
Liquidity Given ...271160212022-07-10 18:53:30627 days ago1657479210IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.000421031.5
Liquidity Given ...271158242022-07-10 18:35:47627 days ago1657478147IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0087411431.14151465
Liquidity Given ...271155402022-07-10 18:07:58627 days ago1657476478IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0057930920.63869154
Liquidity Given ...271154672022-07-10 18:01:52627 days ago1657476112IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0157519253.39798429
Remove Liquidity270449442022-07-05 21:31:37632 days ago1657056697IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0032387827.58693797
New Liquidity ET...270258242022-07-04 7:27:34634 days ago1656919654IN
0x5DC2cbf1...3F2C06EF8
0.0005 MATIC0.4689010832.58661895
New Liquidity269858942022-07-01 11:36:05636 days ago1656675365IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.3160745530.38963674
Borrow Given Per...269854312022-07-01 10:52:03636 days ago1656672723IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0105599437.636
Borrow Given Per...269854212022-07-01 10:51:13636 days ago1656672673IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.009836735.41171213
Lend Given Perce...269853742022-07-01 10:47:17636 days ago1656672437IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.000568541.93999998
Collect269846432022-07-01 9:40:51636 days ago1656668451IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0044067329.16031818
Lend Given Perce...269754042022-06-30 20:20:58637 days ago1656620458IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0030504610.4087546
New Liquidity269735212022-06-30 17:16:44637 days ago1656609404IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.3732823735.89
Repay269733512022-06-30 16:57:11637 days ago1656608231IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0038839430.89509894
Liquidity Given ...269730782022-06-30 16:30:57637 days ago1656606657IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0090398130.63566271
Borrow Given Deb...269551482022-06-29 7:52:14638 days ago1656489134IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.000636462.42500007
Lend Given Insur...269550092022-06-29 7:39:32638 days ago1656488372IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0061567829.67641466
Lend Given Perce...269549162022-06-29 7:31:45639 days ago1656487905IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0068057330.36554337
Lend Given Perce...269546692022-06-29 7:11:06639 days ago1656486666IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.000336131.50000011
Lend Given Perce...269535072022-06-29 5:23:18639 days ago1656480198IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.0068108130.39306524
Borrow Given Per...269434152022-06-28 12:18:18639 days ago1656418698IN
0x5DC2cbf1...3F2C06EF8
0 MATIC0.000875983.12846902
View all transactions

Latest 25 internal transactions (View All)

Parent Txn Hash Block From To Value
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
0.0005 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
270258242022-07-04 7:27:34634 days ago1656919654
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269858942022-07-01 11:36:05636 days ago1656675365
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269735212022-06-30 17:16:44637 days ago1656609404
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
269348222022-06-27 20:54:09640 days ago1656363249
0x5DC2cbf1...3F2C06EF8
 Contract Creation0 MATIC
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TimeswapConvenience

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 75 : TimeswapConvenience.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from './interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IMint} from './interfaces/IMint.sol';
import {IBurn} from './interfaces/IBurn.sol';
import {ILend} from './interfaces/ILend.sol';
import {IWithdraw} from './interfaces/IWithdraw.sol';
import {IBorrow} from './interfaces/IBorrow.sol';
import {IPay} from './interfaces/IPay.sol';
import {IWETH} from './interfaces/IWETH.sol';
import {IDue} from './interfaces/IDue.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ITimeswapMintCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapMintCallback.sol';
import {ITimeswapLendCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapLendCallback.sol';
import {ITimeswapBorrowCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapBorrowCallback.sol';
import {ITimeswapPayCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapPayCallback.sol';
import {Mint} from './libraries/Mint.sol';
import {Burn} from './libraries/Burn.sol';
import {Lend} from './libraries/Lend.sol';
import {Withdraw} from './libraries/Withdraw.sol';
import {Borrow} from './libraries/Borrow.sol';
import {Pay} from './libraries/Pay.sol';
import {DeployNative} from './libraries/DeployNative.sol';
import {SafeTransfer} from './libraries/SafeTransfer.sol';

/// @title Timeswap Convenience
/// @author Timeswap Labs
/// @notice It is recommnded to use this contract to interact with Timeswap Core contract.
/// @notice All error messages are abbreviated and can be found in the documentation.
contract TimeswapConvenience is IConvenience {
    using SafeTransfer for IERC20;

    /* ===== MODEL ===== */

    /// @inheritdoc IConvenience
    IFactory public immutable override factory;
    /// @inheritdoc IConvenience
    IWETH public immutable override weth;

    /// @dev Stores the addresses of the Liquidty, Bond, Insurance, Collateralized Debt token contracts.
    mapping(IERC20 => mapping(IERC20 => mapping(uint256 => Native))) private natives;

    /* ===== VIEW ===== */

    /// @inheritdoc IConvenience
    function getNative(
        IERC20 asset,
        IERC20 collateral,
        uint256 maturity
    ) external view override returns (Native memory) {
        return natives[asset][collateral][maturity];
    }

    /* ===== INIT ===== */

    /// @dev Initializes the Convenience contract.
    /// @param _factory The address of factory contract used by this contract.
    /// @param _weth The address of the Wrapped ETH contract.
    constructor(IFactory _factory, IWETH _weth) {
        require(address(_factory) != address(0), 'E601');
        require(address(_weth) != address(0), 'E601');
        require(address(_factory) != address(_weth), 'E612');

        factory = _factory;
        weth = _weth;
    }

    /* ===== UPDATE ===== */

    receive() external payable {
        require(msg.sender == address(weth), 'E615');
    }

    /// @inheritdoc IConvenience
    function deployPair(DeployPair calldata params) external override {
        factory.createPair(params.asset, params.collateral);
    }

    /// @inheritdoc IConvenience
    function deployNatives(DeployNatives calldata params) external override {
        DeployNative.deploy(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function newLiquidity(IMint.NewLiquidity calldata params)
        external
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.newLiquidity(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function newLiquidityETHAsset(IMint.NewLiquidityETHAsset calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.newLiquidityETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function newLiquidityETHCollateral(IMint.NewLiquidityETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.newLiquidityETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenAsset(IMint.LiquidityGivenAsset calldata params)
        external
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenAsset(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenAssetETHAsset(IMint.LiquidityGivenAssetETHAsset calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenAssetETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenAssetETHCollateral(IMint.LiquidityGivenAssetETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenAssetETHCollateral(
            natives,
            this,
            factory,
            weth,
            params
        );
    }

    /// @inheritdoc IConvenience
    function liquidityGivenDebt(IMint.LiquidityGivenDebt calldata params)
        external
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenDebt(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenDebtETHAsset(IMint.LiquidityGivenDebtETHAsset calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenDebtETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenDebtETHCollateral(IMint.LiquidityGivenDebtETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenDebtETHCollateral(
            natives,
            this,
            factory,
            weth,
            params
        );
    }

    /// @inheritdoc IConvenience
    function liquidityGivenCollateral(IMint.LiquidityGivenCollateral calldata params)
        external
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenCollateral(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function liquidityGivenCollateralETHAsset(IMint.LiquidityGivenCollateralETHAsset calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenCollateralETHAsset(
            natives,
            this,
            factory,
            weth,
            params
        );
    }

    /// @inheritdoc IConvenience
    function liquidityGivenCollateralETHCollateral(IMint.LiquidityGivenCollateralETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = Mint.liquidityGivenCollateralETHCollateral(
            natives,
            this,
            factory,
            weth,
            params
        );
    }

    /// @inheritdoc IConvenience
    function removeLiquidity(IBurn.RemoveLiquidity calldata params)
        external
        override
        returns (uint256 assetOut, uint128 collateralOut)
    {
        (assetOut, collateralOut) = Burn.removeLiquidity(natives, factory, params);
    }

    /// @inheritdoc IConvenience
    function removeLiquidityETHAsset(IBurn.RemoveLiquidityETHAsset calldata params)
        external
        override
        returns (uint256 assetOut, uint128 collateralOut)
    {
        (assetOut, collateralOut) = Burn.removeLiquidityETHAsset(natives, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function removeLiquidityETHCollateral(IBurn.RemoveLiquidityETHCollateral calldata params)
        external
        override
        returns (uint256 assetOut, uint128 collateralOut)
    {
        (assetOut, collateralOut) = Burn.removeLiquidityETHCollateral(natives, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenBond(ILend.LendGivenBond calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenBond(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenBondETHAsset(ILend.LendGivenBondETHAsset calldata params)
        external
        payable
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenBondETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenBondETHCollateral(ILend.LendGivenBondETHCollateral calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenBondETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenInsurance(ILend.LendGivenInsurance calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenInsurance(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenInsuranceETHAsset(ILend.LendGivenInsuranceETHAsset calldata params)
        external
        payable
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenInsuranceETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenInsuranceETHCollateral(ILend.LendGivenInsuranceETHCollateral calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenInsuranceETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenPercent(ILend.LendGivenPercent calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenPercent(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenPercentETHAsset(ILend.LendGivenPercentETHAsset calldata params)
        external
        payable
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenPercentETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function lendGivenPercentETHCollateral(ILend.LendGivenPercentETHCollateral calldata params)
        external
        override
        returns (uint256 assetIn, IPair.Claims memory claimsOut)
    {
        (assetIn, claimsOut) = Lend.lendGivenPercentETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function collect(IWithdraw.Collect calldata params) external override returns (IPair.Tokens memory tokensOut) {
        tokensOut = Withdraw.collect(natives, factory, params);
    }

    /// @inheritdoc IConvenience
    function collectETHAsset(IWithdraw.CollectETHAsset calldata params)
        external
        override
        returns (IPair.Tokens memory tokensOut)
    {
        tokensOut = Withdraw.collectETHAsset(natives, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function collectETHCollateral(IWithdraw.CollectETHCollateral calldata params)
        external
        override
        returns (IPair.Tokens memory tokensOut)
    {
        tokensOut = Withdraw.collectETHCollateral(natives, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenDebt(IBorrow.BorrowGivenDebt calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenDebt(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenDebtETHAsset(IBorrow.BorrowGivenDebtETHAsset calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenDebtETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenDebtETHCollateral(IBorrow.BorrowGivenDebtETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenDebtETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenCollateral(IBorrow.BorrowGivenCollateral calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenCollateral(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenCollateralETHAsset(IBorrow.BorrowGivenCollateralETHAsset calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenCollateralETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenCollateralETHCollateral(IBorrow.BorrowGivenCollateralETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenCollateralETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenPercent(IBorrow.BorrowGivenPercent calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenPercent(natives, this, factory, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenPercentETHAsset(IBorrow.BorrowGivenPercentETHAsset calldata params)
        external
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenPercentETHAsset(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function borrowGivenPercentETHCollateral(IBorrow.BorrowGivenPercentETHCollateral calldata params)
        external
        payable
        override
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = Borrow.borrowGivenPercentETHCollateral(natives, this, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function repay(IPay.Repay calldata params) external override returns (uint128 assetIn, uint128 collateralOut) {
        (assetIn, collateralOut) = Pay.pay(natives, factory, params);
    }

    /// @inheritdoc IConvenience
    function repayETHAsset(IPay.RepayETHAsset calldata params)
        external
        payable
        override
        returns (uint128 assetIn, uint128 collateralOut)
    {
        (assetIn, collateralOut) = Pay.payETHAsset(natives, factory, weth, params);
    }

    /// @inheritdoc IConvenience
    function repayETHCollateral(IPay.RepayETHCollateral calldata params)
        external
        override
        returns (uint128 assetIn, uint128 collateralOut)
    {
        (assetIn, collateralOut) = Pay.payETHCollateral(natives, factory, weth, params);
    }

    /// @inheritdoc ITimeswapMintCallback
    function timeswapMintCallback(
        uint256 assetIn,
        uint112 collateralIn,
        bytes calldata data
    ) external override {
        (IERC20 asset, IERC20 collateral, address assetFrom, address collateralFrom) = abi.decode(
            data,
            (IERC20, IERC20, address, address)
        );
        IPair pair = getPairAndVerify(asset, collateral);
        callbackTransfer(asset, assetFrom, pair, assetIn);
        callbackTransfer(collateral, collateralFrom, pair, collateralIn);
    }

    /// @inheritdoc ITimeswapLendCallback
    function timeswapLendCallback(uint256 assetIn, bytes calldata data) external override {
        (IERC20 asset, IERC20 collateral, address from) = abi.decode(data, (IERC20, IERC20, address));
        IPair pair = getPairAndVerify(asset, collateral);
        callbackTransfer(asset, from, pair, assetIn);
    }

    /// @inheritdoc ITimeswapBorrowCallback
    function timeswapBorrowCallback(uint112 collateralIn, bytes calldata data) external override {
        (IERC20 asset, IERC20 collateral, address from) = abi.decode(data, (IERC20, IERC20, address));
        IPair pair = getPairAndVerify(asset, collateral);
        callbackTransfer(collateral, from, pair, collateralIn);
    }

    /// @inheritdoc ITimeswapPayCallback
    function timeswapPayCallback(uint128 assetIn, bytes calldata data) external override {
        (IERC20 asset, IERC20 collateral, address from) = abi.decode(data, (IERC20, IERC20, address));
        IPair pair = getPairAndVerify(asset, collateral);
        callbackTransfer(asset, from, pair, assetIn);
    }

    function getPairAndVerify(IERC20 asset, IERC20 collateral) private view returns (IPair pair) {
        pair = factory.getPair(asset, collateral);
        require(msg.sender == address(pair), 'E701');
    }

    function callbackTransfer(
        IERC20 token,
        address from,
        IPair pair,
        uint256 tokenIn
    ) private {
        if (from == address(this)) {
            weth.deposit{value: tokenIn}();
            token.safeTransfer(pair, tokenIn);
        } else {
            token.safeTransferFrom(from, pair, tokenIn);
        }
    }
}

File 2 of 75 : IConvenience.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IMint} from './IMint.sol';
import {IBurn} from './IBurn.sol';
import {ILend} from './ILend.sol';
import {IWithdraw} from './IWithdraw.sol';
import {IBorrow} from './IBorrow.sol';
import {IPay} from './IPay.sol';
import {ILiquidity} from './ILiquidity.sol';
import {IClaim} from './IClaim.sol';
import {IDue} from './IDue.sol';
import {IWETH} from './IWETH.sol';
import {ITimeswapMintCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapMintCallback.sol';
import {ITimeswapLendCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapLendCallback.sol';
import {ITimeswapBorrowCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapBorrowCallback.sol';
import {ITimeswapPayCallback} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/callback/ITimeswapPayCallback.sol';
import {IDeployNatives} from './IDeployNatives.sol';
import {IDeployPair} from './IDeployPair.sol';

/// @title Timeswap Convenience Interface
/// @author Ricsson W. Ngo
interface IConvenience is
    ITimeswapMintCallback,
    ITimeswapLendCallback,
    ITimeswapBorrowCallback,
    ITimeswapPayCallback,
    IDeployPair,
    IDeployNatives
{
    struct Native {
        ILiquidity liquidity;
        IClaim bondInterest;
        IClaim bondPrincipal;
        IClaim insuranceInterest;
        IClaim insurancePrincipal;
        IDue collateralizedDebt;
    }

    /* ===== VIEW ===== */

    /// @dev Return the address of the factory contract used by this contract.
    /// @return The address of the factory contract.
    function factory() external returns (IFactory);

    /// @dev Return the address of the Wrapped ETH contract.
    /// @return The address of WETH.
    function weth() external returns (IWETH);

    /// @dev Return the addresses of the Liquidty, Bond, Insurance, Collateralized Debt token contracts.
    /// @return The addresses of the native token contracts.
    function getNative(
        IERC20 asset,
        IERC20 collateral,
        uint256 maturity
    ) external view returns (Native memory);

    /// @dev Create pair contracts.
    /// @param params The parameters for this function found in IDeployPair interface.
    function deployPair(IDeployPair.DeployPair calldata params) external;

    /// @dev Create native token contracts.
    /// @param params The parameters for this function found in IDeployNative interface.
    function deployNatives(IDeployNatives.DeployNatives calldata params) external;

    /// @dev Calls the mint function and creates a new pool.
    /// @dev If the pair does not exist, creates a new pair first.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function newLiquidity(IMint.NewLiquidity calldata params)
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and creates a new pool.
    /// @dev If the pair does not exist, creates a new pair first.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the assetIn amount.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function newLiquidityETHAsset(IMint.NewLiquidityETHAsset calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and creates a new pool.
    /// @dev If the pair does not exist, creates a new pair first.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the collateralIn amount.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function newLiquidityETHCollateral(IMint.NewLiquidityETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenAsset(IMint.LiquidityGivenAsset calldata params)
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the assetIn amount.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenAssetETHAsset(IMint.LiquidityGivenAssetETHAsset calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The collateral ERC20 is the WETH contract.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the maxCollateral amount. Any excess ETH will be returned to Msg.sender.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenAssetETHCollateral(IMint.LiquidityGivenAssetETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenDebt(IMint.LiquidityGivenDebt calldata params)
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the assetIn amount.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenDebtETHAsset(IMint.LiquidityGivenDebtETHAsset calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The collateral ERC20 is the WETH contract.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the maxCollateral amount. Any excess ETH will be returned to Msg.sender.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenDebtETHCollateral(IMint.LiquidityGivenDebtETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenCollateral(IMint.LiquidityGivenCollateral calldata params)
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the assetIn amount.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenCollateralETHAsset(IMint.LiquidityGivenCollateralETHAsset calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the mint function and add more liquidity to an existing pool.
    /// @dev The collateral ERC20 is the WETH contract.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @dev Msg.value is the maxCollateral amount. Any excess ETH will be returned to Msg.sender.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IMint interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function liquidityGivenCollateralETHCollateral(IMint.LiquidityGivenCollateralETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the burn funtion and withdraw liquiidty from a pool.
    /// @param params The parameters for this function found in IBurn interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return collateralOut The amount of collateral ERC20 received by collateralTo.
    function removeLiquidity(IBurn.RemoveLiquidity calldata params)
        external
        returns (uint256 assetOut, uint128 collateralOut);

    /// @dev Calls the burn funtion and withdraw liquiidty from a pool.
    /// @dev The asset received is ETH which will be unwrapped from WETH.
    /// @param params The parameters for this function found in IBurn interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return collateralOut The amount of collateral ERC20 received by collateralTo.
    function removeLiquidityETHAsset(IBurn.RemoveLiquidityETHAsset calldata params)
        external
        returns (uint256 assetOut, uint128 collateralOut);

    /// @dev Calls the burn funtion and withdraw liquiidty from a pool.
    /// @dev The collateral received is ETH which will be unwrapped from WETH.
    /// @param params The parameters for this function found in IBurn interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return collateralOut The amount of collateral ERC20 received by collateralTo.
    function removeLiquidityETHCollateral(IBurn.RemoveLiquidityETHCollateral calldata params)
        external
        returns (uint256 assetOut, uint128 collateralOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the bond received by bondTo.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenBond(ILend.LendGivenBond calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the bond received by bondTo.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenBondETHAsset(ILend.LendGivenBondETHAsset calldata params)
        external
        payable
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the bond received by bondTo.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenBondETHCollateral(ILend.LendGivenBondETHCollateral calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the insurance received by insuranceTo.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenInsurance(ILend.LendGivenInsurance calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the insurance received by insuranceTo.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenInsuranceETHAsset(ILend.LendGivenInsuranceETHAsset calldata params)
        external
        payable
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given the insurance received by insuranceTo.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenInsuranceETHCollateral(ILend.LendGivenInsuranceETHCollateral calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given percentage ratio of bond and insurance.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenPercent(ILend.LendGivenPercent calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given percentage ratio of bond and insurance.
    /// @dev The asset deposited is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenPercentETHAsset(ILend.LendGivenPercentETHAsset calldata params)
        external
        payable
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the lend function and deposit asset into a pool.
    /// @dev Calls given percentage ratio of bond and insurance.
    /// @dev Must have the asset ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in ILend interface.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond ERC20 and insurance ERC20 received by bondTo and insuranceTo.
    function lendGivenPercentETHCollateral(ILend.LendGivenPercentETHCollateral calldata params)
        external
        returns (uint256 assetIn, IPair.Claims memory claimsOut);

    /// @dev Calls the withdraw function and withdraw asset and collateral from a pool.
    /// @param params The parameters for this function found in IWithdraw interface.
    /// @return tokensOut The amount of asset ERC20 and collateral ERC20 received by assetTo and collateralTo.
    function collect(IWithdraw.Collect calldata params) external returns (IPair.Tokens memory tokensOut);

    /// @dev Calls the withdraw function and withdraw asset and collateral from a pool.
    /// @dev The asset received is ETH which will be unwrapped from WETH.
    /// @param params The parameters for this function found in IWithdraw interface.
    /// @return tokensOut The amount of asset ERC20 and collateral ERC20 received by assetTo and collateralTo.
    function collectETHAsset(IWithdraw.CollectETHAsset calldata params)
        external
        returns (IPair.Tokens memory tokensOut);

    /// @dev Calls the withdraw function and withdraw asset and collateral from a pool.
    /// @dev The collateral received is ETH which will be unwrapped from WETH.
    /// @param params The parameters for this function found in IWithdraw interface.
    /// @return tokensOut The amount of asset ERC20 and collateral ERC20 received by assetTo and collateralTo.
    function collectETHCollateral(IWithdraw.CollectETHCollateral calldata params)
        external
        returns (IPair.Tokens memory tokensOut);

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the debt received by dueTo.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenDebt(IBorrow.BorrowGivenDebt calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the debt received by dueTo.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenDebtETHAsset(IBorrow.BorrowGivenDebtETHAsset calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the debt received by dueTo.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenDebtETHCollateral(IBorrow.BorrowGivenDebtETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the collateral locked.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenCollateral(IBorrow.BorrowGivenCollateral calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the collateral locked.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenCollateralETHAsset(IBorrow.BorrowGivenCollateralETHAsset calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given the collateral locked.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenCollateralETHCollateral(IBorrow.BorrowGivenCollateralETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given percentage ratio of debt and collateral.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenPercent(IBorrow.BorrowGivenPercent calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given percentage ratio of debt and collateral.
    /// @dev Must have the collateral ERC20 approve this contract before calling this function.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenPercentETHAsset(IBorrow.BorrowGivenPercentETHAsset calldata params)
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the borrow function and borrow asset from a pool and locking collateral into the pool.
    /// @dev Calls given percentage ratio of debt and collateral.
    /// @dev The collateral locked is ETH which will be wrapped as WETH.
    /// @param params The parameters for this function found in IBorrow interface.
    /// @return assetOut The amount of asset ERC20 received by assetTo.
    /// @return id The token id of collateralized debt ERC721 received by dueTo.
    /// @return dueOut The collateralized debt ERC721 received by dueTo.
    function borrowGivenPercentETHCollateral(IBorrow.BorrowGivenPercentETHCollateral calldata params)
        external
        payable
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        );

    /// @dev Calls the pay function and withdraw collateral from a pool given debt is paid or being paid.
    /// @dev If there is debt being paid, must have the asset ERC20 approve this contract before calling this function.
    /// @dev Possible to pay debt of collateralized debt not owned by msg.sender, which means no collateral is withdraw.
    /// @param params The parameters for this function found in IPay interface.
    /// @return assetIn The total amount of asset ERC20 paid.
    /// @return collateralOut The total amount of collateral ERC20 receceived by to;
    function repay(IPay.Repay calldata params) external returns (uint128 assetIn, uint128 collateralOut);

    /// @dev Calls the pay function and withdraw collateral from a pool given debt is paid or being paid.
    //// @dev The asset being paid is ETH which will be wrapped as WETH.
    /// @dev Possible to pay debt of collateralized debt not owned by msg.sender, which means no collateral is withdraw.
    /// @param params The parameters for this function found in IPay interface.
    /// @return assetIn The total amount of asset ERC20 paid.
    /// @return collateralOut The total amount of collateral ERC20 receceived by to;
    function repayETHAsset(IPay.RepayETHAsset calldata params)
        external
        payable
        returns (uint128 assetIn, uint128 collateralOut);

    /// @dev Calls the pay function and withdraw collateral from a pool given debt is paid or being paid.
    /// @dev The collateral received is ETH which will be unwrapped from WETH.
    /// @dev If there is debt being paid, must have the asset ERC20 approve this contract before calling this function.
    /// @dev Possible to pay debt of collateralized debt not owned by msg.sender, which means no collateral is withdraw.
    /// @param params The parameters for this function found in IPay interface.
    /// @return assetIn The total amount of asset ERC20 paid.
    /// @return collateralOut The total amount of collateral ERC20 receceived by to;
    function repayETHCollateral(IPay.RepayETHCollateral calldata params)
        external
        returns (uint128 assetIn, uint128 collateralOut);
}

File 3 of 75 : IFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

import {IPair} from './IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IFactory {
    /* ===== EVENT ===== */

    /// @dev Emits when a new Timeswap Pair contract is created.
    /// @param asset The address of the ERC20 being lent and borrowed.
    /// @param collateral The address of the ERC20 used as collateral.
    /// @param pair The address of the Timeswap Pair contract created.
    event CreatePair(IERC20 indexed asset, IERC20 indexed collateral, IPair pair);

    /// @dev Emits when a new pending owner is set.
    /// @param pendingOwner The address of the new pending owner.
    event SetOwner(address indexed pendingOwner);

    /// @dev Emits when the pending owner has accepted being the new owner.
    /// @param owner The address of the new owner.
    event AcceptOwner(address indexed owner);

    /* ===== VIEW ===== */

    /// @dev Return the address that receives the protocol fee.
    /// @return The address of the owner.
    function owner() external view returns (address);

    /// @dev Return the new pending address to replace the owner.
    /// @return The address of the pending owner.
    function pendingOwner() external view returns (address);

    /// @dev Return the fee per second earned by liquidity providers.
    /// @dev Must be downcasted to uint16.
    /// @return The fee following UQ0.40 format.
    function fee() external view returns (uint256);

    /// @dev Return the protocol fee per second earned by the owner.
    /// @dev Must be downcasted to uint16.
    /// @return The protocol fee per second following UQ0.40 format.
    function protocolFee() external view returns (uint256);

    /// @dev Returns the address of a deployed pair.
    /// @param asset The address of the ERC20 being lent and borrowed.
    /// @param collateral The address of the ERC20 used as collateral.
    /// @return pair The address of the Timeswap Pair contract.
    function getPair(IERC20 asset, IERC20 collateral) external view returns (IPair pair);

    /* ===== UPDATE ===== */

    /// @dev Creates a Timeswap Pool based on ERC20 pair parameters.
    /// @dev Cannot create a Timeswap Pool with the same pair parameters.
    /// @param asset The address of the ERC20 being lent and borrowed.
    /// @param collateral The address of the ERC20 as the collateral.
    /// @return pair The address of the Timeswap Pair contract.
    function createPair(IERC20 asset, IERC20 collateral) external returns (IPair pair);

    /// @dev Set the pending owner of the factory.
    /// @dev Can only be called by the current owner.
    /// @param _pendingOwner the chosen pending owner.
    function setPendingOwner(address _pendingOwner) external;

    /// @dev Set the pending owner as the owner of the factory.
    /// @dev Reset the pending owner to zero.
    /// @dev Can only be called by the pending owner.
    function acceptOwner() external;
}

File 4 of 75 : IMint.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from './IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

interface IMint {
    struct NewLiquidity {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint112 debtIn;
        uint112 collateralIn;
        uint256 deadline;
    }

    struct NewLiquidityETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 debtIn;
        uint112 collateralIn;
        uint256 deadline;
    }

    struct NewLiquidityETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint112 debtIn;
        uint256 deadline;
    }

    struct _NewLiquidity {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetFrom;
        address collateralFrom;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint112 debtIn;
        uint112 collateralIn;
        uint256 deadline;
    }

    struct LiquidityGivenAsset {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint256 minLiquidity;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenAssetETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint256 minLiquidity;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenAssetETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint256 minLiquidity;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct _LiquidityGivenAsset {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetFrom;
        address collateralFrom;
        address liquidityTo;
        address dueTo;
        uint112 assetIn;
        uint256 minLiquidity;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenDebt {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 debtIn;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenDebtETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 debtIn;
        uint256 minLiquidity;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenDebtETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 debtIn;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint256 deadline;
    }

    struct _LiquidityGivenDebt {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetFrom;
        address collateralFrom;
        address liquidityTo;
        address dueTo;
        uint112 debtIn;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct LiquidityGivenCollateral {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 collateralIn;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct LiquidityGivenCollateralETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 collateralIn;
        uint256 minLiquidity;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct LiquidityGivenCollateralETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct _LiquidityGivenCollateral {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetFrom;
        address collateralFrom;
        address liquidityTo;
        address dueTo;
        uint112 collateralIn;
        uint256 minLiquidity;
        uint112 maxAsset;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct _Mint {
        IConvenience convenience;
        IPair pair;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetFrom;
        address collateralFrom;
        address liquidityTo;
        address dueTo;
        uint112 xIncrease;
        uint112 yIncrease;
        uint112 zIncrease;
        uint256 deadline;
    }
}

File 5 of 75 : IBurn.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';

interface IBurn {
    struct RemoveLiquidity {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address collateralTo;
        uint256 liquidityIn;
    }

    struct RemoveLiquidityETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address payable assetTo;
        address collateralTo;
        uint256 liquidityIn;
    }

    struct RemoveLiquidityETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address assetTo;
        address payable collateralTo;
        uint256 liquidityIn;
    }

    struct _RemoveLiquidity {
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address collateralTo;
        uint256 liquidityIn;
    }
}

File 6 of 75 : ILend.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

interface ILend {
    struct LendGivenBond {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 bondOut;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct LendGivenBondETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint128 bondOut;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct LendGivenBondETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 bondOut;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct _LendGivenBond {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 bondOut;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct LendGivenInsurance {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 insuranceOut;
        uint128 minBond;
        uint256 deadline;
    }

    struct LendGivenInsuranceETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint128 insuranceOut;
        uint128 minBond;
        uint256 deadline;
    }

    struct LendGivenInsuranceETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 insuranceOut;
        uint128 minBond;
        uint256 deadline;
    }

    struct _LendGivenInsurance {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint128 insuranceOut;
        uint128 minBond;
        uint256 deadline;
    }

    struct LendGivenPercent {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint40 percent;
        uint128 minBond;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct LendGivenPercentETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint40 percent;
        uint128 minBond;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct LendGivenPercentETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint40 percent;
        uint128 minBond;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct _LendGivenPercent {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address bondTo;
        address insuranceTo;
        uint112 assetIn;
        uint40 percent;
        uint128 minBond;
        uint128 minInsurance;
        uint256 deadline;
    }

    struct _Lend {
        IConvenience convenience;
        IPair pair;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address bondTo;
        address insuranceTo;
        uint112 xIncrease;
        uint112 yDecrease;
        uint112 zDecrease;
        uint256 deadline;
    }
}

File 7 of 75 : IWithdraw.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

interface IWithdraw {
    struct Collect {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address collateralTo;
        IPair.Claims claimsIn;
    }

    struct CollectETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address payable assetTo;
        address collateralTo;
        IPair.Claims claimsIn;
    }

    struct CollectETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address assetTo;
        address payable collateralTo;
        IPair.Claims claimsIn;
    }

    struct _Collect {
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address collateralTo;
        IPair.Claims claimsIn;
    }
}

File 8 of 75 : IBorrow.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

interface IBorrow {
    struct BorrowGivenDebt {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 debtIn;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct BorrowGivenDebtETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address payable assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 debtIn;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct BorrowGivenDebtETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 debtIn;
        uint256 deadline;
    }

    struct _BorrowGivenDebt {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 debtIn;
        uint112 maxCollateral;
        uint256 deadline;
    }
    struct BorrowGivenCollateral {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 collateralIn;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct BorrowGivenCollateralETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address payable assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 collateralIn;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct BorrowGivenCollateralETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct _BorrowGivenCollateral {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint112 collateralIn;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct BorrowGivenPercent {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint40 percent;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct BorrowGivenPercentETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address payable assetTo;
        address dueTo;
        uint112 assetOut;
        uint40 percent;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct BorrowGivenPercentETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint40 percent;
        uint112 maxDebt;
        uint256 deadline;
    }

    struct _BorrowGivenPercent {
        IConvenience convenience;
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address assetTo;
        address dueTo;
        uint112 assetOut;
        uint40 percent;
        uint112 maxDebt;
        uint112 maxCollateral;
        uint256 deadline;
    }

    struct _Borrow {
        IConvenience convenience;
        IPair pair;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address assetTo;
        address dueTo;
        uint112 xDecrease;
        uint112 yIncrease;
        uint112 zIncrease;
        uint256 deadline;
    }
}

File 9 of 75 : IPay.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';

interface IPay {
    struct Repay {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address collateralTo;
        uint256[] ids;
        uint112[] maxAssetsIn;
        uint256 deadline;
    }

    struct RepayETHAsset {
        IERC20 collateral;
        uint256 maturity;
        address collateralTo;
        uint256[] ids;
        uint112[] maxAssetsIn;
        uint256 deadline;
    }

    struct RepayETHCollateral {
        IERC20 asset;
        uint256 maturity;
        address payable collateralTo;
        uint256[] ids;
        uint112[] maxAssetsIn;
        uint256 deadline;
    }

    struct _Repay {
        IFactory factory;
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        address from;
        address collateralTo;
        uint256[] ids;
        uint112[] maxAssetsIn;
        uint256 deadline;
    }
}

File 10 of 75 : IWETH.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

/// @title WETH9 Interface
/// @author Ricsson W. Ngo
interface IWETH is IERC20 {
    /* ===== UPDATE ===== */

    function deposit() external payable;

    function withdraw(uint256 amount) external;
}

File 11 of 75 : IDue.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC721Permit} from './IERC721Permit.sol';
import {IConvenience} from './IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

/// @author Ricsson W. Ngo
interface IDue is IERC721Permit {
    // VIEW

    function convenience() external returns (IConvenience);

    function pair() external returns (IPair);

    function maturity() external returns (uint256);

    function dueOf(uint256 id) external returns (IPair.Due memory);

    // UPDATE

    function mint(address to, uint256 id) external;
}

File 12 of 75 : IPair.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

import {IFactory} from './IFactory.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IPair {
    /* ===== STRUCT ===== */

    struct Tokens {
        uint128 asset;
        uint128 collateral;
    }

    struct Claims {
        uint112 bondPrincipal;
        uint112 bondInterest;
        uint112 insurancePrincipal;
        uint112 insuranceInterest;
    }

    struct Due {
        uint112 debt;
        uint112 collateral;
        uint32 startBlock;
    }

    struct State {
        Tokens reserves;
        uint256 feeStored;
        uint256 totalLiquidity;
        Claims totalClaims;
        uint120 totalDebtCreated;
        uint112 x;
        uint112 y;
        uint112 z;
    }

    struct Pool {
        State state;
        mapping(address => uint256) liquidities;
        mapping(address => Claims) claims;
        mapping(address => Due[]) dues;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param liquidityTo The address of the receiver of liquidity balance.
    /// @param dueTo The addres of the receiver of collateralized debt balance.
    /// @param xIncrease The increase in the X state.
    /// @param yIncrease The increase in the Y state.
    /// @param zIncrease The increase in the Z state.
    /// @param data The data for callback.
    struct MintParam {
        uint256 maturity;
        address liquidityTo;
        address dueTo;
        uint112 xIncrease;
        uint112 yIncrease;
        uint112 zIncrease;
        bytes data;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param collateralTo The addres of the receiver of collateral ERC20.
    /// @param liquidityIn The amount of liquidity balance burnt by the msg.sender.
    struct BurnParam {
        uint256 maturity;
        address assetTo;
        address collateralTo;
        uint256 liquidityIn;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param bondTo The address of the receiver of bond balance.
    /// @param insuranceTo The addres of the receiver of insurance balance.
    /// @param xIncrease The increase in x state and the amount of asset ERC20 sent.
    /// @param yDecrease The decrease in y state.
    /// @param zDecrease The decrease in z state.
    /// @param data The data for callback.
    struct LendParam {
        uint256 maturity;
        address bondTo;
        address insuranceTo;
        uint112 xIncrease;
        uint112 yDecrease;
        uint112 zDecrease;
        bytes data;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param collateralTo The addres of the receiver of collateral ERC20.
    /// @param claimsIn The amount of bond balance and insurance balance burnt by the msg.sender.
    struct WithdrawParam {
        uint256 maturity;
        address assetTo;
        address collateralTo;
        Claims claimsIn;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param dueTo The address of the receiver of collateralized debt.
    /// @param xDecrease The decrease in x state and amount of asset ERC20 received by assetTo.
    /// @param yIncrease The increase in y state.
    /// @param zIncrease The increase in z state.
    /// @param data The data for callback.
    struct BorrowParam {
        uint256 maturity;
        address assetTo;
        address dueTo;
        uint112 xDecrease;
        uint112 yIncrease;
        uint112 zIncrease;
        bytes data;
    }

    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param to The address of the receiver of collateral ERC20.
    /// @param owner The addres of the owner of collateralized debt.
    /// @param ids The array indexes of collateralized debts.
    /// @param assetsIn The amount of asset ERC20 paid per collateralized debts.
    /// @param collateralsOut The amount of collateral ERC20 withdrawn per collaterlaized debts.
    /// @param data The data for callback.
    struct PayParam {
        uint256 maturity;
        address to;
        address owner;
        uint256[] ids;
        uint112[] assetsIn;
        uint112[] collateralsOut;
        bytes data;
    }

    /* ===== EVENT ===== */

    /// @dev Emits when the state gets updated.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param x The new x state of the pool.
    /// @param y The new y state of the pool.
    /// @param z The new z state of the pool.
    event Sync(uint256 indexed maturity, uint112 x, uint112 y, uint112 z);

    /// @dev Emits when mint function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param liquidityTo The address of the receiver of liquidity balance.
    /// @param dueTo The address of the receiver of collateralized debt balance.
    /// @param assetIn The increase in the X state.
    /// @param liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @param id The array index of the collateralized debt received by dueTo.
    /// @param dueOut The collateralized debt received by dueTo.
    /// @param feeIn The amount of fee asset ERC20 deposited.
    event Mint(
        uint256 maturity,
        address indexed sender,
        address indexed liquidityTo,
        address indexed dueTo,
        uint256 assetIn,
        uint256 liquidityOut,
        uint256 id,
        Due dueOut,
        uint256 feeIn
    );

    /// @dev Emits when burn function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param collateralTo The addres of the receiver of collateral ERC20.
    /// @param liquidityIn The amount of liquidity balance burnt by the sender.
    /// @param assetOut The amount of asset ERC20 received.
    /// @param collateralOut The amount of collateral ERC20 received.
    /// @param feeOut The amount of fee asset ERC20 received.
    event Burn(
        uint256 maturity,
        address indexed sender,
        address indexed assetTo,
        address indexed collateralTo,
        uint256 liquidityIn,
        uint256 assetOut,
        uint128 collateralOut,
        uint256 feeOut
    );

    /// @dev Emits when lend function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param bondTo The address of the receiver of bond balance.
    /// @param insuranceTo The addres of the receiver of insurance balance.
    /// @param assetIn The increase in X state.
    /// @param claimsOut The amount of bond balance and insurance balance received.
    /// @param feeIn The amount of fee paid by lender.
    /// @param protocolFeeIn The amount of protocol fee paid by lender.
    event Lend(
        uint256 maturity,
        address indexed sender,
        address indexed bondTo,
        address indexed insuranceTo,
        uint256 assetIn,
        Claims claimsOut,
        uint256 feeIn,
        uint256 protocolFeeIn
    );

    /// @dev Emits when withdraw function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param collateralTo The address of the receiver of collateral ERC20.
    /// @param claimsIn The amount of bond balance and insurance balance burnt by the sender.
    /// @param tokensOut The amount of asset ERC20 and collateral ERC20 received.
    event Withdraw(
        uint256 maturity,
        address indexed sender,
        address indexed assetTo,
        address indexed collateralTo,
        Claims claimsIn,
        Tokens tokensOut
    );

    /// @dev Emits when borrow function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param assetTo The address of the receiver of asset ERC20.
    /// @param dueTo The address of the receiver of collateralized debt.
    /// @param assetOut The amount of asset ERC20 received by assetTo.
    /// @param id The array index of the collateralized debt received by dueTo.
    /// @param dueOut The collateralized debt received by dueTo.
    /// @param feeIn The amount of fee paid by lender.
    /// @param protocolFeeIn The amount of protocol fee paid by lender.
    event Borrow(
        uint256 maturity,
        address indexed sender,
        address indexed assetTo,
        address indexed dueTo,
        uint256 assetOut,
        uint256 id,
        Due dueOut,
        uint256 feeIn,
        uint256 protocolFeeIn
    );

    /// @dev Emits when pay function is called.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param sender The address of the caller.
    /// @param to The address of the receiver of collateral ERC20.
    /// @param owner The address of the owner of collateralized debt.
    /// @param ids The array indexes of collateralized debts.
    /// @param assetsIn The amount of asset ERC20 paid per collateralized debts.
    /// @param collateralsOut The amount of collateral ERC20 withdrawn per collaterelized debts.
    /// @param assetIn The total amount of asset ERC20 paid.
    /// @param collateralOut The total amount of collateral ERC20 received.
    event Pay(
        uint256 maturity,
        address indexed sender,
        address indexed to,
        address indexed owner,
        uint256[] ids,
        uint112[] assetsIn,
        uint112[] collateralsOut,
        uint128 assetIn,
        uint128 collateralOut
    );

    /// @dev Emits when collectProtocolFee function is called
    /// @param sender The address of the caller.
    /// @param to The address of the receiver of asset ERC20.
    /// @param protocolFeeOut The amount of protocol fee asset ERC20 received.
    event CollectProtocolFee(
        address indexed sender,
        address indexed to,
        uint256 protocolFeeOut
    );

    /* ===== VIEW ===== */

    /// @dev Return the address of the factory contract that deployed this contract.
    /// @return The address of the factory contract.
    function factory() external view returns (IFactory);

    /// @dev Return the address of the ERC20 being lent and borrowed.
    /// @return The address of the asset ERC20.
    function asset() external view returns (IERC20);

    /// @dev Return the address of the ERC20 as collateral.
    /// @return The address of the collateral ERC20.
    function collateral() external view returns (IERC20);

    //// @dev Return the fee per second earned by liquidity providers.
    /// @dev Must be downcasted to uint16.
    //// @return The transaction fee following the UQ0.40 format.
    function fee() external view returns (uint256);

    /// @dev Return the protocol fee per second earned by the owner.
    /// @dev Must be downcasted to uint16.
    /// @return The protocol fee per second following the UQ0.40 format.
    function protocolFee() external view returns (uint256);

    /// @dev Return the fee stored of the Pool given maturity.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return The fee in asset ERC20 stored in the Pool.
    function feeStored(uint256 maturity) external view returns (uint256);

    /// @dev Return the protocol fee stored.
    /// @return The protocol fee in asset ERC20 stored.
    function protocolFeeStored() external view returns (uint256);

    /// @dev Returns the Constant Product state of a Pool.
    /// @dev The Y state follows the UQ80.32 format.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return x The x state.
    /// @return y The y state.
    /// @return z The z state.
    function constantProduct(uint256 maturity)
        external
        view
        returns (
            uint112 x,
            uint112 y,
            uint112 z
        );

    /// @dev Returns the asset ERC20 and collateral ERC20 balances of a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return The asset ERC20 and collateral ERC20 locked.
    function totalReserves(uint256 maturity) external view returns (Tokens memory);

    /// @dev Returns the total liquidity supply of a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return The total liquidity supply.
    function totalLiquidity(uint256 maturity) external view returns (uint256);

    /// @dev Returns the liquidity balance of a user in a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param owner The address of the user.
    /// @return The liquidity balance.
    function liquidityOf(uint256 maturity, address owner) external view returns (uint256);

    /// @dev Returns the total claims of a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return The total claims.
    function totalClaims(uint256 maturity) external view returns (Claims memory);

    /// @dev Returms the claims of a user in a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param owner The address of the user.
    /// @return The claims balance.
    function claimsOf(uint256 maturity, address owner) external view returns (Claims memory);

    /// @dev Returns the total debt created.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @return The total asset ERC20 debt created.
    function totalDebtCreated(uint256 maturity) external view returns (uint120);

    /// @dev Returns the number of dues owned by owner.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param owner The address of the user.
    function totalDuesOf(uint256 maturity, address owner) external view returns (uint256);

    /// @dev Returns a collateralized debt of a user in a Pool.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param owner The address of the user.
    /// @param id The index of the collateralized debt
    /// @return The collateralized debt balance.
    function dueOf(uint256 maturity, address owner, uint256 id) external view returns (Due memory);

    /* ===== UPDATE ===== */

    /// @dev Add liquidity into a Pool by a liquidity provider.
    /// @dev Liquidity providers can be thought as making both lending and borrowing positions.
    /// @dev Must be called by a contract implementing the ITimeswapMintCallback interface.
    /// @param param The mint parameter found in the MintParam struct.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return liquidityOut The amount of liquidity balance received by liquidityTo.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function mint(MintParam calldata param)
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            Due memory dueOut
        );

    /// @dev Remove liquidity from a Pool by a liquidity provider.
    /// @dev Can only be called after the maturity of the Pool.
    /// @param param The burn parameter found in the BurnParam struct.
    /// @return assetOut The amount of asset ERC20 received.
    /// @return collateralOut The amount of collateral ERC20 received.
    function burn(BurnParam calldata param) 
        external 
        returns (
            uint256 assetOut,
            uint128 collateralOut 
        );

    /// @dev Lend asset ERC20 into the Pool.
    /// @dev Must be called by a contract implementing the ITimeswapLendCallback interface.
    /// @param param The lend parameter found in the LendParam struct.
    /// @return assetIn The amount of asset ERC20 deposited.
    /// @return claimsOut The amount of bond balance and insurance balance received.
    function lend(LendParam calldata param) 
        external 
        returns (
            uint256 assetIn,
            Claims memory claimsOut
        );

    /// @dev Withdraw asset ERC20 and/or collateral ERC20 for lenders.
    /// @dev Can only be called after the maturity of the Pool.
    /// @param param The withdraw parameter found in the WithdrawParam struct.
    /// @return tokensOut The amount of asset ERC20 and collateral ERC20 received.
    function withdraw(WithdrawParam calldata param)
        external 
        returns (
            Tokens memory tokensOut
        );

    /// @dev Borrow asset ERC20 from the Pool.
    /// @dev Must be called by a contract implementing the ITimeswapBorrowCallback interface.
    /// @param param The borrow parameter found in the BorrowParam struct.
    /// @return assetOut The amount of asset ERC20 received.
    /// @return id The array index of the collateralized debt received by dueTo.
    /// @return dueOut The collateralized debt received by dueTo.
    function borrow(BorrowParam calldata param)
        external 
        returns (
            uint256 assetOut,
            uint256 id, 
            Due memory dueOut
        );

    /// @dev Pay asset ERC20 into the Pool to repay debt for borrowers.
    /// @dev If there are asset paid, must be called by a contract implementing the ITimeswapPayCallback interface.
    /// @param param The pay parameter found in the PayParam struct.
    /// @return assetIn The total amount of asset ERC20 paid.
    /// @return collateralOut The total amount of collateral ERC20 received.
    function pay(PayParam calldata param)
        external 
        returns (
            uint128 assetIn, 
            uint128 collateralOut
        );

    /// @dev Collect the stored protocol fee.
    /// @dev Can only be called by the owner.
    /// @param to The receiver of the protocol fee.
    /// @return protocolFeeOut The total amount of protocol fee asset ERC20 received.
    function collectProtocolFee(address to) external returns (uint256 protocolFeeOut);
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 14 of 75 : ITimeswapMintCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

/// @title Callback for ITimeswapPair#mint
/// @notice Any contract that calls ITimeswapPair#mint must implement this interface
interface ITimeswapMintCallback {
    /// @notice Called to `msg.sender` after initiating a mint from ITimeswapPair#mint.
    /// @dev In the implementation you must pay the asset token and collateral token owed for the mint transaction.
    /// The caller of this method must be checked to be a TimeswapPair deployed by the canonical TimeswapFactory.
    /// @param assetIn The amount of asset tokens owed due to the pool for the mint transaction.
    /// @param collateralIn The amount of collateral tokens owed due to the pool for the min transaction.
    /// @param data Any data passed through by the caller via the ITimeswapPair#mint call
    function timeswapMintCallback(
        uint256 assetIn,
        uint112 collateralIn,
        bytes calldata data
    ) external;
}

File 15 of 75 : ITimeswapLendCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

/// @title Callback for ITimeswapPair#lend
/// @notice Any contract that calls ITimeswapPair#lend must implement this interface
interface ITimeswapLendCallback {
    /// @notice Called to `msg.sender` after initiating a lend from ITimeswapPair#lend.
    /// @dev In the implementation you must pay the asset token owed for the lend transaction.
    /// The caller of this method must be checked to be a TimeswapPair deployed by the canonical TimeswapFactory.
    /// @param assetIn The amount of asset tokens owed due to the pool for the lend transaction
    /// @param data Any data passed through by the caller via the ITimeswapPair#lend call
    function timeswapLendCallback(
        uint256 assetIn,
        bytes calldata data
    ) external;
}

File 16 of 75 : ITimeswapBorrowCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

/// @title Callback for ITimeswapPair#borrow
/// @notice Any contract that calls ITimeswapPair#borrow must implement this interface
interface ITimeswapBorrowCallback {
    /// @notice Called to `msg.sender` after initiating a borrow from ITimeswapPair#borrow.
    /// @dev In the implementation you must pay the collateral token owed for the borrow transaction.
    /// The caller of this method must be checked to be a TimeswapPair deployed by the canonical TimeswapFactory.
    /// @param collateralIn The amount of asset tokens owed due to the pool for the borrow transaction
    /// @param data Any data passed through by the caller via the ITimeswapPair#borrow call
    function timeswapBorrowCallback(
        uint112 collateralIn,
        bytes calldata data
    ) external;
}

File 17 of 75 : ITimeswapPayCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

/// @title Callback for ITimeswapPair#pay
/// @notice Any contract that calls ITimeswapPair#pay must implement this interface
interface ITimeswapPayCallback {
    /// @notice Called to `msg.sender` after initiating a pay from ITimeswapPair#pay.
    /// @dev In the implementation you must pay the asset token owed for the pay transaction.
    /// The caller of this method must be checked to be a TimeswapPair deployed by the canonical TimeswapFactory.
    /// @param assetIn The amount of asset tokens owed due to the pool for the pay transaction
    /// @param data Any data passed through by the caller via the ITimeswapPair#pay call
    function timeswapPayCallback(
        uint128 assetIn,
        bytes calldata data
    ) external;
}

File 18 of 75 : Mint.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IMint} from '../interfaces/IMint.sol';
import {MintMath} from './MintMath.sol';
import {Deploy} from './Deploy.sol';
import {MsgValue} from './MsgValue.sol';
import {ETH} from './ETH.sol';

library Mint {
    using MintMath for IPair;
    using Deploy for IConvenience.Native;

    function newLiquidity(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IMint.NewLiquidity calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = _newLiquidity(
            natives,
            IMint._NewLiquidity(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.assetIn,
                params.debtIn,
                params.collateralIn,
                params.deadline
            )
        );
    }

    function newLiquidityETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.NewLiquidityETHAsset calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 assetInETH = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _newLiquidity(
            natives,
            IMint._NewLiquidity(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                assetInETH,
                params.debtIn,
                params.collateralIn,
                params.deadline
            )
        );
    }

    function newLiquidityETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.NewLiquidityETHCollateral calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 collateralIn = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _newLiquidity(
            natives,
            IMint._NewLiquidity(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                address(this),
                params.liquidityTo,
                params.dueTo,
                params.assetIn,
                params.debtIn,
                collateralIn,
                params.deadline
            )
        );
    }

    function liquidityGivenAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IMint.LiquidityGivenAsset calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenAsset(
            natives,
            IMint._LiquidityGivenAsset(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.assetIn,
                params.minLiquidity,
                params.maxDebt,
                params.maxCollateral,
                params.deadline
            )
        );
    }

    function liquidityGivenAssetETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenAssetETHAsset calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 assetInETH = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenAsset(
            natives,
            IMint._LiquidityGivenAsset(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                assetInETH,
                params.minLiquidity,
                params.maxDebt,
                params.maxCollateral,
                params.deadline
            )
        );
    }

    function liquidityGivenAssetETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenAssetETHCollateral calldata params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxCollateral = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenAsset(
            natives,
            IMint._LiquidityGivenAsset(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                address(this),
                params.liquidityTo,
                params.dueTo,
                params.assetIn,
                params.minLiquidity,
                params.maxDebt,
                maxCollateral,
                params.deadline
            )
        );

        if (maxCollateral > dueOut.collateral) {
            uint256 excess = maxCollateral;
            unchecked {
                excess -= dueOut.collateral;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function liquidityGivenDebt(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IMint.LiquidityGivenDebt memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenDebt(
            natives,
            IMint._LiquidityGivenDebt(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.debtIn,
                params.minLiquidity,
                params.maxAsset,
                params.maxCollateral,
                params.deadline
            )
        );
    }

    function liquidityGivenDebtETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenDebtETHAsset memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxAsset = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenDebt(
            natives,
            IMint._LiquidityGivenDebt(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.debtIn,
                params.minLiquidity,
                maxAsset,
                params.maxCollateral,
                params.deadline
            )
        );

        if (maxAsset > assetIn) {
            uint256 excess = maxAsset;
            unchecked {
                excess -= assetIn;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function liquidityGivenDebtETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenDebtETHCollateral memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxCollateral = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenDebt(
            natives,
            IMint._LiquidityGivenDebt(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                address(this),
                params.liquidityTo,
                params.dueTo,
                params.debtIn,
                params.minLiquidity,
                params.maxAsset,
                maxCollateral,
                params.deadline
            )
        );

        if (maxCollateral > dueOut.collateral) {
            uint256 excess = maxCollateral;
            unchecked {
                excess -= dueOut.collateral;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function liquidityGivenCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IMint.LiquidityGivenCollateral memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenCollateral(
            natives,
            IMint._LiquidityGivenCollateral(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.collateralIn,
                params.minLiquidity,
                params.maxAsset,
                params.maxDebt,
                params.deadline
            )
        );
    }

    function liquidityGivenCollateralETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenCollateralETHAsset memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxAsset = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenCollateral(
            natives,
            IMint._LiquidityGivenCollateral(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                msg.sender,
                params.liquidityTo,
                params.dueTo,
                params.collateralIn,
                params.minLiquidity,
                maxAsset,
                params.maxDebt,
                params.deadline
            )
        );

        if (maxAsset > assetIn) {
            uint256 excess = maxAsset;
            unchecked {
                excess -= assetIn;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function liquidityGivenCollateralETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IMint.LiquidityGivenCollateralETHCollateral memory params
    )
        external
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 collateralIn = MsgValue.getUint112();

        (assetIn, liquidityOut, id, dueOut) = _liquidityGivenCollateral(
            natives,
            IMint._LiquidityGivenCollateral(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                address(this),
                params.liquidityTo,
                params.dueTo,
                collateralIn,
                params.minLiquidity,
                params.maxAsset,
                params.maxDebt,
                params.deadline
            )
        );
    }

    function _newLiquidity(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IMint._NewLiquidity memory params
    )
        private
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        require(params.debtIn > params.assetIn, 'E516');
        require(params.maturity > block.timestamp, 'E508');
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        if (address(pair) == address(0)) pair = params.factory.createPair(params.asset, params.collateral);

        require(pair.totalLiquidity(params.maturity) == 0, 'E506');

        (uint112 xIncrease, uint112 yIncrease, uint112 zIncrease) = MintMath.givenNew(
            params.maturity,
            params.assetIn,
            params.debtIn,
            params.collateralIn
        );

        (assetIn, liquidityOut, id, dueOut) = _mint(
            natives,
            IMint._Mint(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetFrom,
                params.collateralFrom,
                params.liquidityTo,
                params.dueTo,
                xIncrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );
    }

    function _liquidityGivenAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IMint._LiquidityGivenAsset memory params
    )
        private
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        if (address(pair) == address(0)) {
            pair = params.factory.createPair(params.asset, params.collateral);
        }
        require(pair.totalLiquidity(params.maturity) != 0, 'E507');

        (uint112 xIncrease, uint112 yIncrease, uint112 zIncrease) = pair.givenAsset(params.maturity, params.assetIn);

        (assetIn, liquidityOut, id, dueOut) = _mint(
            natives,
            IMint._Mint(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetFrom,
                params.collateralFrom,
                params.liquidityTo,
                params.dueTo,
                xIncrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );

        require(liquidityOut >= params.minLiquidity, 'E511');
        require(dueOut.debt <= params.maxDebt, 'E512');
        require(dueOut.collateral <= params.maxCollateral, 'E513');
    }

    function _liquidityGivenDebt(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IMint._LiquidityGivenDebt memory params
    )
        private
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');
        require(pair.totalLiquidity(params.maturity) != 0, 'E507');

        (uint112 xIncrease, uint112 yIncrease, uint112 zIncrease) = pair.givenDebt(params.maturity, params.debtIn);

        (assetIn, liquidityOut, id, dueOut) = _mint(
            natives,
            IMint._Mint(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetFrom,
                params.collateralFrom,
                params.liquidityTo,
                params.dueTo,
                xIncrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );

        require(liquidityOut >= params.minLiquidity, 'E511');
        require(xIncrease <= params.maxAsset, 'E519');
        require(dueOut.collateral <= params.maxCollateral, 'E513');
    }

    function _liquidityGivenCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IMint._LiquidityGivenCollateral memory params
    )
        private
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');
        require(pair.totalLiquidity(params.maturity) != 0, 'E507');

        (uint112 xIncrease, uint112 yIncrease, uint112 zIncrease) = pair.givenCollateral(
            params.maturity,
            params.collateralIn
        );
        (assetIn, liquidityOut, id, dueOut) = _mint(
            natives,
            IMint._Mint(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetFrom,
                params.collateralFrom,
                params.liquidityTo,
                params.dueTo,
                xIncrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );
        require(liquidityOut >= params.minLiquidity, 'E511');
        require(xIncrease <= params.maxAsset, 'E519');
        require(dueOut.debt <= params.maxDebt, 'E512');
    }

    function _mint(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IMint._Mint memory params
    )
        private
        returns (
            uint256 assetIn,
            uint256 liquidityOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        require(params.deadline >= block.timestamp, 'E504');
        require(params.maturity > block.timestamp, 'E508');
        IConvenience.Native storage native = natives[params.asset][params.collateral][params.maturity];
        if (address(native.liquidity) == address(0))
            native.deploy(params.convenience, params.pair, params.asset, params.collateral, params.maturity);
        (assetIn, liquidityOut, id, dueOut) = params.pair.mint(
            IPair.MintParam(
                params.maturity,
                address(this),
                address(this),
                params.xIncrease,
                params.yIncrease,
                params.zIncrease,
                bytes(abi.encode(params.asset, params.collateral, params.assetFrom, params.collateralFrom))
            )
        );
        native.liquidity.mint(params.liquidityTo, liquidityOut);
        native.collateralizedDebt.mint(params.dueTo, id);
    }
}

File 19 of 75 : Burn.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IBurn} from '../interfaces/IBurn.sol';
import {ETH} from './ETH.sol';

library Burn {
    function removeLiquidity(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IBurn.RemoveLiquidity calldata params
    ) external returns (uint256 assetOut, uint128 collateralOut) {
        (assetOut, collateralOut) = _removeLiquidity(
            natives,
            IBurn._RemoveLiquidity(
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetTo,
                params.collateralTo,
                params.liquidityIn
            )
        );
    }

    function removeLiquidityETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IBurn.RemoveLiquidityETHAsset calldata params
    ) external returns (uint256 assetOut, uint128 collateralOut) {
        (assetOut, collateralOut) = _removeLiquidity(
            natives,
            IBurn._RemoveLiquidity(
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.collateralTo,
                params.liquidityIn
            )
        );

        if (assetOut != 0) {
            weth.withdraw(assetOut);
            ETH.transfer(params.assetTo, assetOut);
        }
    }

    function removeLiquidityETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IBurn.RemoveLiquidityETHCollateral calldata params
    ) external returns (uint256 assetOut, uint128 collateralOut) {
        (assetOut, collateralOut) = _removeLiquidity(
            natives,
            IBurn._RemoveLiquidity(
                factory,
                params.asset,
                weth,
                params.maturity,
                params.assetTo,
                address(this),
                params.liquidityIn
            )
        );

        if (collateralOut != 0) {
            weth.withdraw(collateralOut);
            ETH.transfer(params.collateralTo, collateralOut);
        }
    }

    function _removeLiquidity(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IBurn._RemoveLiquidity memory params
    ) private returns (uint256 assetOut, uint128 collateralOut) {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        IConvenience.Native memory native = natives[params.asset][params.collateral][params.maturity];
        require(address(native.liquidity) != address(0), 'E502');

        (assetOut, collateralOut) = pair.burn(
            IPair.BurnParam(params.maturity, params.assetTo, params.collateralTo, params.liquidityIn)
        );

        native.liquidity.burn(msg.sender, params.liquidityIn);
    }
}

File 20 of 75 : Lend.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ILend} from '../interfaces/ILend.sol';
import {LendMath} from './LendMath.sol';
import {Deploy} from './Deploy.sol';
import {MsgValue} from './MsgValue.sol';

library Lend {
    using LendMath for IPair;
    using Deploy for IConvenience.Native;

    function lendGivenBond(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        ILend.LendGivenBond calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenBond(
            natives,
            ILend._LendGivenBond(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.bondOut,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function lendGivenBondETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenBondETHAsset calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        uint112 assetInETH = MsgValue.getUint112();

        (assetIn, claimsOut) = _lendGivenBond(
            natives,
            ILend._LendGivenBond(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.bondTo,
                params.insuranceTo,
                assetInETH,
                params.bondOut,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function lendGivenBondETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenBondETHCollateral calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenBond(
            natives,
            ILend._LendGivenBond(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.bondOut,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function lendGivenInsurance(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        ILend.LendGivenInsurance calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenInsurance(
            natives,
            ILend._LendGivenInsurance(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.insuranceOut,
                params.minBond,
                params.deadline
            )
        );
    }

    function lendGivenInsuranceETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenInsuranceETHAsset calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        uint112 assetInETH = MsgValue.getUint112();

        (assetIn, claimsOut) = _lendGivenInsurance(
            natives,
            ILend._LendGivenInsurance(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.bondTo,
                params.insuranceTo,
                assetInETH,
                params.insuranceOut,
                params.minBond,
                params.deadline
            )
        );
    }

    function lendGivenInsuranceETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenInsuranceETHCollateral calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenInsurance(
            natives,
            ILend._LendGivenInsurance(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.insuranceOut,
                params.minBond,
                params.deadline
            )
        );
    }

    function lendGivenPercent(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        ILend.LendGivenPercent calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenPercent(
            natives,
            ILend._LendGivenPercent(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.percent,
                params.minBond,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function lendGivenPercentETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenPercentETHAsset calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        uint112 assetInETH = MsgValue.getUint112();

        (assetIn, claimsOut) = _lendGivenPercent(
            natives,
            ILend._LendGivenPercent(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.bondTo,
                params.insuranceTo,
                assetInETH,
                params.percent,
                params.minBond,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function lendGivenPercentETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        ILend.LendGivenPercentETHCollateral calldata params
    ) external returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        (assetIn, claimsOut) = _lendGivenPercent(
            natives,
            ILend._LendGivenPercent(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                params.bondTo,
                params.insuranceTo,
                params.assetIn,
                params.percent,
                params.minBond,
                params.minInsurance,
                params.deadline
            )
        );
    }

    function _lendGivenBond(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        ILend._LendGivenBond memory params
    ) private returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        require(params.bondOut > params.assetIn, 'E517');

        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');
        (uint112 xIncrease, uint112 yDecrease, uint112 zDecrease) = pair.givenBond(
            params.maturity,
            params.assetIn,
            params.bondOut
        );

        (assetIn, claimsOut) = _lend(
            natives,
            ILend._Lend(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.bondTo,
                params.insuranceTo,
                xIncrease,
                yDecrease,
                zDecrease,
                params.deadline
            )
        );

        require(uint128(claimsOut.insuranceInterest) + claimsOut.insurancePrincipal >= params.minInsurance, 'E515');
    }

    function _lendGivenInsurance(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        ILend._LendGivenInsurance memory params
    ) private returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        (uint112 xIncrease, uint112 yDecrease, uint112 zDecrease) = pair.givenInsurance(
            params.maturity,
            params.assetIn,
            params.insuranceOut
        );

        (assetIn, claimsOut) = _lend(
            natives,
            ILend._Lend(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.bondTo,
                params.insuranceTo,
                xIncrease,
                yDecrease,
                zDecrease,
                params.deadline
            )
        );

        require(uint128(claimsOut.bondInterest) + claimsOut.bondPrincipal >= params.minBond, 'E514');
    }

    function _lendGivenPercent(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        ILend._LendGivenPercent memory params
    ) private returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        require(params.percent <= 0x100000000, 'E505');

        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        (uint112 xIncrease, uint112 yDecrease, uint112 zDecrease) = pair.givenPercent(
            params.maturity,
            params.assetIn,
            params.percent
        );

        (assetIn, claimsOut) = _lend(
            natives,
            ILend._Lend(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.bondTo,
                params.insuranceTo,
                xIncrease,
                yDecrease,
                zDecrease,
                params.deadline
            )
        );

        require(uint128(claimsOut.bondInterest) + claimsOut.bondPrincipal >= params.minBond, 'E514');
        require(uint128(claimsOut.insuranceInterest) + claimsOut.insurancePrincipal >= params.minInsurance, 'E515');
    }

    function _lend(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        ILend._Lend memory params
    ) private returns (uint256 assetIn, IPair.Claims memory claimsOut) {
        require(params.deadline >= block.timestamp, 'E504');
        require(params.maturity > block.timestamp, 'E508');

        IConvenience.Native storage native = natives[params.asset][params.collateral][params.maturity];
        if (address(native.liquidity) == address(0))
            native.deploy(params.convenience, params.pair, params.asset, params.collateral, params.maturity);

        (assetIn, claimsOut) = params.pair.lend(
            IPair.LendParam(
                params.maturity,
                address(this),
                address(this),
                params.xIncrease,
                params.yDecrease,
                params.zDecrease,
                bytes(abi.encode(params.asset, params.collateral, params.from))
            )
        );

        native.bondInterest.mint(params.bondTo, claimsOut.bondInterest);
        native.bondPrincipal.mint(params.bondTo, claimsOut.bondPrincipal);
        native.insuranceInterest.mint(params.insuranceTo, claimsOut.insuranceInterest);
        native.insurancePrincipal.mint(params.insuranceTo, claimsOut.insurancePrincipal);
    }
}

File 21 of 75 : Withdraw.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IWithdraw} from '../interfaces/IWithdraw.sol';
import {ETH} from './ETH.sol';

library Withdraw {
    function collect(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWithdraw.Collect calldata params
    ) external returns (IPair.Tokens memory tokensOut) {
        tokensOut = _collect(
            natives,
            IWithdraw._Collect(
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                params.assetTo,
                params.collateralTo,
                params.claimsIn
            )
        );
    }

    function collectETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IWithdraw.CollectETHAsset calldata params
    ) external returns (IPair.Tokens memory tokensOut) {
        tokensOut = _collect(
            natives,
            IWithdraw._Collect(
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.collateralTo,
                params.claimsIn
            )
        );

        if (tokensOut.asset != 0) {
            weth.withdraw(tokensOut.asset);
            ETH.transfer(params.assetTo, tokensOut.asset);
        }
    }

    function collectETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IWithdraw.CollectETHCollateral calldata params
    ) external returns (IPair.Tokens memory tokensOut) {
        tokensOut = _collect(
            natives,
            IWithdraw._Collect(
                factory,
                params.asset,
                weth,
                params.maturity,
                params.assetTo,
                address(this),
                params.claimsIn
            )
        );

        if (tokensOut.collateral != 0) {
            weth.withdraw(tokensOut.collateral);
            ETH.transfer(params.collateralTo, tokensOut.collateral);
        }
    }

    function _collect(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IWithdraw._Collect memory params
    ) private returns (IPair.Tokens memory tokensOut) {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        IConvenience.Native memory native = natives[params.asset][params.collateral][params.maturity];
        require(address(native.liquidity) != address(0), 'E502');

        tokensOut = pair.withdraw(
            IPair.WithdrawParam(params.maturity, params.assetTo, params.collateralTo, params.claimsIn)
        );

        if (params.claimsIn.bondInterest != 0) native.bondInterest.burn(msg.sender, params.claimsIn.bondInterest);
        if (params.claimsIn.bondPrincipal != 0) native.bondPrincipal.burn(msg.sender, params.claimsIn.bondPrincipal);
        if (params.claimsIn.insuranceInterest != 0)
            native.insuranceInterest.burn(msg.sender, params.claimsIn.insuranceInterest);
        if (params.claimsIn.insurancePrincipal != 0)
            native.insurancePrincipal.burn(msg.sender, params.claimsIn.insurancePrincipal);
    }
}

File 22 of 75 : Borrow.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IBorrow} from '../interfaces/IBorrow.sol';
import {BorrowMath} from './BorrowMath.sol';
import {Deploy} from './Deploy.sol';
import {MsgValue} from './MsgValue.sol';
import {ETH} from './ETH.sol';

library Borrow {
    using BorrowMath for IPair;
    using Deploy for IConvenience.Native;

    function borrowGivenDebt(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IBorrow.BorrowGivenDebt calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenDebt(
            natives,
            IBorrow._BorrowGivenDebt(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.assetTo,
                params.dueTo,
                params.assetOut,
                params.debtIn,
                params.maxCollateral,
                params.deadline
            )
        );
    }

    function borrowGivenDebtETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenDebtETHAsset calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenDebt(
            natives,
            IBorrow._BorrowGivenDebt(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                msg.sender,
                address(this),
                params.dueTo,
                params.assetOut,
                params.debtIn,
                params.maxCollateral,
                params.deadline
            )
        );

        weth.withdraw(params.assetOut);
        ETH.transfer(params.assetTo, params.assetOut);
    }

    function borrowGivenDebtETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenDebtETHCollateral calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxCollateral = MsgValue.getUint112();

        (assetOut, id, dueOut) = _borrowGivenDebt(
            natives,
            IBorrow._BorrowGivenDebt(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                address(this),
                params.assetTo,
                params.dueTo,
                params.assetOut,
                params.debtIn,
                maxCollateral,
                params.deadline
            )
        );

        if (maxCollateral > dueOut.collateral) {
            uint256 excess = maxCollateral;
            unchecked {
                excess -= dueOut.collateral;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function borrowGivenCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IBorrow.BorrowGivenCollateral calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenCollateral(
            natives,
            IBorrow._BorrowGivenCollateral(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.assetTo,
                params.dueTo,
                params.assetOut,
                params.collateralIn,
                params.maxDebt,
                params.deadline
            )
        );
    }

    function borrowGivenCollateralETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenCollateralETHAsset calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenCollateral(
            natives,
            IBorrow._BorrowGivenCollateral(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                msg.sender,
                address(this),
                params.dueTo,
                params.assetOut,
                params.collateralIn,
                params.maxDebt,
                params.deadline
            )
        );

        weth.withdraw(assetOut);
        ETH.transfer(payable(params.assetTo), assetOut);
    }

    function borrowGivenCollateralETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenCollateralETHCollateral calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 collateralIn = MsgValue.getUint112();

        (assetOut, id, dueOut) = _borrowGivenCollateral(
            natives,
            IBorrow._BorrowGivenCollateral(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                address(this),
                params.assetTo,
                params.dueTo,
                params.assetOut,
                collateralIn,
                params.maxDebt,
                params.deadline
            )
        );

        if (collateralIn > dueOut.collateral) {
            uint256 excess = collateralIn;
            unchecked {
                excess -= dueOut.collateral;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function borrowGivenPercent(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IBorrow.BorrowGivenPercent calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenPercent(
            natives,
            IBorrow._BorrowGivenPercent(
                convenience,
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.assetTo,
                params.dueTo,
                params.assetOut,
                params.percent,
                params.maxDebt,
                params.maxCollateral,
                params.deadline
            )
        );
    }

    function borrowGivenPercentETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenPercentETHAsset calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        (assetOut, id, dueOut) = _borrowGivenPercent(
            natives,
            IBorrow._BorrowGivenPercent(
                convenience,
                factory,
                weth,
                params.collateral,
                params.maturity,
                msg.sender,
                address(this),
                params.dueTo,
                params.assetOut,
                params.percent,
                params.maxDebt,
                params.maxCollateral,
                params.deadline
            )
        );

        weth.withdraw(assetOut);
        ETH.transfer(params.assetTo, assetOut);
    }

    function borrowGivenPercentETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IWETH weth,
        IBorrow.BorrowGivenPercentETHCollateral calldata params
    )
        external
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        uint112 maxCollateral = MsgValue.getUint112();

        (assetOut, id, dueOut) = _borrowGivenPercent(
            natives,
            IBorrow._BorrowGivenPercent(
                convenience,
                factory,
                params.asset,
                weth,
                params.maturity,
                address(this),
                params.assetTo,
                params.dueTo,
                params.assetOut,
                params.percent,
                params.maxDebt,
                maxCollateral,
                params.deadline
            )
        );

        if (maxCollateral > dueOut.collateral) {
            uint256 excess = maxCollateral;
            unchecked {
                excess -= dueOut.collateral;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function _borrowGivenDebt(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IBorrow._BorrowGivenDebt memory params
    )
        private
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        require(params.debtIn > params.assetOut, 'E518');

        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        (uint112 xDecrease, uint112 yIncrease, uint112 zIncrease) = pair.givenDebt(
            params.maturity,
            params.assetOut,
            params.debtIn
        );

        (assetOut, id, dueOut) = _borrow(
            natives,
            IBorrow._Borrow(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.assetTo,
                params.dueTo,
                xDecrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );

        require(dueOut.collateral <= params.maxCollateral, 'E513');
    }

    function _borrowGivenCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IBorrow._BorrowGivenCollateral memory params
    )
        private
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        (uint112 xDecrease, uint112 yIncrease, uint112 zIncrease) = pair.givenCollateral(
            params.maturity,
            params.assetOut,
            params.collateralIn
        );

        (assetOut, id, dueOut) = _borrow(
            natives,
            IBorrow._Borrow(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.assetTo,
                params.dueTo,
                xDecrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );

        require(dueOut.debt <= params.maxDebt, 'E512');
    }

    function _borrowGivenPercent(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IBorrow._BorrowGivenPercent memory params
    )
        private
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        require(params.percent <= 0x100000000, 'E505');

        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        (uint112 xDecrease, uint112 yIncrease, uint112 zIncrease) = pair.givenPercent(
            params.maturity,
            params.assetOut,
            params.percent
        );

        (assetOut, id, dueOut) = _borrow(
            natives,
            IBorrow._Borrow(
                params.convenience,
                pair,
                params.asset,
                params.collateral,
                params.maturity,
                params.from,
                params.assetTo,
                params.dueTo,
                xDecrease,
                yIncrease,
                zIncrease,
                params.deadline
            )
        );

        require(dueOut.debt <= params.maxDebt, 'E512');
        require(dueOut.collateral <= params.maxCollateral, 'E513');
    }

    function _borrow(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IBorrow._Borrow memory params
    )
        private
        returns (
            uint256 assetOut,
            uint256 id,
            IPair.Due memory dueOut
        )
    {
        require(params.deadline >= block.timestamp, 'E504');
        require(params.maturity > block.timestamp, 'E508');

        IConvenience.Native storage native = natives[params.asset][params.collateral][params.maturity];
        if (address(native.liquidity) == address(0))
            native.deploy(params.convenience, params.pair, params.asset, params.collateral, params.maturity);

        (assetOut, id, dueOut) = params.pair.borrow(
            IPair.BorrowParam(
                params.maturity,
                params.assetTo,
                address(this),
                params.xDecrease,
                params.yIncrease,
                params.zIncrease,
                bytes(abi.encode(params.asset, params.collateral, params.from))
            )
        );

        native.collateralizedDebt.mint(params.dueTo, id);
    }
}

File 23 of 75 : Pay.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IWETH} from '../interfaces/IWETH.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IPay} from '../interfaces/IPay.sol';
import {IDue} from '../interfaces/IDue.sol';
import {PayMath} from './PayMath.sol';
import {MsgValue} from './MsgValue.sol';
import {ETH} from './ETH.sol';

library Pay {
    using PayMath for IPair;

    function pay(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IPay.Repay memory params
    ) external returns (uint128 assetIn, uint128 collateralOut) {
        (assetIn, collateralOut) = _pay(
            natives,
            IPay._Repay(
                factory,
                params.asset,
                params.collateral,
                params.maturity,
                msg.sender,
                params.collateralTo,
                params.ids,
                params.maxAssetsIn,
                params.deadline
            )
        );
    }

    function payETHAsset(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IPay.RepayETHAsset memory params
    ) external returns (uint128 assetIn, uint128 collateralOut) {
        uint128 maxAssetIn = MsgValue.getUint112();

        (assetIn, collateralOut) = _pay(
            natives,
            IPay._Repay(
                factory,
                weth,
                params.collateral,
                params.maturity,
                address(this),
                params.collateralTo,
                params.ids,
                params.maxAssetsIn,
                params.deadline
            )
        );

        if (maxAssetIn > assetIn) {
            uint256 excess = maxAssetIn;
            unchecked {
                excess -= assetIn;
            }
            ETH.transfer(payable(msg.sender), excess);
        }
    }

    function payETHCollateral(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IFactory factory,
        IWETH weth,
        IPay.RepayETHCollateral memory params
    ) external returns (uint128 assetIn, uint128 collateralOut) {
        (assetIn, collateralOut) = _pay(
            natives,
            IPay._Repay(
                factory,
                params.asset,
                weth,
                params.maturity,
                msg.sender,
                address(this),
                params.ids,
                params.maxAssetsIn,
                params.deadline
            )
        );

        if (collateralOut != 0) {
            weth.withdraw(collateralOut);
            ETH.transfer(params.collateralTo, collateralOut);
        }
    }

    function _pay(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IPay._Repay memory params
    ) private returns (uint128 assetIn, uint128 collateralOut) {
        require(params.deadline >= block.timestamp, 'E504');
        require(params.maturity > block.timestamp, 'E508');
        require(params.ids.length == params.maxAssetsIn.length, '520');

        IPair pair = params.factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        IDue collateralizedDebt = natives[params.asset][params.collateral][params.maturity].collateralizedDebt;
        require(address(collateralizedDebt) != address(0), 'E502');

        (uint112[] memory assetsIn, uint112[] memory collateralsOut) = pair.givenMaxAssetsIn(
            params.maturity,
            collateralizedDebt,
            params.ids,
            params.maxAssetsIn
        );

        (assetIn, collateralOut) = pair.pay(
            IPair.PayParam(
                params.maturity,
                params.collateralTo,
                address(this),
                params.ids,
                assetsIn,
                collateralsOut,
                bytes(abi.encode(params.asset, params.collateral, params.from, params.maturity))
            )
        );
    }
}

File 24 of 75 : DeployNative.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IFactory} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IFactory.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {Deploy} from './Deploy.sol';
import {IDeployNatives} from '../interfaces/IDeployNatives.sol';

library DeployNative {
    using Deploy for IConvenience.Native;

    function deploy(
        mapping(IERC20 => mapping(IERC20 => mapping(uint256 => IConvenience.Native))) storage natives,
        IConvenience convenience,
        IFactory factory,
        IDeployNatives.DeployNatives memory params
    ) internal {
        require(params.deadline >= block.timestamp, 'E504');

        IPair pair = factory.getPair(params.asset, params.collateral);
        require(address(pair) != address(0), 'E501');

        IConvenience.Native storage native = natives[params.asset][params.collateral][params.maturity];
        require(address(native.liquidity) == address(0), 'E503');

        native.deploy(convenience, pair, params.asset, params.collateral, params.maturity);
    }
}

File 25 of 75 : SafeTransfer.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';

library SafeTransfer {
    using SafeERC20 for IERC20;

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

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

File 26 of 75 : ILiquidity.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20Permit} from './IERC20Permit.sol';
import {IConvenience} from './IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

/// @author Ricsson W. Ngo
interface ILiquidity is IERC20Permit {
    // VIEW

    function convenience() external returns (IConvenience);

    function pair() external returns (IPair);

    function maturity() external returns (uint256);

    // UPDATE

    function mint(address to, uint256 amount) external;

    function burn(address from, uint256 amount) external;
}

File 27 of 75 : IClaim.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20Permit} from './IERC20Permit.sol';
import {IConvenience} from './IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

/// @author Ricsson W. Ngo
interface IClaim is IERC20Permit {
    // VIEW

    function convenience() external returns (IConvenience);

    function pair() external returns (IPair);

    function maturity() external returns (uint256);

    // UPDATE

    function mint(address to, uint128 amount) external;

    function burn(address from, uint128 amount) external;
}

File 28 of 75 : IDeployNatives.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IDeployNatives {
    struct DeployNatives {
        IERC20 asset;
        IERC20 collateral;
        uint256 maturity;
        uint256 deadline;
    }
}

File 29 of 75 : IDeployPair.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IDeployPair {
    struct DeployPair {
        IERC20 asset;
        IERC20 collateral;
    }
}

File 30 of 75 : IERC20Permit.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20Metadata} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';

interface IERC20Permit is IERC20Metadata {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

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

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

File 31 of 75 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 32 of 75 : IERC721Permit.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC721Extended} from './IERC721Extended.sol';

interface IERC721Permit is IERC721Extended {
    // /// @notice The permit typehash used in the permit signature
    // /// @return The typehash for the permit
    // function PERMIT_TYPEHASH() external pure returns (bytes32);

    /// @notice The domain separator used in the permit signature
    /// @return The domain seperator used in encoding of permit signature
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /// @notice Approve of a specific token ID for spending by spender via signature
    /// @param spender The account that is being approved
    /// @param tokenId The ID of the token that is being approved for spending
    /// @param deadline The deadline timestamp by which the call must be mined for the approve to work
    /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
    /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
    /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
    function permit(
        address spender,
        uint256 tokenId,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

File 33 of 75 : IERC721Extended.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC721Metadata} from '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
import {IERC721Enumerable} from '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';

interface IERC721Extended is IERC721Metadata, IERC721Enumerable {
    function assetDecimals() external view returns (uint8);

    function collateralDecimals() external view returns (uint8);
}

File 34 of 75 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 35 of 75 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 36 of 75 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 37 of 75 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 38 of 75 : MintMath.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {Math} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/Math.sol';
import {ConstantProduct} from './ConstantProduct.sol';
import {SafeCast} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/SafeCast.sol';

library MintMath {
    using Math for uint256;
    using ConstantProduct for IPair;
    using SafeCast for uint256;

    function givenNew(
        uint256 maturity,
        uint112 assetIn,
        uint112 debtIn,
        uint112 collateralIn
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        xIncrease = assetIn;
        uint256 duration = maturity;
        duration -= block.timestamp;
        uint256 _yIncrease = debtIn;
        _yIncrease -= assetIn;
        _yIncrease <<= 32;
        _yIncrease /= duration;
        yIncrease = _yIncrease.toUint112();
        uint256 _zIncrease = collateralIn;
        _zIncrease <<= 25;
        uint256 denominator = duration;
        denominator += 0x2000000;
        _zIncrease /= denominator;
        zIncrease = _zIncrease.toUint112();
    }

    function givenAsset(
        IPair pair,
        uint256 maturity,
        uint112 assetIn
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        uint256 _xIncrease = assetIn;
        _xIncrease *= cp.x;
        uint256 denominator = cp.x;
        denominator += pair.feeStored(maturity);
        _xIncrease /= denominator;
        xIncrease = _xIncrease.toUint112();

        uint256 _yIncrease = cp.y;
        _yIncrease *= xIncrease;
        _yIncrease /= cp.x;
        yIncrease = _yIncrease.toUint112();

        uint256 _zIncrease = cp.z;
        _zIncrease *= xIncrease;
        _zIncrease /= cp.x;
        zIncrease = _zIncrease.toUint112();
    }

    function givenDebt(
        IPair pair,
        uint256 maturity,
        uint112 debtIn
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        uint256 _yIncrease = debtIn;
        _yIncrease *= cp.y;
        _yIncrease <<= 32;
        uint256 denominator = maturity;
        denominator -= block.timestamp;
        denominator *= cp.y;
        uint256 addend = cp.x;
        addend <<= 32;
        denominator += addend;
        _yIncrease /= denominator;
        yIncrease = _yIncrease.toUint112();

        uint256 _xIncrease = cp.x;
        _xIncrease *= _yIncrease;
        _xIncrease = _xIncrease.divUp(cp.y);
        xIncrease = _xIncrease.toUint112();

        uint256 _zIncrease = cp.z;
        _zIncrease *= _yIncrease;
        _zIncrease /= cp.y;
        zIncrease = _zIncrease.toUint112();
    }

    function givenCollateral(
        IPair pair,
        uint256 maturity,
        uint112 collateralIn
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        uint256 _zIncrease = collateralIn;
        _zIncrease <<= 25;
        uint256 denominator = maturity;
        denominator -= block.timestamp;
        denominator += 0x2000000;
        _zIncrease /= denominator;
        zIncrease = _zIncrease.toUint112();

        uint256 _xIncrease = cp.x;
        _xIncrease *= _zIncrease;
        _xIncrease = _xIncrease.divUp(cp.z);
        xIncrease = _xIncrease.toUint112();

        uint256 _yIncrease = cp.y;
        _yIncrease *= _zIncrease;
        _yIncrease /= cp.z;
        yIncrease = _yIncrease.toUint112();
    }
}

File 39 of 75 : Deploy.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
import {DeployLiquidity} from './DeployLiquidity.sol';
import {DeployBonds} from './DeployBonds.sol';
import {DeployInsurances} from './DeployInsurances.sol';
import {DeployCollateralizedDebt} from './DeployCollateralizedDebt.sol';

library Deploy {
    using Strings for uint256;
    using DeployLiquidity for IConvenience.Native;
    using DeployBonds for IConvenience.Native;
    using DeployInsurances for IConvenience.Native;
    using DeployCollateralizedDebt for IConvenience.Native;

    /// @dev Emits when the new natives are deployed.
    /// @param asset The address of the asset ERC20 contract.
    /// @param collateral The address of the collateral ERC20 contract.
    /// @param maturity The unix timestamp maturity of the Pool.
    /// @param native The native ERC20 and ERC721 contracts deployed.
    event DeployNatives(IERC20 indexed asset, IERC20 indexed collateral, uint256 maturity, IConvenience.Native native);

    function deploy(
        IConvenience.Native storage native,
        IConvenience convenience,
        IPair pair,
        IERC20 asset,
        IERC20 collateral,
        uint256 maturity
    ) internal {
        bytes32 salt = keccak256(abi.encode(asset, collateral, maturity.toString()));
        native.deployLiquidity(salt, convenience, pair, maturity);
        native.deployBonds(salt, convenience, pair, maturity);
        native.deployInsurances(salt, convenience, pair, maturity);
        native.deployCollateralizedDebt(salt, convenience, pair, maturity);
        emit DeployNatives(asset, collateral, maturity, native);
    }
}

File 40 of 75 : MsgValue.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {ETH} from './ETH.sol';
import {SafeCast} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/SafeCast.sol';

library MsgValue {
    using SafeCast for uint256;

    function getUint112() internal returns (uint112 value) {
        value = msg.value.truncateUint112();
        unchecked {
            if (msg.value > value) ETH.transfer(payable(msg.sender), msg.value - value);
        }
    }
}

File 41 of 75 : ETH.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

library ETH {
    function transfer(address payable to, uint256 amount) internal {
        (bool success, ) = to.call{value: amount}('');
        require(success, 'E521');
    }
}

File 42 of 75 : Math.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

library Math {
    function divUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x / y;
        if (x % y != 0) z++;
    }

    function shiftRightUp(uint256 x, uint8 y) internal pure returns (uint256 z) {
        z = x >> y;
        if (x != z << y) z++;
    }

}

File 43 of 75 : ConstantProduct.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';

library ConstantProduct {
    struct CP {
        uint112 x;
        uint112 y;
        uint112 z;
    }

    function get(IPair pair, uint256 maturity) internal view returns (CP memory cp) {
        (uint112 x, uint112 y, uint112 z) = pair.constantProduct(maturity);
        cp = CP(x, y, z);
    }
}

File 44 of 75 : SafeCast.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.4;

library SafeCast {    
    function toUint112(uint256 x) internal pure returns (uint112 y) {
        require(x <= type(uint112).max);
        y = uint112(x);
    }

    function toUint128(uint256 x) internal pure returns (uint128 y) {
        require(x <= type(uint128).max);
        y = uint128(x);
    }

    function truncateUint112(uint256 x) internal pure returns (uint112 y) {
        if (x > type(uint112).max) return y = type(uint112).max;
        y = uint112(x);
    }
}

File 45 of 75 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 46 of 75 : DeployLiquidity.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {Liquidity} from '../Liquidity.sol';

library DeployLiquidity {
    function deployLiquidity(
        IConvenience.Native storage native,
        bytes32 salt,
        IConvenience convenience,
        IPair pair,
        uint256 maturity
    ) external {
        native.liquidity = new Liquidity{salt: salt}(convenience, pair, maturity);
    }
}

File 47 of 75 : DeployBonds.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {BondInterest} from '../BondInterest.sol';
import {BondPrincipal} from '../BondPrincipal.sol';

library DeployBonds {
    function deployBonds(
        IConvenience.Native storage native,
        bytes32 salt,
        IConvenience convenience,
        IPair pair,
        uint256 maturity
    ) external {
        native.bondInterest = new BondInterest{salt: salt}(convenience, pair, maturity);
        native.bondPrincipal = new BondPrincipal{salt: salt}(convenience, pair, maturity);
    }
}

File 48 of 75 : DeployInsurances.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {InsuranceInterest} from '../InsuranceInterest.sol';
import {InsurancePrincipal} from '../InsurancePrincipal.sol';

library DeployInsurances {
    function deployInsurances(
        IConvenience.Native storage native,
        bytes32 salt,
        IConvenience convenience,
        IPair pair,
        uint256 maturity
    ) external {
        native.insuranceInterest = new InsuranceInterest{salt: salt}(convenience, pair, maturity);
        native.insurancePrincipal = new InsurancePrincipal{salt: salt}(convenience, pair, maturity);
    }
}

File 49 of 75 : DeployCollateralizedDebt.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IConvenience} from '../interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {CollateralizedDebt} from '../CollateralizedDebt.sol';

library DeployCollateralizedDebt {
    function deployCollateralizedDebt(
        IConvenience.Native storage native,
        bytes32 salt,
        IConvenience convenience,
        IPair pair,
        uint256 maturity
    ) external {
        native.collateralizedDebt = new CollateralizedDebt{salt: salt}(convenience, pair, maturity);
    }
}

File 50 of 75 : Liquidity.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {ILiquidity} from './interfaces/ILiquidity.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ERC20Permit} from './base/ERC20Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';

contract Liquidity is ILiquidity, ERC20Permit {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    uint8 public constant override decimals = 18;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked('Timeswap Liquidity - ', assetName, ' - ', collateralName, ' - ', maturity.toString())
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-LIQ-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function totalSupply() external view override returns (uint256) {
        return pair.liquidityOf(maturity, address(convenience));
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC20Permit('Timeswap Liquidity') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    modifier onlyConvenience() {
        require(msg.sender == address(convenience), 'E403');
        _;
    }

    function mint(address to, uint256 amount) external override onlyConvenience {
        _mint(to, amount);
    }

    function burn(address from, uint256 amount) external override onlyConvenience {
        _burn(from, amount);
    }
}

File 51 of 75 : ERC20Permit.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20Permit} from '../interfaces/IERC20Permit.sol';
import {ERC20} from './ERC20.sol';
import {EIP712} from '@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol';
import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import {Counters} from '@openzeppelin/contracts/utils/Counters.sol';

abstract contract ERC20Permit is IERC20Permit, ERC20, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private immutable _PERMIT_TYPEHASH =
        keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, '1') {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, 'E602');

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, 'E603');

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

File 52 of 75 : SafeMetadata.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IERC20Metadata} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';

library SafeMetadata {
    function isSafeString(string memory str) public pure returns (bool) {
        bytes memory b = bytes(str);

        for (uint256 i; i < b.length; i++) {
            bytes1 char = b[i];
            if (
                !(char >= 0x30 && char <= 0x39) && //9-0
                !(char >= 0x41 && char <= 0x5A) && //A-Z
                !(char >= 0x61 && char <= 0x7A) && //a-z
                !(char == 0x2E) &&
                !(char == 0x20) // ." "
            ) return false;
        }
        return true;
    }

    function safeName(IERC20 token) internal view returns (string memory) {
        (bool success, bytes memory data) = address(token).staticcall(
            abi.encodeWithSelector(IERC20Metadata.name.selector)
        );
        return success ? returnDataToString(data) : 'Token';
    }

    function safeSymbol(IERC20 token) internal view returns (string memory) {
        (bool _success, bytes memory data) = address(token).staticcall(
            abi.encodeWithSelector(IERC20Metadata.symbol.selector)
        );
        string memory tokenSymbol = _success ? returnDataToString(data) : 'TKN';

        bool success = isSafeString(tokenSymbol);
        return success ? tokenSymbol : 'TKN';
    }

    function safeDecimals(IERC20 token) internal view returns (uint8) {
        (bool success, bytes memory data) = address(token).staticcall(
            abi.encodeWithSelector(IERC20Metadata.decimals.selector)
        );
        return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
    }

    function returnDataToString(bytes memory data) private pure returns (string memory) {
        if (data.length >= 64) {
            return abi.decode(data, (string));
        } else if (data.length == 32) {
            uint8 i;
            while (i < 32 && data[i] != 0) {
                unchecked {
                    ++i;
                }
            }
            bytes memory bytesArray = new bytes(i);
            uint256 length = bytesArray.length;
            for (i = 0; i < length; ) {
                bytesArray[i] = data[i];
                unchecked {
                    ++i;
                }
            }
            return string(bytesArray);
        } else {
            return '???';
        }
    }
}

File 53 of 75 : ERC20.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC20Metadata} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';

abstract contract ERC20 is IERC20Metadata {
    mapping(address => uint256) public override balanceOf;
    mapping(address => mapping(address => uint256)) public override allowance;

    function transfer(address to, uint256 amount) external override returns (bool) {
        _transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external override returns (bool) {
        _approve(from, msg.sender, allowance[from][msg.sender] - amount);
        _transfer(from, to, amount);

        return true;
    }

    function approve(address spender, uint256 amount) external override returns (bool) {
        _approve(msg.sender, spender, amount);

        return true;
    }

    function increaseAllowance(address spender, uint256 amount) external returns (bool) {
        _approve(msg.sender, spender, allowance[msg.sender][spender] + amount);

        return true;
    }

    function decreaseAllowance(address spender, uint256 amount) external returns (bool) {
        _approve(msg.sender, spender, allowance[msg.sender][spender] - amount);

        return true;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) private {
        require(to != address(0), 'E601');

        balanceOf[from] -= amount;
        balanceOf[to] += amount;

        emit Transfer(from, to, amount);
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal {
        allowance[owner][spender] = amount;

        emit Approval(owner, spender, amount);
    }

    function _mint(address to, uint256 amount) internal {
        require(to != address(0), 'E601');

        balanceOf[to] += amount;

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal {
        balanceOf[from] -= amount;

        emit Transfer(from, address(0), amount);
    }
}

File 54 of 75 : draft-EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}

File 55 of 75 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 56 of 75 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 57 of 75 : BondInterest.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IClaim} from './interfaces/IClaim.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ERC20Permit} from './base/ERC20Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';

contract BondInterest is IClaim, ERC20Permit {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked(
                    'Timeswap Bond Interest - ',
                    assetName,
                    ' - ',
                    collateralName,
                    ' - ',
                    maturity.toString()
                )
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-BND-INT-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function decimals() external view override returns (uint8) {
        return pair.asset().safeDecimals();
    }

    function totalSupply() external view override returns (uint256) {
        return pair.claimsOf(maturity, address(convenience)).bondInterest;
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC20Permit('Timeswap Bond Interest') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    modifier onlyConvenience() {
        require(msg.sender == address(convenience), 'E403');
        _;
    }

    function mint(address to, uint128 amount) external override onlyConvenience {
        _mint(to, amount);
    }

    function burn(address from, uint128 amount) external override onlyConvenience {
        _burn(from, amount);
    }
}

File 58 of 75 : BondPrincipal.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IClaim} from './interfaces/IClaim.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ERC20Permit} from './base/ERC20Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';

contract BondPrincipal is IClaim, ERC20Permit {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked(
                    'Timeswap Bond Principal - ',
                    assetName,
                    ' - ',
                    collateralName,
                    ' - ',
                    maturity.toString()
                )
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-BND-PRI-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function decimals() external view override returns (uint8) {
        return pair.asset().safeDecimals();
    }

    function totalSupply() external view override returns (uint256) {
        return pair.claimsOf(maturity, address(convenience)).bondPrincipal;
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC20Permit('Timeswap Bond Principal') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    modifier onlyConvenience() {
        require(msg.sender == address(convenience), 'E403');
        _;
    }

    function mint(address to, uint128 amount) external override onlyConvenience {
        _mint(to, amount);
    }

    function burn(address from, uint128 amount) external override onlyConvenience {
        _burn(from, amount);
    }
}

File 59 of 75 : InsuranceInterest.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IClaim} from './interfaces/IClaim.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ERC20Permit} from './base/ERC20Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';

contract InsuranceInterest is IClaim, ERC20Permit {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked(
                    'Timeswap Insurance Interest- ',
                    assetName,
                    ' - ',
                    collateralName,
                    ' - ',
                    maturity.toString()
                )
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-INS-INT-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function decimals() external view override returns (uint8) {
        return pair.collateral().safeDecimals();
    }

    function totalSupply() external view override returns (uint256) {
        return pair.claimsOf(maturity, address(convenience)).insuranceInterest;
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC20Permit('Timeswap Insurance Interest') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    modifier onlyConvenience() {
        require(msg.sender == address(convenience), 'E403');
        _;
    }

    function mint(address to, uint128 amount) external override onlyConvenience {
        _mint(to, amount);
    }

    function burn(address from, uint128 amount) external override onlyConvenience {
        _burn(from, amount);
    }
}

File 60 of 75 : InsurancePrincipal.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IClaim} from './interfaces/IClaim.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {ERC20Permit} from './base/ERC20Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';

contract InsurancePrincipal is IClaim, ERC20Permit {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked(
                    'Timeswap Insurance Principal- ',
                    assetName,
                    ' - ',
                    collateralName,
                    ' - ',
                    maturity.toString()
                )
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-INS-PRI-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function decimals() external view override returns (uint8) {
        return pair.collateral().safeDecimals();
    }

    function totalSupply() external view override returns (uint256) {
        return pair.claimsOf(maturity, address(convenience)).insurancePrincipal;
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC20Permit('Timeswap Insurance Principal') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    modifier onlyConvenience() {
        require(msg.sender == address(convenience), 'E403');
        _;
    }

    function mint(address to, uint128 amount) external override onlyConvenience {
        _mint(to, amount);
    }

    function burn(address from, uint128 amount) external override onlyConvenience {
        _burn(from, amount);
    }
}

File 61 of 75 : CollateralizedDebt.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IDue} from './interfaces/IDue.sol';
import {IConvenience} from './interfaces/IConvenience.sol';
import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {ERC721Permit} from './base/ERC721Permit.sol';
import {SafeMetadata} from './libraries/SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
import {NFTTokenURIScaffold} from './libraries/NFTTokenURIScaffold.sol';

contract CollateralizedDebt is IDue, ERC721Permit {
    using Strings for uint256;
    using SafeMetadata for IERC20;

    IConvenience public immutable override convenience;
    IPair public immutable override pair;
    uint256 public immutable override maturity;

    function name() external view override returns (string memory) {
        string memory assetName = pair.asset().safeName();
        string memory collateralName = pair.collateral().safeName();
        return
            string(
                abi.encodePacked(
                    'Timeswap Collateralized Debt - ',
                    assetName,
                    ' - ',
                    collateralName,
                    ' - ',
                    maturity.toString()
                )
            );
    }

    function symbol() external view override returns (string memory) {
        string memory assetSymbol = pair.asset().safeSymbol();
        string memory collateralSymbol = pair.collateral().safeSymbol();
        return string(abi.encodePacked('TS-CDT-', assetSymbol, '-', collateralSymbol, '-', maturity.toString()));
    }

    function tokenURI(uint256 id) external view override returns (string memory) {
        require(_owners[id] != address(0), 'E404');
        return NFTTokenURIScaffold.tokenURI(id, pair, pair.dueOf(maturity, address(convenience), id), maturity);
    }

    function assetDecimals() external view override returns (uint8) {
        return pair.asset().safeDecimals();
    }

    function collateralDecimals() external view override returns (uint8) {
        return pair.collateral().safeDecimals();
    }

    function totalSupply() external view override returns (uint256) {
        return pair.totalDuesOf(maturity, address(convenience));
    }

    function tokenByIndex(uint256 id) external view override returns (uint256) {
        require(id < pair.totalDuesOf(maturity, address(convenience)), 'E614');
        return id;
    }

    function dueOf(uint256 id) external view override returns (IPair.Due memory) {
        return pair.dueOf(maturity, address(convenience), id);
    }

    constructor(
        IConvenience _convenience,
        IPair _pair,
        uint256 _maturity
    ) ERC721Permit('Timeswap Collateralized Debt') {
        convenience = _convenience;
        pair = _pair;
        maturity = _maturity;
    }

    function mint(address to, uint256 id) external override {
        require(msg.sender == address(convenience), 'E403');
        _safeMint(to, id);
    }
}

File 62 of 75 : ERC721Permit.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {EIP712} from '@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol';
import {IERC721Permit} from '../interfaces/IERC721Permit.sol';
import {ERC721} from './ERC721.sol';
import {IERC721Permit} from '../interfaces/IERC721Permit.sol';
import {Counters} from '@openzeppelin/contracts/utils/Counters.sol';
import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';

abstract contract ERC721Permit is IERC721Permit, ERC721, EIP712 {
    using Counters for Counters.Counter;

    mapping(uint256 => Counters.Counter) private _nonces;

    bytes32 public immutable _PERMIT_TYPEHASH =
        keccak256('Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)');

    constructor(string memory name) EIP712(name, '1') {}

    /// @inheritdoc IERC721Permit
    function permit(
        address spender,
        uint256 tokenId,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external override {
        address owner = _owners[tokenId];

        require(block.timestamp <= deadline, 'E602');

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, spender, tokenId, _useNonce(tokenId), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer != address(0), 'E606');
        require(signer == owner, 'E603');
        require(spender != owner, 'E605');

        _approve(spender, tokenId);
    }

    function nonces(uint256 tokenId) public view virtual returns (uint256) {
        return _nonces[tokenId].current();
    }

    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    function _useNonce(uint256 tokenId) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[tokenId];
        current = nonce.current();
        nonce.increment();
    }
}

File 63 of 75 : NFTTokenURIScaffold.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeMetadata} from './SafeMetadata.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
import {DateTime} from './DateTime.sol';
import './Base64.sol';
import {NFTSVG} from './NFTSVG.sol';

library NFTTokenURIScaffold {
    using SafeMetadata for IERC20;
    using Strings for uint256;

    function tokenURI(
        uint256 id,
        IPair pair,
        IPair.Due memory due,
        uint256 maturity
    ) public view returns (string memory) {
        string memory uri = constructTokenSVG(
            address(pair.asset()),
            address(pair.collateral()),
            id.toString(),
            weiToPrecisionString(due.debt, pair.asset().safeDecimals()),
            weiToPrecisionString(due.collateral, pair.collateral().safeDecimals()),
            getReadableDateString(maturity),
            maturity
        );

        string memory description = string(
            abi.encodePacked(
                'This collateralized debt position represents a debt of ',
                weiToPrecisionString(due.debt, pair.asset().safeDecimals()),
                ' ',
                pair.asset().safeSymbol(),
                ' borrowed against a collateral of ',
                weiToPrecisionString(due.collateral, pair.collateral().safeDecimals()),
                ' ',
                pair.collateral().safeSymbol(),
                '. This position will expire on ',
                maturity.toString(),
                ' unix epoch time.\\nThe owner of this NFT has the option to pay the debt before maturity time to claim the locked collateral. In case the owner choose to default on the debt payment, the collateral will be forfeited'
            )
        );
        description = string(
            abi.encodePacked(
                description,
                '\\n\\nAsset Address: ',
                addressToString(address(pair.asset())),
                '\\n\\nCollateral Address: ',
                addressToString(address(pair.collateral())),
                '\\n\\nTotal Debt: ',
                weiToPrecisionLongString(due.debt, pair.asset().safeDecimals()),
                ' ',
                IERC20(pair.asset()).safeSymbol(),
                '\\n\\nCollateral Locked: ',
                weiToPrecisionLongString(due.collateral, pair.collateral().safeDecimals()),
                ' ',
                IERC20(pair.collateral()).safeSymbol(),
                '\\n\\nWarning: Even if a debt has been repaid, the repayment will not be reflected in the NFT, hence please cross check on chain before buying an NFT if you are buying it to repay the debt and claim the collateral'
            )
        );

        string memory name = 'Timeswap Collateralized Debt';

        return (constructTokenURI(name, description, uri));
    }

    function constructTokenURI(
        string memory name,
        string memory description,
        string memory imageSVG
    ) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    'data:application/json;base64,',
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{"name":"',
                                name,
                                '", "description":"',
                                description,
                                '", "image": "',
                                'data:image/svg+xml;base64,',
                                Base64.encode(bytes(imageSVG)),
                                '"}'
                            )
                        )
                    )
                )
            );
    }

    function constructTokenSVG(
        address asset,
        address collateral,
        string memory tokenId,
        string memory assetAmount,
        string memory collateralAmount,
        string memory maturityDate,
        uint256 maturityTimestamp
    ) internal view returns (string memory) {
        NFTSVG.SVGParams memory params = NFTSVG.SVGParams({
            tokenId: tokenId,
            svgTitle: string(
                abi.encodePacked(
                    parseSymbol(IERC20(asset).safeSymbol()),
                    '/',
                    parseSymbol(IERC20(collateral).safeSymbol())
                )
            ),
            assetInfo: string(abi.encodePacked(parseSymbol(IERC20(asset).safeSymbol()), ': ', addressToString(asset))),
            collateralInfo: string(
                abi.encodePacked(parseSymbol(IERC20(collateral).safeSymbol()), ': ', addressToString(collateral))
            ),
            debtRequired: string(abi.encodePacked(assetAmount, ' ', parseSymbol(IERC20(asset).safeSymbol()))),
            collateralLocked: string(
                abi.encodePacked(collateralAmount, ' ', parseSymbol(IERC20(collateral).safeSymbol()))
            ),
            maturityDate: maturityDate,
            isMatured: block.timestamp > maturityTimestamp,
            maturityTimestampString: maturityTimestamp.toString(),
            tokenColors: getSVGCData(asset, collateral)
        });

        return NFTSVG.constructSVG(params);
    }

    function weiToPrecisionLongString(uint256 weiAmt, uint256 decimal) public pure returns (string memory) {
        if (decimal == 0) {
            return string(abi.encodePacked(weiAmt.toString(), '.00'));
        }
        require(decimal >= 4, 'Should have either greater than or equal to 4 decimal places or 0 decimal places');

        uint256 significantDigits = weiAmt / (10**decimal);
        uint256 precisionDigits = weiAmt % (10**(decimal));

        if (precisionDigits == 0) {
            return string(abi.encodePacked(significantDigits.toString(), '.00'));
        }

        string memory precisionDigitsString = toStringTrimmed(precisionDigits);
        uint256 lengthDiff = decimal - bytes(precisionDigits.toString()).length;
        for (uint256 i; i < lengthDiff; ) {
            precisionDigitsString = string(abi.encodePacked('0', precisionDigitsString));
            unchecked {
                ++i;
            }
        }

        return string(abi.encodePacked(significantDigits.toString(), '.', precisionDigitsString));
    }

    function weiToPrecisionString(uint256 weiAmt, uint256 decimal) public pure returns (string memory) {
        if (decimal == 0) {
            return string(abi.encodePacked(weiAmt.toString(), '.00'));
        }
        require(decimal >= 4, 'Should have either greater than or equal to 4 decimal places or 0 decimal places');

        uint256 significantDigits = weiAmt / (10**decimal);
        if (significantDigits > 1e9) {
            string memory weiAmtString = weiAmt.toString();
            uint256 len = bytes(weiAmtString).length - 9;
            weiAmt = weiAmt / (10**len);
            return string(abi.encodePacked(weiAmt.toString(), '...'));
        }
        uint256 precisionDigits = weiAmt % (10**(decimal));
        precisionDigits = precisionDigits / (10**(decimal - 4));

        if (precisionDigits == 0) {
            return string(abi.encodePacked(significantDigits.toString(), '.00'));
        }

        string memory precisionDigitsString = toStringTrimmed(precisionDigits);
        uint256 lengthDiff = 4 - bytes(precisionDigits.toString()).length;
        for (uint256 i; i < lengthDiff; ) {
            precisionDigitsString = string(abi.encodePacked('0', precisionDigitsString));
            unchecked {
                ++i;
            }
        }

        return string(abi.encodePacked(significantDigits.toString(), '.', precisionDigitsString));
    }

    function toStringTrimmed(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return '0';
        }
        uint256 temp = value;
        uint256 digits;
        uint256 flag;
        while (temp != 0) {
            if (flag == 0 && temp % 10 == 0) {
                temp /= 10;
                continue;
            } else if (flag == 0 && temp % 10 != 0) {
                flag++;
                digits++;
            } else {
                digits++;
            }

            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        flag = 0;
        while (value != 0) {
            if (flag == 0 && value % 10 == 0) {
                value /= 10;
                continue;
            } else if (flag == 0 && value % 10 != 0) {
                flag++;
                digits -= 1;
                buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            } else {
                digits -= 1;
                buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            }

            value /= 10;
        }
        return string(buffer);
    }

    function addressToString(address _addr) public pure returns (string memory) {
        bytes memory data = abi.encodePacked(_addr);
        bytes memory alphabet = '0123456789abcdef';

        bytes memory str = new bytes(2 + data.length * 2);
        str[0] = '0';
        str[1] = 'x';
        for (uint256 i; i < data.length; ) {
            str[2 + i * 2] = alphabet[uint256(uint8(data[i] >> 4))];
            str[3 + i * 2] = alphabet[uint256(uint8(data[i] & 0x0f))];
            unchecked {
                ++i;
            }
        }
        return string(str);
    }

    function getSlice(
        uint256 begin,
        uint256 end,
        string memory text
    ) public pure returns (string memory) {
        bytes memory a = new bytes(end - begin + 1);
        for (uint256 i; i <= end - begin; ) {
            a[i] = bytes(text)[i + begin - 1];
            unchecked {
                ++i;
            }
        }
        return string(a);
    }

    function parseSymbol(string memory symbol) public pure returns (string memory) {
        if (bytes(symbol).length > 5) {
            return getSlice(1, 5, symbol);
        }
        return symbol;
    }

    function getMonthString(uint256 _month) public pure returns (string memory) {
        string[12] memory months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        return months[_month];
    }

    function getReadableDateString(uint256 timestamp) public pure returns (string memory) {
        (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second) = DateTime
            .timestampToDateTime(timestamp);

        string memory result = string(
            abi.encodePacked(
                day.toString(),
                ' ',
                getMonthString(month - 1),
                ' ',
                year.toString(),
                ', ',
                padWithZero(hour),
                ':',
                padWithZero(minute),
                ':',
                padWithZero(second),
                ' UTC'
            )
        );
        return result;
    }

    function padWithZero(uint256 value) public pure returns (string memory) {
        if (value < 10) {
            return string(abi.encodePacked('0', value.toString()));
        }
        return value.toString();
    }

    function getLightColor(address token) public pure returns (string memory) {
        string[15] memory lightColors = [
            'F7BAF7',
            'F7C8BA',
            'FAE2BE',
            'BAE1F7',
            'EBF7BA',
            'CEF7BA',
            'CED2EF',
            'CABAF7',
            'BAF7E5',
            'BACFF7',
            'F7BAE3',
            'F7E9BA',
            'E0BAF7',
            'F7BACF',
            'FFFFFF'
        ];
        uint160 tokenValue = uint160(token) % 15;
        return (lightColors[tokenValue]);
    }

    function getDarkColor(address token) public pure returns (string memory) {
        string[15] memory darkColors = [
            'DF51EC',
            'EC7651',
            'ECAE51',
            '51B4EC',
            'A4C327',
            '59C327',
            '5160EC',
            '7951EC',
            '27C394',
            '5185EC',
            'EC51B8',
            'F4CB3A',
            'B151EC',
            'EC5184',
            'C5C0C2'
        ];
        uint160 tokenValue = uint160(token) % 15;
        return (darkColors[tokenValue]);
    }

    function getSVGCData(address asset, address collateral) public pure returns (string memory) {
        string memory token0LightColor = string(abi.encodePacked('.C{fill:#', getLightColor(asset), '}'));
        string memory token0DarkColor = string(abi.encodePacked('.D{fill:#', getDarkColor(asset), '}'));
        string memory token1LightColor = string(abi.encodePacked('.E{fill:#', getLightColor(collateral), '}'));
        string memory token1DarkColor = string(abi.encodePacked('.F{fill:#', getDarkColor(collateral), '}'));

        return string(abi.encodePacked(token0LightColor, token0DarkColor, token1LightColor, token1DarkColor));
    }
}

File 64 of 75 : ERC721.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

import {IERC721Extended} from '../interfaces/IERC721Extended.sol';
import {IERC721Receiver} from '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';

abstract contract ERC721 is IERC721Extended {
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
    bytes4 private constant _INTERFACE_ID_ERC721METADATA = 0x5b5e139f;
    bytes4 private constant _INTERFACE_ID_ERC721ENUMERABLE = 0x780e9d63;

    mapping(address => uint256) private _balances;
    mapping(uint256 => address) internal _owners;
    mapping(uint256 => address) private _tokenApprovals;
    mapping(address => mapping(address => bool)) private _operatorApprovals;
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
    mapping(uint256 => uint256) private _ownedTokensIndex;

    function balanceOf(address owner) external view override returns (uint256) {
        require(owner != address(0), 'E613');
        return _balances[owner];
    }

    function ownerOf(uint256 id) external view override returns (address) {
        address owner = _owners[id];
        require(owner != address(0), 'E613');
        return owner;
    }

    function getApproved(uint256 id) external view override returns (address) {
        require(_owners[id] != address(0), 'E614');
        return _tokenApprovals[id];
    }

    function isApprovedForAll(address owner, address operator) external view override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    function tokenOfOwnerByIndex(address owner, uint256 id) external view override returns (uint256) {
        require(id < _balances[owner], 'E614');
        return _ownedTokens[owner][id];
    }

    function supportsInterface(bytes4 interfaceID) external pure override returns (bool) {
        return
            interfaceID == _INTERFACE_ID_ERC165 ||
            interfaceID == _INTERFACE_ID_ERC721 ||
            interfaceID == _INTERFACE_ID_ERC721METADATA ||
            interfaceID == _INTERFACE_ID_ERC721ENUMERABLE;
    }

    modifier isApproved(address owner, uint256 id) {
        require(
            owner == msg.sender || _tokenApprovals[id] == msg.sender || _operatorApprovals[owner][msg.sender],
            '611'
        );
        _;
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) external override isApproved(from, id) {
        _safeTransfer(from, to, id, '');
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) external override isApproved(from, id) {
        _safeTransfer(from, to, id, data);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) external override isApproved(from, id) {
        _transfer(from, to, id);
    }

    function approve(address to, uint256 id) external override {
        address owner = _owners[id];
        require(owner == msg.sender || _operatorApprovals[owner][msg.sender], '609');
        require(to != owner, 'E605');

        _approve(to, id);
    }

    function setApprovalForAll(address operator, bool approved) external override {
        require(operator != msg.sender, 'E607');

        _setApprovalForAll(operator, approved);
    }

    function _safeTransfer(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) private {
        _transfer(from, to, id);

        require(_checkOnERC721Received(from, to, id, data), 'E608');
    }

    function _approve(address to, uint256 id) internal {
        if (to == address(0)) {
            delete _tokenApprovals[id];
        } else _tokenApprovals[id] = to;

        emit Approval(_owners[id], to, id);
    }

    function _setApprovalForAll(address operator, bool approved) private {
        if (!approved) {
            delete _operatorApprovals[msg.sender][operator];
        } else _operatorApprovals[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function _safeMint(address to, uint256 id) internal {
        _mint(to, id);

        require(_checkOnERC721Received(address(0), to, id, ''), 'E610');
    }

    function _mint(address to, uint256 id) private {
        require(to != address(0), 'E601');
        require(_owners[id] == address(0), 'E604');

        uint256 length = _balances[to];
        _ownedTokens[to][length] = id;
        _ownedTokensIndex[id] = length;

        _balances[to]++;
        _owners[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _transfer(
        address from,
        address to,
        uint256 id
    ) private {
        require(to != address(0), 'E601');

        if (from != to) {
            uint256 lastTokenIndex = _balances[from] - 1;
            uint256 tokenIndex = _ownedTokensIndex[id];

            if (lastTokenIndex != tokenIndex) {
                uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

                _ownedTokens[from][tokenIndex] = lastTokenId;
                _ownedTokensIndex[lastTokenId] = tokenIndex;
            }

            delete _ownedTokens[from][lastTokenIndex];

            uint256 length = _balances[to];
            _ownedTokens[to][length] = id;
            _ownedTokensIndex[id] = length;
        }

        _owners[id] = to;
        _balances[from]--;
        _balances[to]++;

        _approve(address(0), id);

        emit Transfer(from, to, id);
    }

    function _checkOnERC721Received(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) private returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(to)
        }
        if (size == 0) {
            return true;
        } else {
            bytes memory returnData;
            (bool success, bytes memory _return) = to.call(
                abi.encodeWithSelector(IERC721Receiver(to).onERC721Received.selector, msg.sender, from, id, data)
            );
            if (success) {
                returnData = _return;
            } else if (_return.length != 0) {
                assembly {
                    let returnDataSize := mload(_return)
                    revert(add(32, _return), returnDataSize)
                }
            } else {
                revert('E610');
            }
            bytes4 retval = abi.decode(returnData, (bytes4));
            return (retval == 0x150b7a02);
        }
    }
}

File 65 of 75 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 66 of 75 : DateTime.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

// ----------------------------------------------------------------------------
// BokkyPooBah's DateTime Library v1.01
//
// A gas-efficient Solidity date and time library
//
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary
//
// Tested date range 1970/01/01 to 2345/12/31
//
// Conventions:
// Unit      | Range         | Notes
// :-------- |:-------------:|:-----
// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC
// year      | 1970 ... 2345 |
// month     | 1 ... 12      |
// day       | 1 ... 31      |
// hour      | 0 ... 23      |
// minute    | 0 ... 59      |
// second    | 0 ... 59      |
// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday
//
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.
// ----------------------------------------------------------------------------

library DateTime {
    uint256 constant SECONDS_PER_DAY = 86400;
    uint256 constant SECONDS_PER_HOUR = 3600;
    uint256 constant SECONDS_PER_MINUTE = 60;
    int256 constant OFFSET19700101 = 2440588;

    uint256 constant DOW_MON = 1;
    uint256 constant DOW_TUE = 2;
    uint256 constant DOW_WED = 3;
    uint256 constant DOW_THU = 4;
    uint256 constant DOW_FRI = 5;
    uint256 constant DOW_SAT = 6;
    uint256 constant DOW_SUN = 7;

    // ------------------------------------------------------------------------
    // Calculate the number of days from 1970/01/01 to year/month/day using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and subtracting the offset 2440588 so that 1970/01/01 is day 0
    //
    // days = day
    //      - 32075
    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4
    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12
    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4
    //      - offset
    // ------------------------------------------------------------------------
    function _daysFromDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (uint256 _days) {
        require(year >= 1970);
        int256 _year = int256(year);
        int256 _month = int256(month);
        int256 _day = int256(day);

        int256 __days = _day -
            32075 +
            (1461 * (_year + 4800 + (_month - 14) / 12)) /
            4 +
            (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /
            12 -
            (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /
            4 -
            OFFSET19700101;

        _days = uint256(__days);
    }

    // ------------------------------------------------------------------------
    // Calculate year/month/day from the number of days since 1970/01/01 using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and adding the offset 2440588 so that 1970/01/01 is day 0
    //
    // int L = days + 68569 + offset
    // int N = 4 * L / 146097
    // L = L - (146097 * N + 3) / 4
    // year = 4000 * (L + 1) / 1461001
    // L = L - 1461 * year / 4 + 31
    // month = 80 * L / 2447
    // dd = L - 2447 * month / 80
    // L = month / 11
    // month = month + 2 - 12 * L
    // year = 100 * (N - 49) + year + L
    // ------------------------------------------------------------------------
    function _daysToDate(uint256 _days)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day
        )
    {
        int256 __days = int256(_days);

        int256 L = __days + 68569 + OFFSET19700101;
        int256 N = (4 * L) / 146097;
        L = L - (146097 * N + 3) / 4;
        int256 _year = (4000 * (L + 1)) / 1461001;
        L = L - (1461 * _year) / 4 + 31;
        int256 _month = (80 * L) / 2447;
        int256 _day = L - (2447 * _month) / 80;
        L = _month / 11;
        _month = _month + 2 - 12 * L;
        _year = 100 * (N - 49) + _year + L;

        year = uint256(_year);
        month = uint256(_month);
        day = uint256(_day);
    }

    function timestampFromDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (uint256 timestamp) {
        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
    }

    function timestampFromDateTime(
        uint256 year,
        uint256 month,
        uint256 day,
        uint256 hour,
        uint256 minute,
        uint256 second
    ) internal pure returns (uint256 timestamp) {
        timestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            hour *
            SECONDS_PER_HOUR +
            minute *
            SECONDS_PER_MINUTE +
            second;
    }

    function timestampToDate(uint256 timestamp)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day
        )
    {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function timestampToDateTime(uint256 timestamp)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day,
            uint256 hour,
            uint256 minute,
            uint256 second
        )
    {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        uint256 secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
        secs = secs % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
        second = secs % SECONDS_PER_MINUTE;
    }

    function isValidDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (bool valid) {
        if (year >= 1970 && month != 0 && month <= 12) {
            if (day != 0 && day <= _getDaysInMonth(year, month)) {
                valid = true;
            }
        }
    }

    function isValidDateTime(
        uint256 year,
        uint256 month,
        uint256 day,
        uint256 hour,
        uint256 minute,
        uint256 second
    ) internal pure returns (bool valid) {
        if (isValidDate(year, month, day)) {
            if (hour < 24 && minute < 60 && second < 60) {
                valid = true;
            }
        }
    }

    function isLeapYear(uint256 timestamp) internal pure returns (bool leapYear) {
        (uint256 year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
        leapYear = _isLeapYear(year);
    }

    function _isLeapYear(uint256 year) internal pure returns (bool leapYear) {
        leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
    }

    function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) {
        weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
    }

    function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) {
        weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
    }

    function getDaysInMonth(uint256 timestamp) internal pure returns (uint256 daysInMonth) {
        (uint256 year, uint256 month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);
        daysInMonth = _getDaysInMonth(year, month);
    }

    function _getDaysInMonth(uint256 year, uint256 month) internal pure returns (uint256 daysInMonth) {
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            daysInMonth = 31;
        } else if (month != 2) {
            daysInMonth = 30;
        } else {
            daysInMonth = _isLeapYear(year) ? 29 : 28;
        }
    }

    // 1 = Monday, 7 = Sunday
    function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) {
        uint256 _days = timestamp / SECONDS_PER_DAY;
        dayOfWeek = ((_days + 3) % 7) + 1;
    }

    function getYear(uint256 timestamp) internal pure returns (uint256 year) {
        (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getMonth(uint256 timestamp) internal pure returns (uint256 month) {
        (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getDay(uint256 timestamp) internal pure returns (uint256 day) {
        (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getHour(uint256 timestamp) internal pure returns (uint256 hour) {
        uint256 secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
    }

    function getMinute(uint256 timestamp) internal pure returns (uint256 minute) {
        uint256 secs = timestamp % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
    }

    function getSecond(uint256 timestamp) internal pure returns (uint256 second) {
        second = timestamp % SECONDS_PER_MINUTE;
    }

    function addYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {
        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        year += _years;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
        require(newTimestamp >= timestamp);
    }

    function addMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {
        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        month += _months;
        year += (month - 1) / 12;
        month = ((month - 1) % 12) + 1;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
        require(newTimestamp >= timestamp);
    }

    function addDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp + _days * SECONDS_PER_DAY;
        require(newTimestamp >= timestamp);
    }

    function addHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
        require(newTimestamp >= timestamp);
    }

    function addMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp >= timestamp);
    }

    function addSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp + _seconds;
        require(newTimestamp >= timestamp);
    }

    function subYears(uint256 timestamp, uint256 _years) internal pure returns (uint256 newTimestamp) {
        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        year -= _years;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
        require(newTimestamp <= timestamp);
    }

    function subMonths(uint256 timestamp, uint256 _months) internal pure returns (uint256 newTimestamp) {
        (uint256 year, uint256 month, uint256 day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        uint256 yearMonth = year * 12 + (month - 1) - _months;
        year = yearMonth / 12;
        month = (yearMonth % 12) + 1;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + (timestamp % SECONDS_PER_DAY);
        require(newTimestamp <= timestamp);
    }

    function subDays(uint256 timestamp, uint256 _days) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp - _days * SECONDS_PER_DAY;
        require(newTimestamp <= timestamp);
    }

    function subHours(uint256 timestamp, uint256 _hours) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
        require(newTimestamp <= timestamp);
    }

    function subMinutes(uint256 timestamp, uint256 _minutes) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp <= timestamp);
    }

    function subSeconds(uint256 timestamp, uint256 _seconds) internal pure returns (uint256 newTimestamp) {
        newTimestamp = timestamp - _seconds;
        require(newTimestamp <= timestamp);
    }

    function diffYears(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _years) {
        require(fromTimestamp <= toTimestamp);
        (uint256 fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint256 toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _years = toYear - fromYear;
    }

    function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _months) {
        require(fromTimestamp <= toTimestamp);
        (uint256 fromYear, uint256 fromMonth, ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint256 toYear, uint256 toMonth, ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
    }

    function diffDays(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _days) {
        require(fromTimestamp <= toTimestamp);
        _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
    }

    function diffHours(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _hours) {
        require(fromTimestamp <= toTimestamp);
        _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
    }

    function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _minutes) {
        require(fromTimestamp <= toTimestamp);
        _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
    }

    function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) internal pure returns (uint256 _seconds) {
        require(fromTimestamp <= toTimestamp);
        _seconds = toTimestamp - fromTimestamp;
    }
}

File 67 of 75 : Base64.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

/// @title Base64
/// @author Brecht Devos - <[email protected]>
/// @notice Provides a function for encoding some bytes in base64
library Base64 {
    string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';

        // load the table into memory
        string memory table = TABLE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                dataPtr := add(dataPtr, 3)

                // read 3 bytes
                let input := mload(dataPtr)

                // write 4 characters
                mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
                resultPtr := add(resultPtr, 1)
                mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
                resultPtr := add(resultPtr, 1)
                mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F)))))
                resultPtr := add(resultPtr, 1)
                mstore(resultPtr, shl(248, mload(add(tablePtr, and(input, 0x3F)))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }
        }

        return result;
    }
}

File 68 of 75 : NFTSVG.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

library NFTSVG {
    struct SVGParams {
        string tokenId;
        string svgTitle;
        string assetInfo;
        string collateralInfo;
        string debtRequired;
        string collateralLocked;
        string maturityDate;
        string maturityTimestampString;
        string tokenColors;
        bool isMatured;
    }

    function constructSVG(SVGParams memory params) public pure returns (string memory) {
        string memory colorScheme = params.isMatured
            ? '.G{stop-color:#3C3C3C}.H{fill:#959595}.I{stop-color:#000000}.J{stop-color:#FFFFFF}'
            : '.G{stop-color:#20087E}.H{fill:#5457D7}.I{stop-color:#61F6FF}.J{stop-color:#3C43FF}';

        string memory svg = string(
            abi.encodePacked(
                '<svg width="290" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css" ><![CDATA[.B{fill-rule:evenodd}',
                params.tokenColors,
                colorScheme,
                ']]></style><g clip-path="url(#mainclip)"><rect width="290" height="500" fill="url(\'#background\')"/><rect y="409" width="290" height="90" fill="#141330" fill-opacity="0.4"/><rect y="408" width="290" height="2" fill="url(#divider)"/></g><text y="70px" x="145" fill="white" font-family="arial" font-weight="500" font-size="24px" text-anchor="middle">'
            )
        );

        svg = string(
            abi.encodePacked(
                svg,
                params.svgTitle,
                '</text><text y="95px" x="145" fill="white" font-family="arial" font-weight="400" font-size="12px" text-anchor="middle">',
                params.maturityDate,
                '</text>'
            )
        );

        if (!params.isMatured) {
            string memory maturityInfo = string(abi.encodePacked('MATURITY: ', params.maturityTimestampString));
            svg = string(
                abi.encodePacked(
                    svg,
                    '<text y="115px" x="145" fill="white" font-family="arial" font-weight="300" font-size="10px" text-anchor="middle" opacity="50%">',
                    maturityInfo,
                    '</text>'
                )
            );
        } else {
            svg = string(
                abi.encodePacked(
                    svg,
                    '<rect width="74" height="22" rx="13" y="110" x="107" text-anchor="middle" fill="#FFFFFF" /><text y="125px" x="145" fill="black" font-family="arial" font-weight="600" font-size="10px" letter-spacing="1" text-anchor="middle">MATURED</text>'
                )
            );
        }

        svg = string(
            abi.encodePacked(
                svg,
                '<text text-rendering="optimizeSpeed"><textPath startOffset="-100%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
                params.assetInfo,
                '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /></textPath><textPath startOffset="0%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
                params.assetInfo,
                '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /></textPath><textPath startOffset="50%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">'
            )
        );
        svg = string(
            abi.encodePacked(
                svg,
                params.collateralInfo,
                '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /></textPath><textPath startOffset="-50%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
                params.collateralInfo,
                '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /></textPath></text><text y="435px" x="12" fill="white" font-family="arial" font-weight="400" font-size="13px" opacity="60%">ID:</text><text y="435px" x="278" fill="white" font-family="arial" font-weight="500" font-size="13px" text-anchor="end">'
            )
        );
        svg = string(
            abi.encodePacked(
                svg,
                params.tokenId,
                '</text><text y="460px" x="12" fill="white" font-family="arial" font-weight="400" font-size="13px" opacity="60%">Debt required:</text><text y="460px" x="278" fill="white" font-family="arial" font-weight="500" font-size="13px" text-anchor="end">',
                params.debtRequired,
                '</text><text y="484px" x="12" fill="white" font-family="arial" font-weight="400" font-size="13px" opacity="60%">Collateral locked:</text><text y="484px" x="278" fill="white" font-family="arial" font-weight="500" font-size="13px" text-anchor="end">',
                params.collateralLocked,
                '</text><g filter="url(#filter0_f)"><path d="M253 319.5C253 346.838 204.871 369 145.5 369C86.1294 369 38 346.838 38 319.5C38 292.162 86.1294 270 145.5 270C204.871 270 253 292.162 253 319.5Z" class="H"/></g>'
            )
        );
        svg = string(
            abi.encodePacked(
                svg,
                '<path d="M144.235 272.663h4.147v11.255h-4.147zm62.092 19.456l2.074 2.089-16.76 5.627-2.074-2.089zm-26.564-14.565l3.591 1.206-9.676 9.747-3.591-1.206zm37.046 34.903v2.412h-19.353v-2.412zm-33.454 36.11l-3.591 1.206-9.676-9.747 3.591-1.206zm25.046-15.448l-2.074 2.089-16.76-5.627 2.074-2.089zm-64.165 10.289h4.147v11.255h-4.147zm-43.258-15.916l2.074 2.089-16.76 5.627-2.074-2.089zm17.962 11.328l3.591 1.206-9.676 9.747-3.591-1.206zm-25.778-26.157v2.412H73.809v-2.412zm28.915-26.253l-3.591 1.206-9.676-9.747 3.591-1.206zm-20.434 10.881l-2.074 2.089-16.76-5.627 2.074-2.089z" fill="#6fa4d4"/><path d="M198.383 344.249C211.892 336.376 220 325.646 220 314s-8.108-22.376-21.617-30.249C184.898 275.893 166.204 271 145.5 271s-39.398 4.893-52.883 12.751C79.108 291.624 71 302.354 71 314s8.108 22.376 21.617 30.249C106.102 352.107 124.796 357 145.5 357s39.398-4.893 52.883-12.751zM145.5 358c41.698 0 75.5-19.699 75.5-44s-33.802-44-75.5-44S70 289.699 70 314s33.803 44 75.5 44zm56.402-10.206C216.307 339.026 225 327.049 225 314s-8.693-25.026-23.098-33.794C187.516 271.449 167.577 266 145.5 266s-42.016 5.449-56.402 14.206C74.694 288.974 66 300.951 66 314s8.694 25.026 23.098 33.794C103.484 356.551 123.423 362 145.5 362s42.016-5.449 56.402-14.206zM145.5 363c44.459 0 80.5-21.938 80.5-49s-36.041-49-80.5-49S65 286.938 65 314s36.041 49 80.5 49z" fill-rule="evenodd" fill="#6fa4d5"/><path d="M189.764 303.604c0 14.364-19.951 26.008-44.562 26.008-24.343 0-44.127-11.392-44.555-25.54v6.92.363c0 14.38 19.951 26.022 44.562 26.022s44.562-11.642 44.562-26.022v-.363-7.574h-.008l.001.186z" fill="#7fc2e2"/><path d="M145.202 326.408c21.834 0 39.533-10.256 39.533-22.906s-17.699-22.906-39.533-22.906-39.533 10.255-39.533 22.906 17.7 22.906 39.533 22.906z" fill="#020136"/><path d="M189.764 303.604c0 14.364-19.951 26.008-44.562 26.008s-44.562-11.644-44.562-26.008 19.951-26.008 44.562-26.008 44.562 11.644 44.562 26.008zm-5.029-.102c0 12.65-17.699 22.906-39.533 22.906s-39.533-10.255-39.533-22.906 17.699-22.906 39.533-22.906 39.533 10.256 39.533 22.906z" fill="#4f95b8" class="B"/><path d="M184.753 303.84v-5.406c0-18.859-10.806-36.185-28.114-45.047l-3.987-2.053a2.31 2.31 0 0 1-.975-.848 2.46 2.46 0 0 1-.39-1.259 2.47 2.47 0 0 1 .316-1.282c.216-.384.536-.699.924-.908l6.693-3.887c15.85-9.252 25.533-25.798 25.533-43.637V184h-78.996v15.095c0 18.065 9.925 34.782 26.098 43.959l6.772 3.846a2.34 2.34 0 0 1 .937.911c.223.39.334.839.321 1.293s-.15.894-.395 1.27-.588.671-.988.851l-4.105 2.053c-17.598 8.772-28.64 26.249-28.64 45.32v4.948c-.624 6.062 3.212 12.255 11.581 16.901 15.515 8.616 40.595 8.664 56.011.096 8.238-4.584 12.008-10.688 11.404-16.703h0z" fill="#fff" fill-opacity=".3"/><path d="M154.382 238.266c3.037-5.261 3.007-10.965-.062-12.737l2.734 1.579c3.069 1.772 3.098 7.476.061 12.737s-7.992 8.088-11.061 6.316l-2.734-1.579c3.069 1.772 8.025-1.055 11.062-6.315v-.001z" class="D"/><path d="M154.382 238.266c3.037-5.261 3.007-10.965-.062-12.737s-8.024 1.055-11.061 6.316-3.008 10.965.061 12.737 8.025-1.055 11.062-6.315v-.001zm-1.402-.809c2.27-3.932 2.252-8.2-.045-9.526s-6.004.792-8.274 4.724-2.247 8.192.051 9.519 5.998-.784 8.268-4.716v-.001z" class="B C"/><path d="M152.935 227.929c2.297 1.326 2.315 5.595.045 9.526s-5.971 6.042-8.268 4.716-2.321-5.587-.051-9.519 5.975-6.051 8.273-4.724l.001.001z" class="D"/><path d="M148.854 232.173l1.827-2.157c.303-.364.664-.269.607.154l-.349 2.545c-.021.163.023.302.121.349l1.488.806c.241.139.107.695-.237.951l-2.028 1.534a.91.91 0 0 0-.316.438l-.91 2.656c-.155.449-.597.692-.75.437l-.938-1.578c-.031-.052-.08-.09-.139-.107s-.121-.01-.174.019l-2.043.841c-.35.139-.475-.274-.238-.686l1.458-2.525a.81.81 0 0 0 .118-.492l-.345-2.136a.8.8 0 0 1 .142-.539.81.81 0 0 1 .457-.318l1.85.033a.56.56 0 0 0 .223-.071.57.57 0 0 0 .176-.155v.001z" class="C"/><path d="M166.548 230.55c4.318-4.272 5.796-9.782 3.303-12.302l2.221 2.245c2.492 2.519 1.014 8.029-3.304 12.301s-9.844 5.691-12.336 3.171l-2.221-2.245c2.492 2.52 8.018 1.102 12.337-3.17z" class="D"/><path d="M166.548 230.549c4.318-4.272 5.796-9.782 3.303-12.302s-8.017-1.101-12.336 3.171-5.797 9.782-3.304 12.301 8.018 1.102 12.337-3.17zm-1.139-1.151c3.228-3.193 4.338-7.314 2.472-9.2s-6-.821-9.227 2.371-4.33 7.308-2.464 9.194 5.993.827 9.22-2.366l-.001.001z" class="B C"/><path d="M167.881 220.199c1.866 1.886.755 6.008-2.472 9.2s-7.354 4.252-9.22 2.366-.763-6.002 2.464-9.194 7.36-4.258 9.227-2.371l.001-.001z" class="D"/><path d="M162.824 223.215l2.332-1.599c.388-.271.711-.084.545.308l-1.008 2.363c-.064.152-.057.298.024.369l1.222 1.17c.196.198-.08.699-.48.854l-2.361.944c-.172.067-.318.186-.421.339l-1.579 2.321c-.268.392-.758.51-.839.224l-.488-1.77c-.015-.059-.052-.109-.104-.141s-.115-.04-.174-.026l-2.193.271c-.375.042-.386-.39-.048-.725l2.072-2.05a.81.81 0 0 0 .244-.443l.231-2.151a.81.81 0 0 1 .28-.483c.148-.123.333-.188.524-.186l1.776.52c.078.013.158.01.234-.009a.56.56 0 0 0 .211-.103v.003z" class="C"/><path d="M131.352 236.907c4.692 3.858 10.325 4.762 12.576 2.024l-2.005 2.439c-2.251 2.738-7.883 1.832-12.575-2.025s-6.67-9.208-4.419-11.946l2.005-2.439c-2.251 2.738-.274 8.089 4.419 11.947h-.001z" class="D"/><path d="M131.352 236.907c4.692 3.858 10.325 4.762 12.576 2.024s.273-8.088-4.419-11.946-10.324-4.763-12.575-2.025-.274 8.089 4.419 11.947h-.001zm1.028-1.251c3.507 2.883 7.721 3.564 9.405 1.515s.202-6.052-3.305-8.935-7.714-3.558-9.399-1.508-.208 6.046 3.299 8.929v-.001z" class="B C"/><path d="M141.785 237.172c-1.685 2.049-5.898 1.368-9.405-1.515s-4.983-6.879-3.299-8.929 5.892-1.374 9.399 1.509 4.991 6.885 3.305 8.935z" class="D"/><path d="M138.267 232.451l1.829 2.156c.309.359.156.699-.251.574l-2.454-.76c-.157-.048-.302-.026-.364.062l-1.039 1.335c-.177.215-.703-.008-.899-.39l-1.181-2.252c-.084-.164-.217-.298-.381-.384l-2.471-1.333c-.417-.227-.585-.702-.309-.812l1.71-.667c.057-.021.103-.064.128-.12s.03-.117.009-.174l-.495-2.153c-.08-.368.349-.424.716-.122l2.252 1.851a.81.81 0 0 0 .466.197l2.164.009a.81.81 0 0 1 .509.228c.138.134.221.312.239.503l-.336 1.82a.59.59 0 0 0 .033.232c.026.074.069.142.124.2h.001z" class="C"/><path d="M119.071 225.508c3.876 4.677 9.235 6.633 11.964 4.372l-2.431 2.015c-2.729 2.261-8.087.305-11.963-4.373s-4.803-10.306-2.074-12.567l2.431-2.015c-2.729 2.261-1.802 7.89 2.073 12.568z" class="D"/><path d="M119.071 225.508c3.876 4.677 9.235 6.633 11.964 4.372s1.802-7.89-2.074-12.567-9.234-6.634-11.963-4.373-1.802 7.89 2.073 12.568zm1.247-1.033c2.897 3.496 6.905 4.964 8.947 3.271s1.346-5.904-1.551-9.4-6.9-4.956-8.942-3.263-1.351 5.896 1.546 9.392h0z" class="B C"/><path d="M129.265 227.745c-2.043 1.693-6.051.225-8.947-3.271s-3.589-7.699-1.546-9.392 6.045-.233 8.942 3.263 3.595 7.707 1.551 9.4h0z" class="D"/><path d="M126.705 222.444l1.387 2.463c.235.411.021.716-.355.516l-2.265-1.212c-.145-.077-.292-.083-.369-.008l-1.273 1.114c-.214.177-.689-.141-.809-.553l-.733-2.435a.9.9 0 0 0-.301-.449l-2.173-1.777c-.367-.302-.441-.8-.149-.856l1.806-.331c.06-.01.114-.043.15-.092s.05-.111.041-.171l-.078-2.208c-.009-.377.423-.35.726.016l1.86 2.245a.81.81 0 0 0 .42.282l2.123.419c.186.049.347.163.456.32s.158.349.139.539l-.674 1.723c-.02.077-.023.156-.012.234s.041.152.084.219l-.001.002z" class="C"/><path d="M140.196 225.21c5.607 2.338 11.261 1.576 12.624-1.695l-1.215 2.914c-1.364 3.271-7.017 4.031-12.624 1.694s-9.046-6.888-7.682-10.16l1.215-2.914c-1.364 3.271 2.075 7.823 7.682 10.161h0z" class="D"/><path d="M140.196 225.211c5.607 2.337 11.261 1.576 12.624-1.695s-2.075-7.822-7.682-10.16-11.26-1.577-12.624 1.694 2.075 7.823 7.682 10.161h0zm.623-1.494c4.19 1.747 8.421 1.182 9.442-1.266s-1.555-5.853-5.746-7.599-8.413-1.178-9.434 1.271 1.547 5.848 5.737 7.595l.001-.001z" class="B C"/><path d="M150.261 222.449c-1.021 2.449-5.252 3.013-9.442 1.266s-6.758-5.146-5.737-7.595 5.243-3.018 9.434-1.271 6.767 5.15 5.746 7.6h-.001z" class="D"/><path d="M145.528 218.948l2.374 1.535c.4.254.352.624-.074.622l-2.569-.019c-.165 0-.297.062-.331.164l-.609 1.579c-.107.257-.675.196-.973-.114l-1.781-1.815a.9.9 0 0 0-.475-.257l-2.751-.562c-.465-.097-.763-.503-.53-.688l1.445-1.133c.048-.037.079-.091.088-.151s-.006-.121-.041-.17l-1.096-1.919c-.183-.329.211-.507.65-.324l2.691 1.122c.157.071.334.09.503.054l2.074-.616c.187-.043.383-.017.553.072a.81.81 0 0 1 .374.412l.205 1.839c.018.077.052.149.099.213a.57.57 0 0 0 .176.155h0l-.002.001z" class="C"/><path d="M147.623 266.948c3.037-5.26 3.007-10.965-.062-12.737l2.734 1.579c3.069 1.772 3.098 7.476.061 12.737s-7.992 8.087-11.061 6.315l-2.734-1.579c3.069 1.772 8.025-1.054 11.062-6.315h0z" class="F"/><path d="M147.623 266.948c3.037-5.26 3.007-10.965-.062-12.737s-8.024 1.055-11.061 6.315-3.008 10.965.061 12.737 8.025-1.054 11.062-6.315zm-1.402-.809c2.27-3.932 2.252-8.2-.045-9.526s-6.004.791-8.274 4.723-2.247 8.192.051 9.519 5.998-.785 8.268-4.716h0z" class="B E"/><path d="M146.176 256.612c2.297 1.327 2.315 5.595.045 9.527s-5.971 6.042-8.268 4.716-2.321-5.587-.051-9.519 5.975-6.051 8.273-4.724h.001z" class="F"/><path d="M142.095 260.856l1.827-2.157c.303-.364.664-.269.607.153l-.349 2.546c-.021.163.023.302.121.349l1.488.806c.241.139.107.695-.237.951l-2.028 1.534c-.148.11-.258.263-.316.438l-.91 2.656c-.155.449-.597.692-.75.437l-.938-1.578c-.031-.052-.08-.091-.139-.107a.23.23 0 0 0-.174.02l-2.043.84c-.35.14-.475-.274-.238-.686l1.458-2.525a.81.81 0 0 0 .118-.492l-.345-2.136c-.019-.191.032-.381.142-.539a.81.81 0 0 1 .457-.318l1.85.034c.078-.009.154-.033.223-.071s.129-.091.176-.155h0z" class="E"/><use xlink:href="#B" class="F"/><path d="M124 306.844c6.075 0 11-2.879 11-6.423S130.075 294 124 294s-11 2.877-11 6.421 4.926 6.423 11 6.423zm0-1.619c4.54 0 8.228-2.15 8.228-4.803s-3.688-4.803-8.228-4.803-8.218 2.151-8.218 4.803 3.678 4.803 8.218 4.803z" class="B E"/><use xlink:href="#C" class="F"/><use xlink:href="#D" class="E"/><use xlink:href="#B" x="6" y="9" class="F"/><path d="M130 315.844c6.075 0 11-2.879 11-6.423S136.075 303 130 303s-11 2.877-11 6.421 4.926 6.423 11 6.423zm0-1.619c4.54 0 8.228-2.15 8.228-4.803s-3.688-4.803-8.228-4.803-8.218 2.151-8.218 4.803 3.678 4.803 8.218 4.803z" class="B E"/><use xlink:href="#C" x="6" y="9" class="F"/><use xlink:href="#D" x="6" y="9" class="E"/><use xlink:href="#B" x="29" y="12" class="F"/><path d="M153 318.844c6.075 0 11-2.879 11-6.423S159.075 306 153 306s-11 2.877-11 6.421 4.926 6.423 11 6.423zm0-1.619c4.54 0 8.228-2.15 8.228-4.803s-3.688-4.803-8.228-4.803-8.218 2.151-8.218 4.803 3.678 4.803 8.218 4.803z" class="B E"/><use xlink:href="#C" x="29" y="12" class="F"/><use xlink:href="#D" x="29" y="12" class="E"/><use xlink:href="#E" class="F"/><path d="M165 304.844c6.074 0 11-2.879 11-6.423S171.074 292 165 292s-11 2.877-11 6.421 4.926 6.423 11 6.423zm0-1.619c4.54 0 8.227-2.15 8.227-4.803s-3.687-4.803-8.227-4.803-8.218 2.151-8.218 4.803 3.678 4.803 8.218 4.803z" class="B E"/><use xlink:href="#F" class="F"/><path d="M167.512 297.01l2.781.504c.467.081.565.44.171.603l-2.378.97c-.152.064-.251.172-.242.28l.045 1.691c0 .278-.548.44-.942.27l-2.342-.99c-.17-.073-.357-.092-.538-.054l-2.755.539c-.466.09-.898-.17-.754-.431l.898-1.601c.03-.053.038-.115.023-.174a.23.23 0 0 0-.104-.141l-1.75-1.349c-.295-.233 0-.549.476-.549h2.915c.173.005.343-.045.485-.143l1.678-1.367a.8.8 0 0 1 .537-.147.81.81 0 0 1 .504.237l.897 1.619c.046.064.105.118.172.158a.56.56 0 0 0 .223.075h0z" class="E"/><use xlink:href="#E" x="-6" y="7" class="F"/><path d="M159 311.844c6.074 0 11-2.879 11-6.423S165.074 299 159 299s-11 2.877-11 6.421 4.926 6.423 11 6.423zm0-1.619c4.54 0 8.227-2.15 8.227-4.803s-3.687-4.803-8.227-4.803-8.218 2.151-8.218 4.803 3.678 4.803 8.218 4.803z" class="B E"/><use xlink:href="#F" x="-6" y="7" class="F"/><path d="M161.512 304.01l2.781.504c.467.081.565.44.171.603l-2.378.97c-.152.064-.251.172-.242.28l.045 1.691c0 .278-.548.44-.942.27l-2.342-.99c-.17-.073-.357-.092-.538-.054l-2.755.539c-.466.09-.898-.17-.754-.431l.898-1.601c.03-.053.038-.115.023-.174s-.052-.11-.103-.141l-1.75-1.349c-.296-.233 0-.549.476-.549h2.915c.173.005.343-.045.485-.143l1.678-1.367a.8.8 0 0 1 .537-.147.81.81 0 0 1 .504.237l.897 1.619c.046.064.105.118.172.158a.56.56 0 0 0 .223.075h-.001z" class="E"/><path d="M189.764 174.008c0 14.364-19.951 26.008-44.562 26.008-24.343 0-44.127-11.392-44.555-25.54v6.928.356c0 14.38 19.951 26.022 44.562 26.022s44.562-11.641 44.562-26.022v-.356-7.581h-.008l.001.185z" fill="#2f2be1" class="B"/><path d="M144.5 194c19.054 0 34.5-8.954 34.5-20s-15.446-20-34.5-20-34.5 8.954-34.5 20 15.446 20 34.5 20z" fill="#232277"/><path d="M189.764 174.008c0 14.364-19.951 26.008-44.562 26.008s-44.562-11.644-44.562-26.008S120.591 148 145.202 148s44.562 11.644 44.562 26.008zM179 174c0 11.046-15.446 20-34.5 20s-34.5-8.954-34.5-20 15.446-20 34.5-20 34.5 8.954 34.5 20z" fill="#504df7" class="B"/><path d="M155.683 172.788l-12.188 3.486c-1.635.467-3.657-.207-3.774-1.258l-.864-7.836c-.103-.91.257-1.804 1.034-2.582l.602-.601c.55-.55 1.813-.725 2.816-.39l15.507 5.168c1.007.336 1.373 1.053.823 1.604l-.601.601c-.778.777-1.939 1.404-3.355 1.808z" fill="#7b78ff"/><path d="M133.955 172.081l12.187-3.485c1.635-.467 3.657.207 3.774 1.258l.865 7.835c.103.91-.258 1.805-1.036 2.583l-.601.601c-.55.55-1.813.725-2.817.39l-15.507-5.168c-1.006-.336-1.373-1.054-.823-1.604l.602-.601c.777-.777 1.939-1.404 3.356-1.809z" fill="#9fd2eb"/><path d="M149.915 169.853c-.116-1.051-2.138-1.725-3.773-1.258l-6.91 1.977.492 4.444c.117 1.051 2.139 1.725 3.774 1.258l6.91-1.977-.493-4.444z" fill="#11429f"/><defs><filter id="filter0_f" x="-32" y="200" width="355" height="239" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur stdDeviation="35" result="effect1_foregroundBlur"/></filter><linearGradient id="background" x1="273.47" y1="-13.2813" x2="415.619" y2="339.655" gradientUnits="userSpaceOnUse"><stop stop-color="#0B0B16"/><stop offset="1" class="G"/></linearGradient><linearGradient id="divider" x1="1.47345e-06" y1="409" x2="298.995" y2="410.864" gradientUnits="userSpaceOnUse"><stop class="I"/><stop offset="0.5" class="J"/><stop offset="1" class="I"/></linearGradient><clipPath id="mainclip"><rect width="290" height="500" rx="20" fill="white"/></clipPath><path id="text-path-a" d="M40 10 h228 a12,12 0 0 1 12 12 v364 a12,12 0 0 1 -12 12 h-246 a12 12 0 0 1 -12 -12 v-364 a12 12 0 0 1 12 -12 z" /><path id="B" d="M124 306.844c6.075 0 11-2.879 11-6.423v3.158c0 3.544-4.925 6.421-11 6.421s-11-2.877-11-6.421v-3.158c0 3.544 4.926 6.423 11 6.423z"/><path id="C" d="M132.227 300.422c0 2.653-3.688 4.803-8.228 4.803s-8.218-2.15-8.218-4.803 3.678-4.803 8.218-4.803 8.228 2.15 8.228 4.803z"/><path id="D" d="M126.512 299.01l2.782.504c.466.081.565.44.171.603l-2.379.97c-.152.064-.25.172-.242.28l.046 1.691c0 .278-.548.44-.942.27l-2.342-.99c-.169-.073-.357-.092-.538-.054l-2.755.539c-.466.09-.898-.17-.754-.431l.898-1.601c.03-.053.038-.115.023-.174s-.052-.11-.103-.141l-1.75-1.349c-.296-.233 0-.549.476-.549h2.915c.173.005.342-.045.485-.143l1.677-1.367a.8.8 0 0 1 .538-.147.81.81 0 0 1 .504.237l.897 1.619a.57.57 0 0 0 .395.233h-.002z"/><path id="E" d="M165 304.844c6.074 0 11-2.879 11-6.423v3.158c0 3.544-4.926 6.421-11 6.421s-11-2.877-11-6.421v-3.158c0 3.544 4.926 6.423 11 6.423z"/><path id="F" d="M173.227 298.422c0 2.653-3.687 4.803-8.227 4.803s-8.218-2.15-8.218-4.803 3.678-4.803 8.218-4.803 8.227 2.15 8.227 4.803z"/></defs></svg>'
            )
        );

        return svg;
    }
}

File 69 of 75 : LendMath.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {Math} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/Math.sol';
import {SquareRoot} from './SquareRoot.sol';
import {FullMath} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/FullMath.sol';
import {ConstantProduct} from './ConstantProduct.sol';
import {SafeCast} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/SafeCast.sol';

library LendMath {
    using Math for uint256;
    using SquareRoot for uint256;
    using FullMath for uint256;
    using ConstantProduct for IPair;
    using ConstantProduct for ConstantProduct.CP;
    using SafeCast for uint256;

    uint256 private constant BASE = 0x10000000000;

    function givenBond(
        IPair pair,
        uint256 maturity,
        uint112 assetIn,
        uint128 bondOut
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yDecrease,
            uint112 zDecrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);
        xIncrease = getX(pair, maturity, assetIn);
        uint256 xReserve = cp.x;
        xReserve += xIncrease;
        uint256 _yDecrease = bondOut;
        _yDecrease -= xIncrease;
        _yDecrease <<= 32;
        uint256 denominator = maturity;
        denominator -= block.timestamp;
        _yDecrease = _yDecrease.divUp(denominator);
        yDecrease = _yDecrease.toUint112();
        uint256 yReserve = cp.y;
        yReserve -= _yDecrease;
        uint256 zReserve = cp.x;
        zReserve *= cp.y;
        denominator = xReserve;
        denominator *= yReserve;
        zReserve = zReserve.mulDivUp(cp.z, denominator);
        uint256 _zDecrease = cp.z;
        _zDecrease -= zReserve;
        zDecrease = _zDecrease.toUint112();
    }

    function givenInsurance(
        IPair pair,
        uint256 maturity,
        uint112 assetIn,
        uint128 insuranceOut
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yDecrease,
            uint112 zDecrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        xIncrease = getX(pair, maturity, assetIn);
        uint256 xReserve = cp.x;
        xReserve += xIncrease;

        uint256 _zDecrease = insuranceOut;
        _zDecrease++;
        _zDecrease *= xReserve;
        uint256 subtrahend = cp.z;
        subtrahend *= xIncrease;
        _zDecrease -= subtrahend;
        _zDecrease <<= 25;
        uint256 denominator = maturity;
        denominator -= block.timestamp;
        denominator *= xReserve;
        _zDecrease = _zDecrease.divUp(denominator);
        zDecrease = _zDecrease.toUint112();

        uint256 zReserve = cp.z;
        zReserve -= _zDecrease;

        uint256 yReserve = cp.x;
        yReserve *= cp.z;
        denominator = xReserve;
        denominator *= zReserve;
        yReserve = yReserve.mulDivUp(cp.y, denominator);

        uint256 _yDecrease = cp.y;
        _yDecrease -= yReserve;
        yDecrease = _yDecrease.toUint112();
    }

    function givenPercent(
        IPair pair,
        uint256 maturity,
        uint112 assetIn,
        uint40 percent
    )
        internal
        view
        returns (
            uint112 xIncrease,
            uint112 yDecrease,
            uint112 zDecrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        xIncrease = getX(pair, maturity, assetIn);

        uint256 xReserve = cp.x;
        xReserve += xIncrease;

        if (percent <= 0x80000000) {
            uint256 yMin = xIncrease;
            yMin *= cp.y;
            yMin /= xReserve;
            yMin >>= 4;

            uint256 yMid = cp.y;
            uint256 subtrahend = cp.y;
            subtrahend *= cp.y;
            subtrahend = subtrahend.mulDivUp(cp.x, xReserve);
            subtrahend = subtrahend.sqrtUp();
            yMid -= subtrahend;

            uint256 _yDecrease = yMid;
            _yDecrease -= yMin;
            _yDecrease *= percent;
            _yDecrease >>= 31;
            _yDecrease += yMin;
            yDecrease = _yDecrease.toUint112();

            uint256 yReserve = cp.y;
            yReserve -= _yDecrease;

            uint256 zReserve = cp.x;
            zReserve *= cp.y;
            uint256 denominator = xReserve;
            denominator *= yReserve;
            zReserve = zReserve.mulDivUp(cp.z, denominator);

            uint256 _zDecrease = cp.z;
            _zDecrease -= zReserve;
            zDecrease = _zDecrease.toUint112();
        } else {
            percent = 0x100000000 - percent;

            uint256 zMid = cp.z;
            uint256 subtrahend = cp.z;
            subtrahend *= cp.z;
            subtrahend = subtrahend.mulDivUp(cp.x, xReserve);
            subtrahend = subtrahend.sqrtUp();
            zMid -= subtrahend;

            uint256 _zDecrease = zMid;
            _zDecrease *= percent;
            _zDecrease >>= 31;
            zDecrease = _zDecrease.toUint112();

            uint256 zReserve = cp.z;
            zReserve -= _zDecrease;

            uint256 yReserve = cp.x;
            yReserve *= cp.z;
            uint256 denominator = xReserve;
            denominator *= zReserve;
            yReserve = yReserve.mulDivUp(cp.y, denominator);

            uint256 _yDecrease = cp.y;
            _yDecrease -= yReserve;
            yDecrease = _yDecrease.toUint112();
        }
    }

    function getX(
        IPair pair,
        uint256 maturity,
        uint112 assetIn
    ) private view returns (uint112 xIncrease) {
        uint256 totalFee = pair.fee();
        totalFee += pair.protocolFee();

        uint256 denominator = maturity;
        denominator -= block.timestamp;
        denominator *= totalFee;
        denominator += BASE;

        uint256 _xIncrease = assetIn;
        _xIncrease *= BASE;
        _xIncrease /= denominator;
        xIncrease = _xIncrease.toUint112();
    }
}

File 70 of 75 : SquareRoot.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity =0.8.4;

library SquareRoot {
    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 x) internal pure returns (uint256 y) {
        uint256 z = (x + 1) >> 1;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) >> 1;
        }
    }

    function sqrtUp(uint256 x) internal pure returns (uint256 y) {
        y = sqrt(x);
        if (x % y != 0) y++;
    }
}

File 71 of 75 : FullMath.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;

library FullMath {
    function mul512(uint256 a, uint256 b) internal pure returns (uint256 prod0, uint256 prod1) {
        // 512-bit multiply [prod1 prod0] = a * b
        // Compute the product mod 2**256 and mod 2**256 - 1
        // then use the Chinese Remainder Theorem to reconstruct
        // the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2**256 + prod0
        assembly {
            let mm := mulmod(a, b, not(0))
            prod0 := mul(a, b)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }
    }
    
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            (uint256 prod0, uint256 prod1) = mul512(a, b);

            // Handle non-overflow cases, 256 by 256 division
            if (prod1 == 0) {
                require(denominator != 0);
                assembly {
                    result := div(prod0, denominator)
                }
                return result;
            }

            // Make sure the result is less than 2**256.
            // Also prevents denominator == 0
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0]
            // Compute remainder using mulmod
            uint256 remainder;
            assembly {
                remainder := mulmod(a, b, denominator)
            }
            // Subtract 256 bit number from 512 bit number
            assembly {
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator
            // Compute largest power of two divisor of denominator.
            // Always >= 1.
            uint256 twos;
            twos = (0 - denominator) & denominator;
            // Divide denominator by power of two
            assembly {
                denominator := div(denominator, twos)
            }

            // Divide [prod1 prod0] by the factors of two
            assembly {
                prod0 := div(prod0, twos)
            }
            // Shift in bits from prod1 into prod0. For this we need
            // to flip `twos` such that it is 2**256 / twos.
            // If twos is zero, then it becomes one
            assembly {
                twos := add(div(sub(0, twos), twos), 1)
            }
            prod0 |= prod1 * twos;    

            // Invert denominator mod 2**256
            // Now that denominator is an odd number, it has an inverse
            // modulo 2**256 such that denominator * inv = 1 mod 2**256.
            // Compute the inverse by starting with a seed that is correct
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
            uint256 inv;
            inv = (3 * denominator) ^ 2;

            // Now use Newton-Raphson iteration to improve the precision.
            // Thanks to Hensel's lifting lemma, this also works in modular
            // arithmetic, doubling the correct bits in each step.
            inv *= 2 - denominator * inv; // inverse mod 2**8
            inv *= 2 - denominator * inv; // inverse mod 2**16
            inv *= 2 - denominator * inv; // inverse mod 2**32
            inv *= 2 - denominator * inv; // inverse mod 2**64
            inv *= 2 - denominator * inv; // inverse mod 2**128
            inv *= 2 - denominator * inv; // inverse mod 2**256

            // Because the division is now exact we can divide by multiplying
            // with the modular inverse of denominator. This will give us the
            // correct result modulo 2**256. Since the precoditions guarantee
            // that the outcome is less than 2**256, this is the final result.
            // We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inv;

            return result;
        }
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        result = mulDiv(a, b, denominator);
        if (mulmod(a, b, denominator) != 0) result++;
    }
}

File 72 of 75 : BorrowMath.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {Math} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/Math.sol';
import {SquareRoot} from './SquareRoot.sol';
import {FullMath} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/FullMath.sol';
import {ConstantProduct} from './ConstantProduct.sol';
import {SafeCast} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/SafeCast.sol';

library BorrowMath {
    using Math for uint256;
    using SquareRoot for uint256;
    using FullMath for uint256;
    using ConstantProduct for IPair;
    using ConstantProduct for ConstantProduct.CP;
    using SafeCast for uint256;

    uint256 private constant BASE = 0x10000000000;

    function givenDebt(
        IPair pair,
        uint256 maturity,
        uint112 assetOut,
        uint112 debtIn
    )
        internal
        view
        returns (
            uint112 xDecrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        xDecrease = getX(pair, maturity, assetOut);
        uint256 xReserve = cp.x;
        xReserve -= xDecrease;
        uint256 _yIncrease = debtIn;
        _yIncrease -= xDecrease;
        _yIncrease <<= 32;
        uint256 denominator = maturity;
        denominator -= block.timestamp;

        _yIncrease /= denominator;
        yIncrease = _yIncrease.toUint112();

        uint256 yReserve = cp.y;
        yReserve += _yIncrease;

        uint256 zReserve = cp.x;
        zReserve *= cp.y;

        denominator = xReserve;
        denominator *= yReserve;
        zReserve = zReserve.mulDivUp(cp.z, denominator);

        uint256 _zIncrease = zReserve;
        _zIncrease -= cp.z;
        zIncrease = _zIncrease.toUint112();
    }

    function givenCollateral(
        IPair pair,
        uint256 maturity,
        uint112 assetOut,
        uint112 collateralIn
    )
        internal
        view
        returns (
            uint112 xDecrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        xDecrease = getX(pair, maturity, assetOut);

        uint256 xReserve = cp.x;
        xReserve -= xDecrease;

        uint256 _zIncrease = collateralIn;
        _zIncrease--;
        _zIncrease *= xReserve;
        uint256 subtrahend = cp.z;
        subtrahend *= xDecrease;
        _zIncrease -= subtrahend;
        _zIncrease <<= 25;
        uint256 denominator = maturity;
        denominator -= block.timestamp;
        denominator *= xReserve;
        _zIncrease /= denominator;
        zIncrease = _zIncrease.toUint112();

        uint256 zReserve = cp.z;
        zReserve += _zIncrease;

        uint256 yReserve = cp.x;
        yReserve *= cp.z;
        denominator = xReserve;
        denominator *= zReserve;
        yReserve = yReserve.mulDivUp(cp.y, denominator);

        uint256 _yIncrease = yReserve;
        _yIncrease -= cp.y;
        yIncrease = _yIncrease.toUint112();
    }

    function givenPercent(
        IPair pair,
        uint256 maturity,
        uint112 assetOut,
        uint40 percent
    )
        internal
        view
        returns (
            uint112 xDecrease,
            uint112 yIncrease,
            uint112 zIncrease
        )
    {
        ConstantProduct.CP memory cp = pair.get(maturity);

        xDecrease = getX(pair, maturity, assetOut);

        uint256 xReserve = cp.x;
        xReserve -= xDecrease;

        if (percent <= 0x80000000) {
            uint256 yMin = xDecrease;
            yMin *= cp.y;
            yMin = yMin.divUp(xReserve);
            yMin = yMin.shiftRightUp(4);

            uint256 yMid = cp.y;
            yMid *= cp.y;
            yMid = yMid.mulDivUp(cp.x, xReserve);
            yMid = yMid.sqrtUp();
            yMid -= cp.y;

            uint256 _yIncrease = yMid;
            _yIncrease -= yMin;
            _yIncrease *= percent;
            _yIncrease = _yIncrease.shiftRightUp(31);
            _yIncrease += yMin;
            yIncrease = _yIncrease.toUint112();

            uint256 yReserve = cp.y;
            yReserve += _yIncrease;

            uint256 zReserve = cp.x;
            zReserve *= cp.y;
            uint256 denominator = xReserve;
            denominator *= yReserve;
            zReserve = zReserve.mulDivUp(cp.z, denominator);

            uint256 _zIncrease = zReserve;
            _zIncrease -= cp.z;
            zIncrease = _zIncrease.toUint112();
        } else {
            percent = 0x100000000 - percent;

            uint256 zMid = cp.z;
            zMid *= cp.z;
            zMid = zMid.mulDivUp(cp.x, xReserve);
            zMid = zMid.sqrtUp();
            zMid -= cp.z;

            uint256 _zIncrease = zMid;
            _zIncrease *= percent;
            _zIncrease = _zIncrease.shiftRightUp(31);
            zIncrease = _zIncrease.toUint112();

            uint256 zReserve = cp.z;
            zReserve += _zIncrease;

            uint256 yReserve = cp.x;
            yReserve *= cp.z;
            uint256 denominator = xReserve;
            denominator *= zReserve;
            yReserve = yReserve.mulDivUp(cp.y, denominator);

            uint256 _yIncrease = yReserve;
            _yIncrease -= cp.y;
            yIncrease = _yIncrease.toUint112();
        }
    }

    function getX(
        IPair pair,
        uint256 maturity,
        uint112 assetOut
    ) private view returns (uint112 xDecrease) {
        uint256 totalFee = pair.fee();
        totalFee += pair.protocolFee();

        uint256 numerator = maturity;
        numerator -= block.timestamp;
        numerator *= totalFee;
        numerator += BASE;

        uint256 _xDecrease = assetOut;
        _xDecrease *= numerator;
        _xDecrease = _xDecrease.divUp(BASE);
        xDecrease = _xDecrease.toUint112();
    }
}

File 73 of 75 : PayMath.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity =0.8.4;

import {IPair} from '@timeswap-labs/timeswap-v1-core/contracts/interfaces/IPair.sol';
import {IDue} from '../interfaces/IDue.sol';
import {SafeCast} from '@timeswap-labs/timeswap-v1-core/contracts/libraries/SafeCast.sol';

library PayMath {
    using SafeCast for uint256;

    function givenMaxAssetsIn(
        IPair pair,
        uint256 maturity,
        IDue collateralizedDebt,
        uint256[] memory ids,
        uint112[] memory maxAssetsIn
    ) internal view returns (uint112[] memory assetsIn, uint112[] memory collateralsOut) {
        uint256 length = ids.length;

        assetsIn = maxAssetsIn;
        collateralsOut = new uint112[](length);

        for (uint256 i; i < length; ) {
            IPair.Due memory due = pair.dueOf(maturity, address(this), ids[i]);

            if (assetsIn[i] > due.debt) assetsIn[i] = due.debt;
            if (msg.sender == collateralizedDebt.ownerOf(ids[i])) {
                uint256 _collateralOut = due.collateral;
                if (due.debt != 0) {
                    _collateralOut *= assetsIn[i];
                    _collateralOut /= due.debt;
                }
                collateralsOut[i] = _collateralOut.toUint112();
            }

            unchecked {
                ++i;
            }
        }
    }
}

File 74 of 75 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.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 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'
        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) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _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
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 75 of 75 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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");

        (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");

        (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");

        (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");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal 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

                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",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Borrow.sol": {
      "Borrow": "0x8bc1633c9e37a8beffeff1c1a4db673470fa5edb"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Burn.sol": {
      "Burn": "0xeab68789d7e047498158bf8d87cefb0d8ad06962"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/DeployBonds.sol": {
      "DeployBonds": "0x40caac2b6d836c04aa754f4ff6fe420252bfd81e"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/DeployCollateralizedDebt.sol": {
      "DeployCollateralizedDebt": "0xfb06087e41a8af562a686f4ad11bf19c745c481d"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/DeployInsurances.sol": {
      "DeployInsurances": "0xe9ec30653995ce7bacb349d76d8fa376a3ea0138"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/DeployLiquidity.sol": {
      "DeployLiquidity": "0x4a1d7a326fca250e191ee552a3bc6de34d9186f2"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Lend.sol": {
      "Lend": "0xcad2609d4853938868f8d66ba777ac9bacba4a1c"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Mint.sol": {
      "Mint": "0x8eac1410049392e4542dd2810a221f4612910c48"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Pay.sol": {
      "Pay": "0x8e1f09e007701e3611a7699541d43bad5d32dc00"
    },
    "@timeswap-labs/timeswap-v1-convenience/contracts/libraries/Withdraw.sol": {
      "Withdraw": "0x52328dcfca4a0944962bf8ec8832a04daa465218"
    }
  }
}

Contract ABI

[{"inputs":[{"internalType":"contract IFactory","name":"_factory","type":"address"},{"internalType":"contract IWETH","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenCollateral","name":"params","type":"tuple"}],"name":"borrowGivenCollateral","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenCollateralETHAsset","name":"params","type":"tuple"}],"name":"borrowGivenCollateralETHAsset","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenCollateralETHCollateral","name":"params","type":"tuple"}],"name":"borrowGivenCollateralETHCollateral","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenDebt","name":"params","type":"tuple"}],"name":"borrowGivenDebt","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenDebtETHAsset","name":"params","type":"tuple"}],"name":"borrowGivenDebtETHAsset","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenDebtETHCollateral","name":"params","type":"tuple"}],"name":"borrowGivenDebtETHCollateral","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenPercent","name":"params","type":"tuple"}],"name":"borrowGivenPercent","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenPercentETHAsset","name":"params","type":"tuple"}],"name":"borrowGivenPercentETHAsset","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetOut","type":"uint112"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IBorrow.BorrowGivenPercentETHCollateral","name":"params","type":"tuple"}],"name":"borrowGivenPercentETHCollateral","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"collateralTo","type":"address"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsIn","type":"tuple"}],"internalType":"struct IWithdraw.Collect","name":"params","type":"tuple"}],"name":"collect","outputs":[{"components":[{"internalType":"uint128","name":"asset","type":"uint128"},{"internalType":"uint128","name":"collateral","type":"uint128"}],"internalType":"struct IPair.Tokens","name":"tokensOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"assetTo","type":"address"},{"internalType":"address","name":"collateralTo","type":"address"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsIn","type":"tuple"}],"internalType":"struct IWithdraw.CollectETHAsset","name":"params","type":"tuple"}],"name":"collectETHAsset","outputs":[{"components":[{"internalType":"uint128","name":"asset","type":"uint128"},{"internalType":"uint128","name":"collateral","type":"uint128"}],"internalType":"struct IPair.Tokens","name":"tokensOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address payable","name":"collateralTo","type":"address"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsIn","type":"tuple"}],"internalType":"struct IWithdraw.CollectETHCollateral","name":"params","type":"tuple"}],"name":"collectETHCollateral","outputs":[{"components":[{"internalType":"uint128","name":"asset","type":"uint128"},{"internalType":"uint128","name":"collateral","type":"uint128"}],"internalType":"struct IPair.Tokens","name":"tokensOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IDeployNatives.DeployNatives","name":"params","type":"tuple"}],"name":"deployNatives","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"}],"internalType":"struct IDeployPair.DeployPair","name":"params","type":"tuple"}],"name":"deployPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"}],"name":"getNative","outputs":[{"components":[{"internalType":"contract ILiquidity","name":"liquidity","type":"address"},{"internalType":"contract IClaim","name":"bondInterest","type":"address"},{"internalType":"contract IClaim","name":"bondPrincipal","type":"address"},{"internalType":"contract IClaim","name":"insuranceInterest","type":"address"},{"internalType":"contract IClaim","name":"insurancePrincipal","type":"address"},{"internalType":"contract IDue","name":"collateralizedDebt","type":"address"}],"internalType":"struct IConvenience.Native","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint128","name":"bondOut","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenBond","name":"params","type":"tuple"}],"name":"lendGivenBond","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint128","name":"bondOut","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenBondETHAsset","name":"params","type":"tuple"}],"name":"lendGivenBondETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint128","name":"bondOut","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenBondETHCollateral","name":"params","type":"tuple"}],"name":"lendGivenBondETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint128","name":"insuranceOut","type":"uint128"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenInsurance","name":"params","type":"tuple"}],"name":"lendGivenInsurance","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint128","name":"insuranceOut","type":"uint128"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenInsuranceETHAsset","name":"params","type":"tuple"}],"name":"lendGivenInsuranceETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint128","name":"insuranceOut","type":"uint128"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenInsuranceETHCollateral","name":"params","type":"tuple"}],"name":"lendGivenInsuranceETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenPercent","name":"params","type":"tuple"}],"name":"lendGivenPercent","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenPercentETHAsset","name":"params","type":"tuple"}],"name":"lendGivenPercentETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"bondTo","type":"address"},{"internalType":"address","name":"insuranceTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint40","name":"percent","type":"uint40"},{"internalType":"uint128","name":"minBond","type":"uint128"},{"internalType":"uint128","name":"minInsurance","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ILend.LendGivenPercentETHCollateral","name":"params","type":"tuple"}],"name":"lendGivenPercentETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"components":[{"internalType":"uint112","name":"bondPrincipal","type":"uint112"},{"internalType":"uint112","name":"bondInterest","type":"uint112"},{"internalType":"uint112","name":"insurancePrincipal","type":"uint112"},{"internalType":"uint112","name":"insuranceInterest","type":"uint112"}],"internalType":"struct IPair.Claims","name":"claimsOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenAsset","name":"params","type":"tuple"}],"name":"liquidityGivenAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenAssetETHAsset","name":"params","type":"tuple"}],"name":"liquidityGivenAssetETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenAssetETHCollateral","name":"params","type":"tuple"}],"name":"liquidityGivenAssetETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxAsset","type":"uint112"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenCollateral","name":"params","type":"tuple"}],"name":"liquidityGivenCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenCollateralETHAsset","name":"params","type":"tuple"}],"name":"liquidityGivenCollateralETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxAsset","type":"uint112"},{"internalType":"uint112","name":"maxDebt","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenCollateralETHCollateral","name":"params","type":"tuple"}],"name":"liquidityGivenCollateralETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxAsset","type":"uint112"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenDebt","name":"params","type":"tuple"}],"name":"liquidityGivenDebt","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxCollateral","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenDebtETHAsset","name":"params","type":"tuple"}],"name":"liquidityGivenDebtETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint256","name":"minLiquidity","type":"uint256"},{"internalType":"uint112","name":"maxAsset","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.LiquidityGivenDebtETHCollateral","name":"params","type":"tuple"}],"name":"liquidityGivenDebtETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.NewLiquidity","name":"params","type":"tuple"}],"name":"newLiquidity","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.NewLiquidityETHAsset","name":"params","type":"tuple"}],"name":"newLiquidityETHAsset","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"liquidityTo","type":"address"},{"internalType":"address","name":"dueTo","type":"address"},{"internalType":"uint112","name":"assetIn","type":"uint112"},{"internalType":"uint112","name":"debtIn","type":"uint112"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IMint.NewLiquidityETHCollateral","name":"params","type":"tuple"}],"name":"newLiquidityETHCollateral","outputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint256","name":"liquidityOut","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint112","name":"debt","type":"uint112"},{"internalType":"uint112","name":"collateral","type":"uint112"},{"internalType":"uint32","name":"startBlock","type":"uint32"}],"internalType":"struct IPair.Due","name":"dueOut","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address","name":"collateralTo","type":"address"},{"internalType":"uint256","name":"liquidityIn","type":"uint256"}],"internalType":"struct IBurn.RemoveLiquidity","name":"params","type":"tuple"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"assetTo","type":"address"},{"internalType":"address","name":"collateralTo","type":"address"},{"internalType":"uint256","name":"liquidityIn","type":"uint256"}],"internalType":"struct IBurn.RemoveLiquidityETHAsset","name":"params","type":"tuple"}],"name":"removeLiquidityETHAsset","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"address payable","name":"collateralTo","type":"address"},{"internalType":"uint256","name":"liquidityIn","type":"uint256"}],"internalType":"struct IBurn.RemoveLiquidityETHCollateral","name":"params","type":"tuple"}],"name":"removeLiquidityETHCollateral","outputs":[{"internalType":"uint256","name":"assetOut","type":"uint256"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"collateralTo","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint112[]","name":"maxAssetsIn","type":"uint112[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IPay.Repay","name":"params","type":"tuple"}],"name":"repay","outputs":[{"internalType":"uint128","name":"assetIn","type":"uint128"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"collateral","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"collateralTo","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint112[]","name":"maxAssetsIn","type":"uint112[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IPay.RepayETHAsset","name":"params","type":"tuple"}],"name":"repayETHAsset","outputs":[{"internalType":"uint128","name":"assetIn","type":"uint128"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address payable","name":"collateralTo","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint112[]","name":"maxAssetsIn","type":"uint112[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IPay.RepayETHCollateral","name":"params","type":"tuple"}],"name":"repayETHCollateral","outputs":[{"internalType":"uint128","name":"assetIn","type":"uint128"},{"internalType":"uint128","name":"collateralOut","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"timeswapBorrowCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"timeswapLendCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetIn","type":"uint256"},{"internalType":"uint112","name":"collateralIn","type":"uint112"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"timeswapMintCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"assetIn","type":"uint128"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"timeswapPayCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c06040523480156200001157600080fd5b5060405162004cb038038062004cb083398101604081905262000034916200012b565b6001600160a01b0382166200007e5760405162461bcd60e51b815260040162000075906020808252600490820152634536303160e01b604082015260600190565b60405180910390fd5b6001600160a01b038116620000bf5760405162461bcd60e51b815260040162000075906020808252600490820152634536303160e01b604082015260600190565b806001600160a01b0316826001600160a01b031614156200010c5760405162461bcd60e51b81526004016200007590602080825260049082015263229b189960e11b604082015260600190565b6001600160601b0319606092831b8116608052911b1660a05262000182565b600080604083850312156200013e578182fd5b82516200014b8162000169565b60208401519092506200015e8162000169565b809150509250929050565b6001600160a01b03811681146200017f57600080fd5b50565b60805160601c60a05160601c61491862000398600039600081816102a7015281816104b701528181610bba01528181610c8301528181610f0001528181610fff0152818161109d01528181611127015281816112ad0152818161133f015281816113df0152818161157701528181611671015281816117b20152818161185001528181611942015281816119e201528181611a8001528181611b7101528181611c1101528181611cd401528181611d7401528181611de001528181611f0f01528181611fae0152818161204c015281816120ec015281816121960152612466015260008181610768015281816109be01528181610ac201528181610b9801528181610c6201528181610d9c01528181610e0c01528181610ede01528181610fdd0152818161107b01528181611105015281816111a5015281816112230152818161128b0152818161131d015281816113bd0152818161145b015281816114d701528181611555015281816115df0152818161164f01528181611728015281816117900152818161182e015281816118b801528181611920015281816119c001528181611a5e01528181611b4f01528181611bef01528181611cb201528181611d5201528181611dbf01528181611e4001528181611eee01528181611f8c0152818161202a015281816120ca0152818161211e015281816121750152818161222901528181612274015261239401526149186000f3fe6080604052600436106102975760003560e01c8063989e6ecb1161015a578063d01f7648116100c1578063ea678f101161007a578063ea678f10146108a6578063edb1fd74146108b9578063f6d0e515146108d9578063f865f571146108f9578063f8f808a114610919578063f9713d131461093957600080fd5b8063d01f7648146107fd578063d3d841b914610810578063e3af0a7b14610823578063e6478aad14610860578063e76a364e14610880578063e912bab11461089357600080fd5b8063c317bf6111610113578063c317bf6114610736578063c45a015514610756578063c59749b81461078a578063c5dfe8ad146107aa578063c70449bf146107bd578063cd346d4e146107dd57600080fd5b8063989e6ecb1461069d5780639f4f7e74146106bd578063a60d0716146106dd578063ab2f9aa0146106fd578063ac22302414610710578063bd242f1b1461072357600080fd5b80635ca2fda4116101fe57806378fbbe8f116101b757806378fbbe8f146105ea5780637908ff531461060a5780637f8507c11461061d5780638f8f1e1f1461063d57806390e4d0b11461065d578063962d185a1461067d57600080fd5b80635ca2fda4146105375780635e1162021461055757806365a21b3c146105775780636cfae9b1146105975780636f1f5a28146105b757806375ef4638146105ca57600080fd5b80632e7faba5116102505780632e7faba51461043b5780632ebd869f146104825780633fc8cef3146104a5578063436179c8146104f15780634747fb7014610504578063483e67931461052457600080fd5b806307e8d6a31461030d57806311993d6a1461032d578063145bad6e146103995780631a6ec168146103bb5780631ac6082d146103fb5780632cdb7da91461041b57600080fd5b3661030857336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103065760405162461bcd60e51b81526004016102fd906020808252600490820152634536313560e01b604082015260600190565b60405180910390fd5b005b600080fd5b34801561031957600080fd5b506103066103283660046130f8565b6109b4565b34801561033957600080fd5b5061034d61034836600461302f565b610a84565b6040805192835281516001600160701b039081166020808601919091528301518116848301529082015181166060808501919091529091015116608082015260a0015b60405180910390f35b6103ac6103a7366004613014565b610b46565b60405161039093929190614707565b3480156103c757600080fd5b506103db6103d636600461313f565b610c41565b604080516001600160801b03938416815292909116602083015201610390565b34801561040757600080fd5b506103066104163660046132ba565b610d11565b34801561042757600080fd5b506103ac61043636600461302f565b610d4a565b34801561044757600080fd5b5061045b61045636600461302f565b610dc6565b6040805182516001600160801b039081168252602093840151169281019290925201610390565b610495610490366004613014565b610e8b565b6040516103909493929190614749565b3480156104b157600080fd5b506104d97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610390565b6104956104ff366004612ff8565b610f89565b34801561051057600080fd5b506103ac61051f366004612ff8565b611029565b61034d610532366004612ff8565b6110c7565b34801561054357600080fd5b5061049561055236600461304b565b611151565b34801561056357600080fd5b5061049561057236600461304b565b6111cf565b34801561058357600080fd5b5061034d61059236600461302f565b61124d565b3480156105a357600080fd5b5061045b6105b2366004612ff8565b6112d7565b6104956105c5366004612ff8565b611369565b3480156105d657600080fd5b506103ac6105e536600461304b565b611409565b3480156105f657600080fd5b506103ac61060536600461302f565b611485565b610495610618366004612ff8565b611501565b34801561062957600080fd5b5061034d61063836600461304b565b6115a1565b34801561064957600080fd5b5061045b610658366004612ff8565b611609565b34801561066957600080fd5b5061030661067836600461320f565b61169b565b34801561068957600080fd5b5061049561069836600461304b565b6116d4565b3480156106a957600080fd5b5061034d6106b8366004612ff8565b611752565b3480156106c957600080fd5b506103ac6106d8366004612ff8565b6117dc565b3480156106e957600080fd5b5061034d6106f836600461302f565b61187a565b61034d61070b366004613014565b6118e2565b61049561071e366004612ff8565b61196c565b6103ac610731366004612ff8565b611a0c565b34801561074257600080fd5b5061030661075136600461339a565b611aaa565b34801561076257600080fd5b506104d97f000000000000000000000000000000000000000000000000000000000000000081565b34801561079657600080fd5b506103ac6107a536600461302f565b611afd565b6104956107b8366004613014565b611b9b565b3480156107c957600080fd5b506103066107d8366004613262565b611c3b565b3480156107e957600080fd5b5061034d6107f8366004612ff8565b611c74565b61049561080b366004612ff8565b611cfe565b6103db61081e36600461313f565b611d9e565b34801561082f57600080fd5b5061084361083e366004613124565b611e1f565b604080519283526001600160801b03909116602083015201610390565b34801561086c57600080fd5b5061084361087b366004613109565b611ecd565b61034d61088e366004613014565b611f4e565b6103ac6108a1366004613014565b611fd8565b6104956108b4366004612ff8565b612076565b3480156108c557600080fd5b506103066108d4366004613067565b612116565b3480156108e557600080fd5b506108436108f4366004613109565b612154565b34801561090557600080fd5b5061049561091436600461302f565b6121d5565b34801561092557600080fd5b506103db610934366004613172565b612253565b34801561094557600080fd5b50610959610954366004612f9c565b6122b2565b604051610390919081516001600160a01b03908116825260208084015182169083015260408084015182169083015260608084015182169083015260808084015182169083015260a092830151169181019190915260c00190565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663c9c653966109f06020840184612edb565b610a006040850160208601612edb565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b158015610a4857600080fd5b505af1158015610a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a809190612fdc565b5050565b6000610a8e612d17565b604051636f862bef60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90636f862bef90610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000908990600401614563565b60a06040518083038186803b158015610b0457600080fd5b505af4158015610b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c91906132eb565b9094909350915050565b60408051606081018252600080825260208201819052918101829052819060405163edecda4560e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063edecda4590610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b90600401613f60565b60a06040518083038186803b158015610bfc57600080fd5b505af4158015610c10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c349190613418565b9196909550909350915050565b600080738e1f09e007701e3611a7699541d43bad5d32dc00636cefc79f60007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000876040518563ffffffff1660e01b8152600401610cc29493929190613c7d565b604080518083038186803b158015610cd957600080fd5b505af4158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c9190613281565b60008080610d2184860186612ef7565b9250925092506000610d33848461236a565b9050610d418483838a612453565b50505050505050565b60408051606081018252600080825260208201819052918101829052819060405163334b723f60e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063334b723f90610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614418565b6040805180820190915260008082526020820152604051634a0f623d60e01b81527352328dcfca4a0944962bf8ec8832a04daa46521890634a0f623d90610e36906000907f0000000000000000000000000000000000000000000000000000000000000000908790600401613d3e565b604080518083038186803b158015610e4d57600080fd5b505af4158015610e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8591906131a5565b92915050565b6040805160608101825260008082526020820181905291810182905281908190604051623ea4ed60e71b8152738eac1410049392e4542dd2810a221f4612910c4890631f52768090610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c90600401613f60565b60c06040518083038186803b158015610f4257600080fd5b505af4158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061344d565b92989197509550909350915050565b604080516060810182526000808252602082018190529181018290528190819060405163bec850cd60e01b8152738eac1410049392e4542dd2810a221f4612910c489063bec850cd90610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143e4565b604080516060810182526000808252602082018190529181018290528190604051630ed88ad160e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb90631db115a290610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b90600401613f22565b60006110d1612d17565b6040516310d2b20960e31b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90638695904890610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a906004016141e8565b60408051606081018252600080825260208201819052918101829052819081906040516358e7653960e01b8152738eac1410049392e4542dd2810a221f4612910c48906358e7653990610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000908b9060040161469c565b6040805160608101825260008082526020820181905291810182905281908190604051637c66e3c960e01b8152738eac1410049392e4542dd2810a221f4612910c4890637c66e3c990610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000908b9060040161469c565b6000611257612d17565b604051632724931160e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90632724931190610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a906004016142bb565b60408051808201909152600080825260208201526040516325e1fad560e11b81527352328dcfca4a0944962bf8ec8832a04daa46521890634bc3f5aa90610e36906000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908890600401613b8d565b60408051606081018252600080825260208201819052918101829052819081906040516305f0de5360e41b8152738eac1410049392e4542dd2810a221f4612910c4890635f0de53090610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143e4565b6040805160608101825260008082526020820181905291810182905281906040516334af324960e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906334af324990610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614444565b604080516060810182526000808252602082018190529181018290528190604051636cd495a760e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063d9a92b4e90610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614418565b604080516060810182526000808252602082018190529181018290528190819060405163cfb26f8360e01b8152738eac1410049392e4542dd2810a221f4612910c489063cfb26f8390610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143e4565b60006115ab612d17565b60405163e5fa4c4b60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063e5fa4c4b90610aec9060009030907f000000000000000000000000000000000000000000000000000000000000000090899060040161458f565b604080518082019091526000808252602082015260405163f297754960e01b81527352328dcfca4a0944962bf8ec8832a04daa4652189063f297754990610e36906000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908890600401613b8d565b600080806116ab84860186612ef7565b92509250925060006116bd848461236a565b9050610d418383838a6001600160701b0316612453565b604080516060810182526000808252602082018190529181018290528190819060405163c50af1eb60e01b8152738eac1410049392e4542dd2810a221f4612910c489063c50af1eb90610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000908b9060040161469c565b600061175c612d17565b604051638ba21e1d60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90638ba21e1d90610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a906004016141b4565b6040805160608101825260008082526020820181905291810182905281906040516363ff145d60e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063c7fe28ba90610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b90600401613f22565b6000611884612d17565b604051630dcef2ed60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90630dcef2ed90610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000908990600401614563565b60006118ec612d17565b604051630d07304f60e31b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90636839827890610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614180565b60408051606081018252600080825260208201819052918101829052819081906040516317ab7b9b60e21b8152738eac1410049392e4542dd2810a221f4612910c4890635eadee6c90610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143e4565b604080516060810182526000808252602082018190529181018290528190604051631954f75160e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906332a9eea290610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b9060040161409b565b6000808080611abb85870187612f41565b93509350935093506000611acf858561236a565b9050611add8584838c612453565b611af28483838b6001600160701b0316612453565b505050505050505050565b6040805160608101825260008082526020820181905291810182905281906040516359a29a5960e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906359a29a5990610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b90600401613f94565b60408051606081018252600080825260208201819052918101829052819081906040516315d2b52760e01b8152738eac1410049392e4542dd2810a221f4612910c48906315d2b52790610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c90600401613f60565b60008080611c4b84860186612ef7565b9250925092506000611c5d848461236a565b9050610d418483838a6001600160801b0316612453565b6000611c7e612d17565b60405163fb3cc8ed60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063fb3cc8ed90610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a906004016141b4565b604080516060810182526000808252602082018190529181018290528190819060405163eeb09e5d60e01b8152738eac1410049392e4542dd2810a221f4612910c489063eeb09e5d90610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143b0565b600080738e1f09e007701e3611a7699541d43bad5d32dc006358de0b2060007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000876040518563ffffffff1660e01b8152600401610cc29493929190613c7d565b60008073eab68789d7e047498158bf8d87cefb0d8ad069626380fbc4ad60007f0000000000000000000000000000000000000000000000000000000000000000866040518463ffffffff1660e01b8152600401611e7e93929190613dc3565b604080518083038186803b158015611e9557600080fd5b505af4158015611ea9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c91906133f4565b60008073eab68789d7e047498158bf8d87cefb0d8ad0696263ef2797a260007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000876040518563ffffffff1660e01b8152600401611e7e9493929190613c03565b6000611f58612d17565b6040516330cd441d60e21b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063c335107490610aec9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401614180565b60408051606081018252600080825260208201819052918101829052819060405163f777ff6760e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063f777ff6790610be49060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908b90600401613f60565b6040805160608101825260008082526020820181905291810182905281908190604051637e7a8aeb60e01b8152738eac1410049392e4542dd2810a221f4612910c4890637e7a8aeb90610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908c906004016143b0565b6121516000307f000000000000000000000000000000000000000000000000000000000000000061214c36869003860186613078565b61250e565b50565b60008073eab68789d7e047498158bf8d87cefb0d8ad0696263b4cb373260007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000876040518563ffffffff1660e01b8152600401611e7e9493929190613c03565b604080516060810182526000808252602082018190529181018290528190819060405163b1d7966960e01b8152738eac1410049392e4542dd2810a221f4612910c489063b1d7966990610f2a9060009030907f0000000000000000000000000000000000000000000000000000000000000000908b90600401614418565b600080738e1f09e007701e3611a7699541d43bad5d32dc006336b4aeec60007f0000000000000000000000000000000000000000000000000000000000000000866040518463ffffffff1660e01b8152600401610cc293929190613e4b565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506001600160a01b0380841660009081526020818152604080832086851684528252808320858452825291829020825160c0810184528154851681526001820154851692810192909252600281015484169282019290925260038201548316606082015260048201548316608082015260059091015490911660a08201525b9392505050565b60405163e6a4390560e01b81526001600160a01b03838116600483015282811660248301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a439059060440160206040518083038186803b1580156123d857600080fd5b505afa1580156123ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124109190612fdc565b9050336001600160a01b03821614610e855760405162461bcd60e51b81526004016102fd906020808252600490820152634537303160e01b604082015260600190565b6001600160a01b0383163014156124f3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156124bf57600080fd5b505af11580156124d3573d6000803e3d6000fd5b506124ee935050506001600160a01b038616905083836126ab565b612508565b6125086001600160a01b0385168484846126c4565b50505050565b428160600151101561254b5760405162461bcd60e51b81526004016102fd90602080825260049082015263114d4c0d60e21b604082015260600190565b8051602082015160405163e6a4390560e01b81526001600160a01b039283166004820152908216602482015260009184169063e6a439059060440160206040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d69190612fdc565b90506001600160a01b0381166126175760405162461bcd60e51b81526004016102fd906020808252600490820152634535303160e01b604082015260600190565b81516001600160a01b039081166000908152602087815260408083208287015185168452825280832081870151845290915290208054909116156126865760405162461bcd60e51b81526004016102fd906020808252600490820152634535303360e01b604082015260600190565b8251602084015160408501516126a39284928992879291906126d9565b505050505050565b6126bf6001600160a01b0384168383612974565b505050565b6125086001600160a01b0385168484846129d7565b600083836126e684612a0f565b6040516020016126f893929190613b58565b60408051601f19818403018152908290528051602090910120630271028160e41b82529150734a1d7a326fca250e191ee552a3bc6de34d9186f29063271028109061274f908a9085908b908b9089906004016146db565b60006040518083038186803b15801561276757600080fd5b505af415801561277b573d6000803e3d6000fd5b50506040516319618ee560e21b81527340caac2b6d836c04aa754f4ff6fe420252bfd81e92506365863b9491506127be908a9085908b908b9089906004016146db565b60006040518083038186803b1580156127d657600080fd5b505af41580156127ea573d6000803e3d6000fd5b5050604051633aa4a34f60e01b815273e9ec30653995ce7bacb349d76d8fa376a3ea01389250633aa4a34f915061282d908a9085908b908b9089906004016146db565b60006040518083038186803b15801561284557600080fd5b505af4158015612859573d6000803e3d6000fd5b50506040516333bba79f60e11b815273fb06087e41a8af562a686f4ad11bf19c745c481d92506367774f3e915061289c908a9085908b908b9089906004016146db565b60006040518083038186803b1580156128b457600080fd5b505af41580156128c8573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f93a4226e499fc5f28e8d401847de401ce2cf454fc1dd52734bf5b606f6616532848a60405161296392919091825280546001600160a01b0390811660208401526001820154811660408401526002820154811660608401526003820154811660808401526004820154811660a08401526005909101541660c082015260e00190565b60405180910390a350505050505050565b6040516001600160a01b0383166024820152604481018290526126bf90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b31565b6040516001600160a01b03808516602483015283166044820152606481018290526125089085906323b872dd60e01b906084016129a0565b606081612a335750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612a5d5780612a4781614848565b9150612a569050600a836147f1565b9150612a37565b60008167ffffffffffffffff811115612a8657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612ab0576020820181803683370190505b5090505b8415612b2957612ac5600183614805565b9150612ad2600a86614863565b612add9060306147d9565b60f81b818381518110612b0057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612b22600a866147f1565b9450612ab4565b949350505050565b6000612b86826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c039092919063ffffffff16565b8051909150156126bf5780806020019051810190612ba49190612ebb565b6126bf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102fd565b6060612b298484600085856001600160a01b0385163b612c655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102fd565b600080866001600160a01b03168587604051612c819190613b3c565b60006040518083038185875af1925050503d8060008114612cbe576040519150601f19603f3d011682016040523d82523d6000602084013e612cc3565b606091505b5091509150612cd3828286612cde565b979650505050505050565b60608315612ced575081612363565b825115612cfd5782518084602001fd5b8160405162461bcd60e51b81526004016102fd91906146c8565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8035612d49816148a3565b919050565b60008083601f840112612d5f578182fd5b50813567ffffffffffffffff811115612d76578182fd5b602083019150836020828501011115612d8e57600080fd5b9250929050565b60006101008284031215612da7578081fd5b50919050565b600060e08284031215612da7578081fd5b60006101208284031215612da7578081fd5b60006101408284031215612da7578081fd5b600060608284031215612df3578081fd5b6040516060810181811067ffffffffffffffff82111715612e2257634e487b7160e01b83526041600452602483fd5b80604052508091508251612e35816148b8565b81526020830151612e45816148b8565b6020820152604083015163ffffffff81168114612e6157600080fd5b6040919091015292915050565b600060a08284031215612da7578081fd5b600060c08284031215612da7578081fd5b8035612d49816148b8565b8035612d49816148cd565b803564ffffffffff81168114612d4957600080fd5b600060208284031215612ecc578081fd5b81518015158114612363578182fd5b600060208284031215612eec578081fd5b8135612363816148a3565b600080600060608486031215612f0b578182fd5b8335612f16816148a3565b92506020840135612f26816148a3565b91506040840135612f36816148a3565b809150509250925092565b60008060008060808587031215612f56578182fd5b8435612f61816148a3565b93506020850135612f71816148a3565b92506040850135612f81816148a3565b91506060850135612f91816148a3565b939692955090935050565b600080600060608486031215612fb0578081fd5b8335612fbb816148a3565b92506020840135612fcb816148a3565b929592945050506040919091013590565b600060208284031215612fed578081fd5b8151612363816148a3565b6000610100828403121561300a578081fd5b6123638383612d95565b600060e08284031215613025578081fd5b6123638383612dad565b60006101208284031215613041578081fd5b6123638383612dbe565b6000610140828403121561305d578081fd5b6123638383612dd0565b600060808284031215612da7578081fd5b600060808284031215613089578081fd5b6040516080810181811067ffffffffffffffff821117156130b857634e487b7160e01b83526041600452602483fd5b60405282356130c6816148a3565b815260208301356130d6816148a3565b6020820152604083810135908201526060928301359281019290925250919050565b600060408284031215612da7578081fd5b600060a0828403121561311a578081fd5b6123638383612e6e565b600060c08284031215613135578081fd5b6123638383612e7f565b600060208284031215613150578081fd5b813567ffffffffffffffff811115613166578182fd5b612b2984828501612e7f565b600060208284031215613183578081fd5b813567ffffffffffffffff811115613199578182fd5b612b2984828501612dad565b6000604082840312156131b6578081fd5b6040516040810181811067ffffffffffffffff821117156131e557634e487b7160e01b83526041600452602483fd5b60405282516131f3816148cd565b81526020830151613203816148cd565b60208201529392505050565b600080600060408486031215613223578081fd5b833561322e816148b8565b9250602084013567ffffffffffffffff811115613249578182fd5b61325586828701612d4e565b9497909650939450505050565b600080600060408486031215613276578081fd5b833561322e816148cd565b60008060408385031215613293578182fd5b825161329e816148cd565b60208401519092506132af816148cd565b809150509250929050565b6000806000604084860312156132ce578081fd5b83359250602084013567ffffffffffffffff811115613249578182fd5b60008082840360a08112156132fe578283fd5b835192506080601f1982011215613313578182fd5b506040516080810181811067ffffffffffffffff8211171561334357634e487b7160e01b83526041600452602483fd5b6040526020840151613354816148b8565b81526040840151613364816148b8565b60208201526060840151613377816148b8565b6040820152608084015161338a816148b8565b6060820152919491935090915050565b600080600080606085870312156133af578182fd5b8435935060208501356133c1816148b8565b9250604085013567ffffffffffffffff8111156133dc578283fd5b6133e887828801612d4e565b95989497509550505050565b60008060408385031215613406578182fd5b8251915060208301516132af816148cd565b600080600060a0848603121561342c578081fd5b83519250602084015191506134448560408601612de2565b90509250925092565b60008060008060c08587031215613462578182fd5b8451935060208501519250604085015191506134818660608701612de2565b905092959194509250565b81835260006020808501945082825b858110156134c95781356134ae816148b8565b6001600160701b03168752958201959082019060010161349b565b509495945050505050565b81835260006001600160fb1b038311156134ec578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845261352081602086016020860161481c565b601f01601f19169290920160200192915050565b803561353f816148a3565b6001600160a01b03908116835260208281013590840152604082013590613565826148a3565b908116604084015260608201359061357c826148a3565b1660608301526080810135613590816148b8565b6001600160701b031660808301526135aa60a08201612e90565b6001600160701b031660a08301526135c460c08201612e90565b6001600160701b03811660c08401525b5060e090810135910152565b80356135eb816148a3565b6001600160a01b03908116835260208281013590840152604082013590613611826148a3565b9081166040840152606082013590613628826148a3565b166060830152608081013561363c816148b8565b6001600160701b03908116608084015260a08201359061365b826148b8565b1660a083015260c090810135910152565b8035613677816148a3565b6001600160a01b031682526020810135613690816148a3565b6001600160a01b03166020830152604081810135908301526136b460608201612d3e565b6001600160a01b031660608301526136ce60808201612d3e565b6001600160a01b031660808301526136e860a08201612e90565b6001600160701b031660a083015261370260c08201612e90565b6001600160701b031660c083015261371c60e08201612e90565b6001600160701b03811660e08401525b5061010090810135910152565b8035613744816148b8565b6001600160701b039081168352602082013590613760826148b8565b9081166020840152604082013590613777826148b8565b908116604084015260608201359061378e826148b8565b808216606085015250505050565b80356137a7816148a3565b6001600160a01b039081168352602082810135908401526040820135906137cd826148a3565b90811660408401526060820135906137e4826148a3565b16606083015260808101356137f8816148cd565b6001600160801b03908116608084015260a08201359061365b826148cd565b8035613822816148a3565b6001600160a01b03908116835260208281013590840152604082013590613848826148a3565b908116604084015260608201359061385f826148a3565b1660608301526080810135613873816148b8565b6001600160701b0316608083015261388d60a08201612e9b565b6001600160801b031660a08301526138a760c08201612e9b565b6001600160801b03811660c08401526135d4565b80356138c6816148a3565b6001600160a01b0316825260208101356138df816148a3565b6001600160a01b031660208301526040818101359083015261390360608201612d3e565b6001600160a01b0316606083015261391d60808201612d3e565b6001600160a01b0316608083015261393760a08201612e90565b6001600160701b031660a083015261395160c08201612e9b565b6001600160801b031660c083015261396b60e08201612e9b565b6001600160801b03811660e084015261372c565b803561398a816148a3565b6001600160a01b039081168352602082810135908401526040820135906139b0826148a3565b90811660408401526060820135906139c7826148a3565b1660608301526080818101359083015260a08101356135aa816148b8565b80356139f0816148a3565b6001600160a01b03908116835260208281013590840152604082013590613a16826148a3565b9081166040840152606082013590613a2d826148a3565b1660608301526080810135613a41816148b8565b6001600160701b0316608083015260a081810135908301526135c460c08201612e90565b613a7f82613a7283612d3e565b6001600160a01b03169052565b613a8b60208201612d3e565b6001600160a01b0316602083015260408181013590830152613aaf60608201612d3e565b6001600160a01b03166060830152613ac960808201612d3e565b6001600160a01b03166080830152613ae360a08201612e90565b6001600160701b031660a083015260c08181013590830152613b0760e08201612e90565b6001600160701b031660e0830152610100613b23828201612e90565b6001600160701b03169083015261012090810135910152565b60008251613b4e81846020870161481c565b9190910192915050565b6001600160a01b03848116825283166020820152606060408201819052600090613b8490830184613508565b95945050505050565b8481526001600160a01b03848116602083015283811660408301526101608201908335613bb9816148a3565b81166060840152602084013560808401526040840135613bd8816148a3565b811660a08401526060840135613bed816148a3565b1660c0830152613b8460e0830160808501613739565b8481526001600160a01b03848116602083015283811660408301526101008201908335613c2f816148a3565b81166060840152602084013560808401526040840135613c4e816148a3565b811660a08401526060840135613c63816148a3565b1660c08301526080929092013560e0909101529392505050565b8481526001600160a01b0384811660208301528381166040830152608060608301526000908335613cad816148a3565b166080830152602083013560a0830152613cc960408401612d3e565b6001600160a01b031660c0830152613ce46060840184614791565b60c060e0850152613cfa610140850182846134d4565b915050613d0a6080850185614791565b848303607f1901610100860152613d2283828461348c565b9250505060a08401356101208401528091505095945050505050565b8381526001600160a01b0383811660208301526101608201908335613d62816148a3565b811660408401526020840135613d77816148a3565b818116606085015250604084013560808401526060840135613d98816148a3565b811660a08401526080840135613dad816148a3565b1660c0830152612b2960e0830160a08501613739565b8381526001600160a01b0383811660208301526101008201908335613de7816148a3565b811660408401526020840135613dfc816148a3565b818116606085015250604084013560808401526060840135613e1d816148a3565b811660a08401526080840135613e32816148a3565b1660c083015260a0929092013560e09091015292915050565b8381526001600160a01b03831660208201526060604082015260008235613e71816148a3565b6001600160a01b03166060830152613e8b60208401612d3e565b6001600160a01b03166080830152604083013560a0830152613eaf60608401612d3e565b6001600160a01b031660c0830152613eca6080840184614791565b60e080850152613edf610140850182846134d4565b915050613eef60a0850185614791565b848303605f1901610100860152613f0783828461348c565b9250505060c084013561012084015280915050949350505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f566080830184613534565b9695505050505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101608101613f5660808301846135e0565b8581526001600160a01b0385811660208301528481166040830152831660608201526101a08101613fcb60808301613a7285612d3e565b602083013560a0830152613fe160408401612d3e565b6001600160a01b031660c0830152613ffb60608401612d3e565b6001600160a01b031660e083015261401560808401612e90565b61010061402c818501836001600160701b03169052565b61403860a08601612ea6565b64ffffffffff8116610120860152915061405460c08601612e90565b6001600160701b038116610140860152915061407260e08601612e90565b6001600160701b03811661016086015291505b8085013561018085015250509695505050505050565b8581526001600160a01b038581166020830152848116604083015283166060820152610180810182356140cd816148a3565b6001600160a01b03166080830152602083013560a08301526140f160408401612d3e565b6001600160a01b031660c083015261410b60608401612d3e565b6001600160a01b031660e083015261412560808401612e90565b6001600160701b031661010083015261414060a08401612ea6565b64ffffffffff1661012083015261415960c08401612e90565b6001600160701b0381166101408401525b5060e08301356101608301529695505050505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101608101613f56608083018461379c565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f566080830184613817565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101823561421a816148a3565b6001600160a01b03166080830152602083013560a083015261423e60408401612d3e565b6001600160a01b031660c083015261425860608401612d3e565b6001600160a01b031660e083015261427260808401612ea6565b64ffffffffff1661010083015261428b60a08401612e9b565b6001600160801b03166101208301526142a660c08401612e9b565b6001600160801b03811661014084015261416a565b8581526001600160a01b0385811660208301528481166040830152831660608201526101a081016142f260808301613a7285612d3e565b602083013560a083015261430860408401612d3e565b6001600160a01b031660c083015261432260608401612d3e565b6001600160a01b031660e083015261433c60808401612e90565b610100614353818501836001600160701b03169052565b61435f60a08601612ea6565b64ffffffffff8116610120860152915061437b60c08601612e9b565b6001600160801b038116610140860152915061439960e08601612e9b565b6001600160801b0381166101608601529150614085565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f56608083018461397f565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f5660808301846139e5565b8481526001600160a01b038481166020830152831660408201526101808101613b84606083018461366c565b8481526001600160a01b038481166020830152831660408201526101a0810161447360608301613a7285612d3e565b61447f60208401612d3e565b6001600160a01b03166080830152604083013560a08301526144a360608401612d3e565b6001600160a01b031660c08301526144bd60808401612d3e565b6001600160a01b031660e08301526144d760a08401612e90565b6101006144ee818501836001600160701b03169052565b6144fa60c08601612ea6565b91506101206145118186018464ffffffffff169052565b61451d60e08701612e90565b6001600160701b038116610140870152925061453a828701612e90565b6001600160701b03811661016087015292505b8086013561018086015250505095945050505050565b8481526001600160a01b038481166020830152831660408201526101808101613b8460608301846138bb565b8481526001600160a01b038481166020830152831660408201526101a081016145be60608301613a7285612d3e565b6145ca60208401612d3e565b6001600160a01b03166080830152604083013560a08301526145ee60608401612d3e565b6001600160a01b031660c083015261460860808401612d3e565b6001600160a01b031660e083015261462260a08401612e90565b610100614639818501836001600160701b03169052565b61464560c08601612ea6565b915061012061465c8186018464ffffffffff169052565b61466860e08701612e9b565b6001600160801b0381166101408701529250614685828701612e9b565b6001600160801b038116610160870152925061454d565b8481526001600160a01b038481166020830152831660408201526101a08101613b846060830184613a65565b6020815260006123636020830184613508565b94855260208501939093526001600160a01b039182166040850152166060830152608082015260a00190565b838152602080820184905282516001600160701b039081166040808501919091529184015116606083015282015163ffffffff16608082015260a08101612b29565b8481526020808201859052604080830185905283516001600160701b03908116606085015291840151909116608083015282015163ffffffff1660a082015260c08101613b84565b6000808335601e198436030181126147a7578283fd5b830160208101925035905067ffffffffffffffff8111156147c757600080fd5b8060051b3603831315612d8e57600080fd5b600082198211156147ec576147ec614877565b500190565b6000826148005761480061488d565b500490565b60008282101561481757614817614877565b500390565b60005b8381101561483757818101518382015260200161481f565b838111156125085750506000910152565b600060001982141561485c5761485c614877565b5060010190565b6000826148725761487261488d565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461215157600080fd5b6001600160701b038116811461215157600080fd5b6001600160801b038116811461215157600080fdfea2646970667358221220f4670042167591e845157d0c9c078b5de6c44601961c79a246a620eadd766e2764736f6c634300080400330000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732

Deployed Bytecode

0x6080604052600436106102975760003560e01c8063989e6ecb1161015a578063d01f7648116100c1578063ea678f101161007a578063ea678f10146108a6578063edb1fd74146108b9578063f6d0e515146108d9578063f865f571146108f9578063f8f808a114610919578063f9713d131461093957600080fd5b8063d01f7648146107fd578063d3d841b914610810578063e3af0a7b14610823578063e6478aad14610860578063e76a364e14610880578063e912bab11461089357600080fd5b8063c317bf6111610113578063c317bf6114610736578063c45a015514610756578063c59749b81461078a578063c5dfe8ad146107aa578063c70449bf146107bd578063cd346d4e146107dd57600080fd5b8063989e6ecb1461069d5780639f4f7e74146106bd578063a60d0716146106dd578063ab2f9aa0146106fd578063ac22302414610710578063bd242f1b1461072357600080fd5b80635ca2fda4116101fe57806378fbbe8f116101b757806378fbbe8f146105ea5780637908ff531461060a5780637f8507c11461061d5780638f8f1e1f1461063d57806390e4d0b11461065d578063962d185a1461067d57600080fd5b80635ca2fda4146105375780635e1162021461055757806365a21b3c146105775780636cfae9b1146105975780636f1f5a28146105b757806375ef4638146105ca57600080fd5b80632e7faba5116102505780632e7faba51461043b5780632ebd869f146104825780633fc8cef3146104a5578063436179c8146104f15780634747fb7014610504578063483e67931461052457600080fd5b806307e8d6a31461030d57806311993d6a1461032d578063145bad6e146103995780631a6ec168146103bb5780631ac6082d146103fb5780632cdb7da91461041b57600080fd5b3661030857336001600160a01b037f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf73216146103065760405162461bcd60e51b81526004016102fd906020808252600490820152634536313560e01b604082015260600190565b60405180910390fd5b005b600080fd5b34801561031957600080fd5b506103066103283660046130f8565b6109b4565b34801561033957600080fd5b5061034d61034836600461302f565b610a84565b6040805192835281516001600160701b039081166020808601919091528301518116848301529082015181166060808501919091529091015116608082015260a0015b60405180910390f35b6103ac6103a7366004613014565b610b46565b60405161039093929190614707565b3480156103c757600080fd5b506103db6103d636600461313f565b610c41565b604080516001600160801b03938416815292909116602083015201610390565b34801561040757600080fd5b506103066104163660046132ba565b610d11565b34801561042757600080fd5b506103ac61043636600461302f565b610d4a565b34801561044757600080fd5b5061045b61045636600461302f565b610dc6565b6040805182516001600160801b039081168252602093840151169281019290925201610390565b610495610490366004613014565b610e8b565b6040516103909493929190614749565b3480156104b157600080fd5b506104d97f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf73281565b6040516001600160a01b039091168152602001610390565b6104956104ff366004612ff8565b610f89565b34801561051057600080fd5b506103ac61051f366004612ff8565b611029565b61034d610532366004612ff8565b6110c7565b34801561054357600080fd5b5061049561055236600461304b565b611151565b34801561056357600080fd5b5061049561057236600461304b565b6111cf565b34801561058357600080fd5b5061034d61059236600461302f565b61124d565b3480156105a357600080fd5b5061045b6105b2366004612ff8565b6112d7565b6104956105c5366004612ff8565b611369565b3480156105d657600080fd5b506103ac6105e536600461304b565b611409565b3480156105f657600080fd5b506103ac61060536600461302f565b611485565b610495610618366004612ff8565b611501565b34801561062957600080fd5b5061034d61063836600461304b565b6115a1565b34801561064957600080fd5b5061045b610658366004612ff8565b611609565b34801561066957600080fd5b5061030661067836600461320f565b61169b565b34801561068957600080fd5b5061049561069836600461304b565b6116d4565b3480156106a957600080fd5b5061034d6106b8366004612ff8565b611752565b3480156106c957600080fd5b506103ac6106d8366004612ff8565b6117dc565b3480156106e957600080fd5b5061034d6106f836600461302f565b61187a565b61034d61070b366004613014565b6118e2565b61049561071e366004612ff8565b61196c565b6103ac610731366004612ff8565b611a0c565b34801561074257600080fd5b5061030661075136600461339a565b611aaa565b34801561076257600080fd5b506104d97f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b81565b34801561079657600080fd5b506103ac6107a536600461302f565b611afd565b6104956107b8366004613014565b611b9b565b3480156107c957600080fd5b506103066107d8366004613262565b611c3b565b3480156107e957600080fd5b5061034d6107f8366004612ff8565b611c74565b61049561080b366004612ff8565b611cfe565b6103db61081e36600461313f565b611d9e565b34801561082f57600080fd5b5061084361083e366004613124565b611e1f565b604080519283526001600160801b03909116602083015201610390565b34801561086c57600080fd5b5061084361087b366004613109565b611ecd565b61034d61088e366004613014565b611f4e565b6103ac6108a1366004613014565b611fd8565b6104956108b4366004612ff8565b612076565b3480156108c557600080fd5b506103066108d4366004613067565b612116565b3480156108e557600080fd5b506108436108f4366004613109565b612154565b34801561090557600080fd5b5061049561091436600461302f565b6121d5565b34801561092557600080fd5b506103db610934366004613172565b612253565b34801561094557600080fd5b50610959610954366004612f9c565b6122b2565b604051610390919081516001600160a01b03908116825260208084015182169083015260408084015182169083015260608084015182169083015260808084015182169083015260a092830151169181019190915260c00190565b6001600160a01b037f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b1663c9c653966109f06020840184612edb565b610a006040850160208601612edb565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b158015610a4857600080fd5b505af1158015610a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a809190612fdc565b5050565b6000610a8e612d17565b604051636f862bef60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90636f862bef90610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908990600401614563565b60a06040518083038186803b158015610b0457600080fd5b505af4158015610b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c91906132eb565b9094909350915050565b60408051606081018252600080825260208201819052918101829052819060405163edecda4560e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063edecda4590610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b90600401613f60565b60a06040518083038186803b158015610bfc57600080fd5b505af4158015610c10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c349190613418565b9196909550909350915050565b600080738e1f09e007701e3611a7699541d43bad5d32dc00636cefc79f60007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b7f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732876040518563ffffffff1660e01b8152600401610cc29493929190613c7d565b604080518083038186803b158015610cd957600080fd5b505af4158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c9190613281565b60008080610d2184860186612ef7565b9250925092506000610d33848461236a565b9050610d418483838a612453565b50505050505050565b60408051606081018252600080825260208201819052918101829052819060405163334b723f60e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063334b723f90610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908a90600401614418565b6040805180820190915260008082526020820152604051634a0f623d60e01b81527352328dcfca4a0944962bf8ec8832a04daa46521890634a0f623d90610e36906000907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908790600401613d3e565b604080518083038186803b158015610e4d57600080fd5b505af4158015610e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8591906131a5565b92915050565b6040805160608101825260008082526020820181905291810182905281908190604051623ea4ed60e71b8152738eac1410049392e4542dd2810a221f4612910c4890631f52768090610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c90600401613f60565b60c06040518083038186803b158015610f4257600080fd5b505af4158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061344d565b92989197509550909350915050565b604080516060810182526000808252602082018190529181018290528190819060405163bec850cd60e01b8152738eac1410049392e4542dd2810a221f4612910c489063bec850cd90610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143e4565b604080516060810182526000808252602082018190529181018290528190604051630ed88ad160e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb90631db115a290610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b90600401613f22565b60006110d1612d17565b6040516310d2b20960e31b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90638695904890610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a906004016141e8565b60408051606081018252600080825260208201819052918101829052819081906040516358e7653960e01b8152738eac1410049392e4542dd2810a221f4612910c48906358e7653990610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908b9060040161469c565b6040805160608101825260008082526020820181905291810182905281908190604051637c66e3c960e01b8152738eac1410049392e4542dd2810a221f4612910c4890637c66e3c990610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908b9060040161469c565b6000611257612d17565b604051632724931160e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90632724931190610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a906004016142bb565b60408051808201909152600080825260208201526040516325e1fad560e11b81527352328dcfca4a0944962bf8ec8832a04daa46521890634bc3f5aa90610e36906000907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908890600401613b8d565b60408051606081018252600080825260208201819052918101829052819081906040516305f0de5360e41b8152738eac1410049392e4542dd2810a221f4612910c4890635f0de53090610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143e4565b6040805160608101825260008082526020820181905291810182905281906040516334af324960e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906334af324990610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908a90600401614444565b604080516060810182526000808252602082018190529181018290528190604051636cd495a760e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063d9a92b4e90610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908a90600401614418565b604080516060810182526000808252602082018190529181018290528190819060405163cfb26f8360e01b8152738eac1410049392e4542dd2810a221f4612910c489063cfb26f8390610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143e4565b60006115ab612d17565b60405163e5fa4c4b60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063e5fa4c4b90610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b90899060040161458f565b604080518082019091526000808252602082015260405163f297754960e01b81527352328dcfca4a0944962bf8ec8832a04daa4652189063f297754990610e36906000907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908890600401613b8d565b600080806116ab84860186612ef7565b92509250925060006116bd848461236a565b9050610d418383838a6001600160701b0316612453565b604080516060810182526000808252602082018190529181018290528190819060405163c50af1eb60e01b8152738eac1410049392e4542dd2810a221f4612910c489063c50af1eb90610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908b9060040161469c565b600061175c612d17565b604051638ba21e1d60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90638ba21e1d90610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a906004016141b4565b6040805160608101825260008082526020820181905291810182905281906040516363ff145d60e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063c7fe28ba90610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b90600401613f22565b6000611884612d17565b604051630dcef2ed60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90630dcef2ed90610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908990600401614563565b60006118ec612d17565b604051630d07304f60e31b815273cad2609d4853938868f8d66ba777ac9bacba4a1c90636839827890610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a90600401614180565b60408051606081018252600080825260208201819052918101829052819081906040516317ab7b9b60e21b8152738eac1410049392e4542dd2810a221f4612910c4890635eadee6c90610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143e4565b604080516060810182526000808252602082018190529181018290528190604051631954f75160e11b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906332a9eea290610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b9060040161409b565b6000808080611abb85870187612f41565b93509350935093506000611acf858561236a565b9050611add8584838c612453565b611af28483838b6001600160701b0316612453565b505050505050505050565b6040805160608101825260008082526020820181905291810182905281906040516359a29a5960e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb906359a29a5990610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b90600401613f94565b60408051606081018252600080825260208201819052918101829052819081906040516315d2b52760e01b8152738eac1410049392e4542dd2810a221f4612910c48906315d2b52790610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c90600401613f60565b60008080611c4b84860186612ef7565b9250925092506000611c5d848461236a565b9050610d418483838a6001600160801b0316612453565b6000611c7e612d17565b60405163fb3cc8ed60e01b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063fb3cc8ed90610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a906004016141b4565b604080516060810182526000808252602082018190529181018290528190819060405163eeb09e5d60e01b8152738eac1410049392e4542dd2810a221f4612910c489063eeb09e5d90610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143b0565b600080738e1f09e007701e3611a7699541d43bad5d32dc006358de0b2060007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b7f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732876040518563ffffffff1660e01b8152600401610cc29493929190613c7d565b60008073eab68789d7e047498158bf8d87cefb0d8ad069626380fbc4ad60007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b866040518463ffffffff1660e01b8152600401611e7e93929190613dc3565b604080518083038186803b158015611e9557600080fd5b505af4158015611ea9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c91906133f4565b60008073eab68789d7e047498158bf8d87cefb0d8ad0696263ef2797a260007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b7f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732876040518563ffffffff1660e01b8152600401611e7e9493929190613c03565b6000611f58612d17565b6040516330cd441d60e21b815273cad2609d4853938868f8d66ba777ac9bacba4a1c9063c335107490610aec9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908a90600401614180565b60408051606081018252600080825260208201819052918101829052819060405163f777ff6760e01b8152738bc1633c9e37a8beffeff1c1a4db673470fa5edb9063f777ff6790610be49060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908b90600401613f60565b6040805160608101825260008082526020820181905291810182905281908190604051637e7a8aeb60e01b8152738eac1410049392e4542dd2810a221f4612910c4890637e7a8aeb90610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b907f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732908c906004016143b0565b6121516000307f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b61214c36869003860186613078565b61250e565b50565b60008073eab68789d7e047498158bf8d87cefb0d8ad0696263b4cb373260007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b7f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732876040518563ffffffff1660e01b8152600401611e7e9493929190613c03565b604080516060810182526000808252602082018190529181018290528190819060405163b1d7966960e01b8152738eac1410049392e4542dd2810a221f4612910c489063b1d7966990610f2a9060009030907f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b908b90600401614418565b600080738e1f09e007701e3611a7699541d43bad5d32dc006336b4aeec60007f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b866040518463ffffffff1660e01b8152600401610cc293929190613e4b565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506001600160a01b0380841660009081526020818152604080832086851684528252808320858452825291829020825160c0810184528154851681526001820154851692810192909252600281015484169282019290925260038201548316606082015260048201548316608082015260059091015490911660a08201525b9392505050565b60405163e6a4390560e01b81526001600160a01b03838116600483015282811660248301526000917f0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b9091169063e6a439059060440160206040518083038186803b1580156123d857600080fd5b505afa1580156123ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124109190612fdc565b9050336001600160a01b03821614610e855760405162461bcd60e51b81526004016102fd906020808252600490820152634537303160e01b604082015260600190565b6001600160a01b0383163014156124f3577f00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf7326001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156124bf57600080fd5b505af11580156124d3573d6000803e3d6000fd5b506124ee935050506001600160a01b038616905083836126ab565b612508565b6125086001600160a01b0385168484846126c4565b50505050565b428160600151101561254b5760405162461bcd60e51b81526004016102fd90602080825260049082015263114d4c0d60e21b604082015260600190565b8051602082015160405163e6a4390560e01b81526001600160a01b039283166004820152908216602482015260009184169063e6a439059060440160206040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d69190612fdc565b90506001600160a01b0381166126175760405162461bcd60e51b81526004016102fd906020808252600490820152634535303160e01b604082015260600190565b81516001600160a01b039081166000908152602087815260408083208287015185168452825280832081870151845290915290208054909116156126865760405162461bcd60e51b81526004016102fd906020808252600490820152634535303360e01b604082015260600190565b8251602084015160408501516126a39284928992879291906126d9565b505050505050565b6126bf6001600160a01b0384168383612974565b505050565b6125086001600160a01b0385168484846129d7565b600083836126e684612a0f565b6040516020016126f893929190613b58565b60408051601f19818403018152908290528051602090910120630271028160e41b82529150734a1d7a326fca250e191ee552a3bc6de34d9186f29063271028109061274f908a9085908b908b9089906004016146db565b60006040518083038186803b15801561276757600080fd5b505af415801561277b573d6000803e3d6000fd5b50506040516319618ee560e21b81527340caac2b6d836c04aa754f4ff6fe420252bfd81e92506365863b9491506127be908a9085908b908b9089906004016146db565b60006040518083038186803b1580156127d657600080fd5b505af41580156127ea573d6000803e3d6000fd5b5050604051633aa4a34f60e01b815273e9ec30653995ce7bacb349d76d8fa376a3ea01389250633aa4a34f915061282d908a9085908b908b9089906004016146db565b60006040518083038186803b15801561284557600080fd5b505af4158015612859573d6000803e3d6000fd5b50506040516333bba79f60e11b815273fb06087e41a8af562a686f4ad11bf19c745c481d92506367774f3e915061289c908a9085908b908b9089906004016146db565b60006040518083038186803b1580156128b457600080fd5b505af41580156128c8573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f93a4226e499fc5f28e8d401847de401ce2cf454fc1dd52734bf5b606f6616532848a60405161296392919091825280546001600160a01b0390811660208401526001820154811660408401526002820154811660608401526003820154811660808401526004820154811660a08401526005909101541660c082015260e00190565b60405180910390a350505050505050565b6040516001600160a01b0383166024820152604481018290526126bf90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b31565b6040516001600160a01b03808516602483015283166044820152606481018290526125089085906323b872dd60e01b906084016129a0565b606081612a335750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612a5d5780612a4781614848565b9150612a569050600a836147f1565b9150612a37565b60008167ffffffffffffffff811115612a8657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612ab0576020820181803683370190505b5090505b8415612b2957612ac5600183614805565b9150612ad2600a86614863565b612add9060306147d9565b60f81b818381518110612b0057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612b22600a866147f1565b9450612ab4565b949350505050565b6000612b86826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c039092919063ffffffff16565b8051909150156126bf5780806020019051810190612ba49190612ebb565b6126bf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102fd565b6060612b298484600085856001600160a01b0385163b612c655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102fd565b600080866001600160a01b03168587604051612c819190613b3c565b60006040518083038185875af1925050503d8060008114612cbe576040519150601f19603f3d011682016040523d82523d6000602084013e612cc3565b606091505b5091509150612cd3828286612cde565b979650505050505050565b60608315612ced575081612363565b825115612cfd5782518084602001fd5b8160405162461bcd60e51b81526004016102fd91906146c8565b60408051608081018252600080825260208201819052918101829052606081019190915290565b8035612d49816148a3565b919050565b60008083601f840112612d5f578182fd5b50813567ffffffffffffffff811115612d76578182fd5b602083019150836020828501011115612d8e57600080fd5b9250929050565b60006101008284031215612da7578081fd5b50919050565b600060e08284031215612da7578081fd5b60006101208284031215612da7578081fd5b60006101408284031215612da7578081fd5b600060608284031215612df3578081fd5b6040516060810181811067ffffffffffffffff82111715612e2257634e487b7160e01b83526041600452602483fd5b80604052508091508251612e35816148b8565b81526020830151612e45816148b8565b6020820152604083015163ffffffff81168114612e6157600080fd5b6040919091015292915050565b600060a08284031215612da7578081fd5b600060c08284031215612da7578081fd5b8035612d49816148b8565b8035612d49816148cd565b803564ffffffffff81168114612d4957600080fd5b600060208284031215612ecc578081fd5b81518015158114612363578182fd5b600060208284031215612eec578081fd5b8135612363816148a3565b600080600060608486031215612f0b578182fd5b8335612f16816148a3565b92506020840135612f26816148a3565b91506040840135612f36816148a3565b809150509250925092565b60008060008060808587031215612f56578182fd5b8435612f61816148a3565b93506020850135612f71816148a3565b92506040850135612f81816148a3565b91506060850135612f91816148a3565b939692955090935050565b600080600060608486031215612fb0578081fd5b8335612fbb816148a3565b92506020840135612fcb816148a3565b929592945050506040919091013590565b600060208284031215612fed578081fd5b8151612363816148a3565b6000610100828403121561300a578081fd5b6123638383612d95565b600060e08284031215613025578081fd5b6123638383612dad565b60006101208284031215613041578081fd5b6123638383612dbe565b6000610140828403121561305d578081fd5b6123638383612dd0565b600060808284031215612da7578081fd5b600060808284031215613089578081fd5b6040516080810181811067ffffffffffffffff821117156130b857634e487b7160e01b83526041600452602483fd5b60405282356130c6816148a3565b815260208301356130d6816148a3565b6020820152604083810135908201526060928301359281019290925250919050565b600060408284031215612da7578081fd5b600060a0828403121561311a578081fd5b6123638383612e6e565b600060c08284031215613135578081fd5b6123638383612e7f565b600060208284031215613150578081fd5b813567ffffffffffffffff811115613166578182fd5b612b2984828501612e7f565b600060208284031215613183578081fd5b813567ffffffffffffffff811115613199578182fd5b612b2984828501612dad565b6000604082840312156131b6578081fd5b6040516040810181811067ffffffffffffffff821117156131e557634e487b7160e01b83526041600452602483fd5b60405282516131f3816148cd565b81526020830151613203816148cd565b60208201529392505050565b600080600060408486031215613223578081fd5b833561322e816148b8565b9250602084013567ffffffffffffffff811115613249578182fd5b61325586828701612d4e565b9497909650939450505050565b600080600060408486031215613276578081fd5b833561322e816148cd565b60008060408385031215613293578182fd5b825161329e816148cd565b60208401519092506132af816148cd565b809150509250929050565b6000806000604084860312156132ce578081fd5b83359250602084013567ffffffffffffffff811115613249578182fd5b60008082840360a08112156132fe578283fd5b835192506080601f1982011215613313578182fd5b506040516080810181811067ffffffffffffffff8211171561334357634e487b7160e01b83526041600452602483fd5b6040526020840151613354816148b8565b81526040840151613364816148b8565b60208201526060840151613377816148b8565b6040820152608084015161338a816148b8565b6060820152919491935090915050565b600080600080606085870312156133af578182fd5b8435935060208501356133c1816148b8565b9250604085013567ffffffffffffffff8111156133dc578283fd5b6133e887828801612d4e565b95989497509550505050565b60008060408385031215613406578182fd5b8251915060208301516132af816148cd565b600080600060a0848603121561342c578081fd5b83519250602084015191506134448560408601612de2565b90509250925092565b60008060008060c08587031215613462578182fd5b8451935060208501519250604085015191506134818660608701612de2565b905092959194509250565b81835260006020808501945082825b858110156134c95781356134ae816148b8565b6001600160701b03168752958201959082019060010161349b565b509495945050505050565b81835260006001600160fb1b038311156134ec578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845261352081602086016020860161481c565b601f01601f19169290920160200192915050565b803561353f816148a3565b6001600160a01b03908116835260208281013590840152604082013590613565826148a3565b908116604084015260608201359061357c826148a3565b1660608301526080810135613590816148b8565b6001600160701b031660808301526135aa60a08201612e90565b6001600160701b031660a08301526135c460c08201612e90565b6001600160701b03811660c08401525b5060e090810135910152565b80356135eb816148a3565b6001600160a01b03908116835260208281013590840152604082013590613611826148a3565b9081166040840152606082013590613628826148a3565b166060830152608081013561363c816148b8565b6001600160701b03908116608084015260a08201359061365b826148b8565b1660a083015260c090810135910152565b8035613677816148a3565b6001600160a01b031682526020810135613690816148a3565b6001600160a01b03166020830152604081810135908301526136b460608201612d3e565b6001600160a01b031660608301526136ce60808201612d3e565b6001600160a01b031660808301526136e860a08201612e90565b6001600160701b031660a083015261370260c08201612e90565b6001600160701b031660c083015261371c60e08201612e90565b6001600160701b03811660e08401525b5061010090810135910152565b8035613744816148b8565b6001600160701b039081168352602082013590613760826148b8565b9081166020840152604082013590613777826148b8565b908116604084015260608201359061378e826148b8565b808216606085015250505050565b80356137a7816148a3565b6001600160a01b039081168352602082810135908401526040820135906137cd826148a3565b90811660408401526060820135906137e4826148a3565b16606083015260808101356137f8816148cd565b6001600160801b03908116608084015260a08201359061365b826148cd565b8035613822816148a3565b6001600160a01b03908116835260208281013590840152604082013590613848826148a3565b908116604084015260608201359061385f826148a3565b1660608301526080810135613873816148b8565b6001600160701b0316608083015261388d60a08201612e9b565b6001600160801b031660a08301526138a760c08201612e9b565b6001600160801b03811660c08401526135d4565b80356138c6816148a3565b6001600160a01b0316825260208101356138df816148a3565b6001600160a01b031660208301526040818101359083015261390360608201612d3e565b6001600160a01b0316606083015261391d60808201612d3e565b6001600160a01b0316608083015261393760a08201612e90565b6001600160701b031660a083015261395160c08201612e9b565b6001600160801b031660c083015261396b60e08201612e9b565b6001600160801b03811660e084015261372c565b803561398a816148a3565b6001600160a01b039081168352602082810135908401526040820135906139b0826148a3565b90811660408401526060820135906139c7826148a3565b1660608301526080818101359083015260a08101356135aa816148b8565b80356139f0816148a3565b6001600160a01b03908116835260208281013590840152604082013590613a16826148a3565b9081166040840152606082013590613a2d826148a3565b1660608301526080810135613a41816148b8565b6001600160701b0316608083015260a081810135908301526135c460c08201612e90565b613a7f82613a7283612d3e565b6001600160a01b03169052565b613a8b60208201612d3e565b6001600160a01b0316602083015260408181013590830152613aaf60608201612d3e565b6001600160a01b03166060830152613ac960808201612d3e565b6001600160a01b03166080830152613ae360a08201612e90565b6001600160701b031660a083015260c08181013590830152613b0760e08201612e90565b6001600160701b031660e0830152610100613b23828201612e90565b6001600160701b03169083015261012090810135910152565b60008251613b4e81846020870161481c565b9190910192915050565b6001600160a01b03848116825283166020820152606060408201819052600090613b8490830184613508565b95945050505050565b8481526001600160a01b03848116602083015283811660408301526101608201908335613bb9816148a3565b81166060840152602084013560808401526040840135613bd8816148a3565b811660a08401526060840135613bed816148a3565b1660c0830152613b8460e0830160808501613739565b8481526001600160a01b03848116602083015283811660408301526101008201908335613c2f816148a3565b81166060840152602084013560808401526040840135613c4e816148a3565b811660a08401526060840135613c63816148a3565b1660c08301526080929092013560e0909101529392505050565b8481526001600160a01b0384811660208301528381166040830152608060608301526000908335613cad816148a3565b166080830152602083013560a0830152613cc960408401612d3e565b6001600160a01b031660c0830152613ce46060840184614791565b60c060e0850152613cfa610140850182846134d4565b915050613d0a6080850185614791565b848303607f1901610100860152613d2283828461348c565b9250505060a08401356101208401528091505095945050505050565b8381526001600160a01b0383811660208301526101608201908335613d62816148a3565b811660408401526020840135613d77816148a3565b818116606085015250604084013560808401526060840135613d98816148a3565b811660a08401526080840135613dad816148a3565b1660c0830152612b2960e0830160a08501613739565b8381526001600160a01b0383811660208301526101008201908335613de7816148a3565b811660408401526020840135613dfc816148a3565b818116606085015250604084013560808401526060840135613e1d816148a3565b811660a08401526080840135613e32816148a3565b1660c083015260a0929092013560e09091015292915050565b8381526001600160a01b03831660208201526060604082015260008235613e71816148a3565b6001600160a01b03166060830152613e8b60208401612d3e565b6001600160a01b03166080830152604083013560a0830152613eaf60608401612d3e565b6001600160a01b031660c0830152613eca6080840184614791565b60e080850152613edf610140850182846134d4565b915050613eef60a0850185614791565b848303605f1901610100860152613f0783828461348c565b9250505060c084013561012084015280915050949350505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f566080830184613534565b9695505050505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101608101613f5660808301846135e0565b8581526001600160a01b0385811660208301528481166040830152831660608201526101a08101613fcb60808301613a7285612d3e565b602083013560a0830152613fe160408401612d3e565b6001600160a01b031660c0830152613ffb60608401612d3e565b6001600160a01b031660e083015261401560808401612e90565b61010061402c818501836001600160701b03169052565b61403860a08601612ea6565b64ffffffffff8116610120860152915061405460c08601612e90565b6001600160701b038116610140860152915061407260e08601612e90565b6001600160701b03811661016086015291505b8085013561018085015250509695505050505050565b8581526001600160a01b038581166020830152848116604083015283166060820152610180810182356140cd816148a3565b6001600160a01b03166080830152602083013560a08301526140f160408401612d3e565b6001600160a01b031660c083015261410b60608401612d3e565b6001600160a01b031660e083015261412560808401612e90565b6001600160701b031661010083015261414060a08401612ea6565b64ffffffffff1661012083015261415960c08401612e90565b6001600160701b0381166101408401525b5060e08301356101608301529695505050505050565b8581526001600160a01b0385811660208301528481166040830152831660608201526101608101613f56608083018461379c565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f566080830184613817565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101823561421a816148a3565b6001600160a01b03166080830152602083013560a083015261423e60408401612d3e565b6001600160a01b031660c083015261425860608401612d3e565b6001600160a01b031660e083015261427260808401612ea6565b64ffffffffff1661010083015261428b60a08401612e9b565b6001600160801b03166101208301526142a660c08401612e9b565b6001600160801b03811661014084015261416a565b8581526001600160a01b0385811660208301528481166040830152831660608201526101a081016142f260808301613a7285612d3e565b602083013560a083015261430860408401612d3e565b6001600160a01b031660c083015261432260608401612d3e565b6001600160a01b031660e083015261433c60808401612e90565b610100614353818501836001600160701b03169052565b61435f60a08601612ea6565b64ffffffffff8116610120860152915061437b60c08601612e9b565b6001600160801b038116610140860152915061439960e08601612e9b565b6001600160801b0381166101608601529150614085565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f56608083018461397f565b8581526001600160a01b0385811660208301528481166040830152831660608201526101808101613f5660808301846139e5565b8481526001600160a01b038481166020830152831660408201526101808101613b84606083018461366c565b8481526001600160a01b038481166020830152831660408201526101a0810161447360608301613a7285612d3e565b61447f60208401612d3e565b6001600160a01b03166080830152604083013560a08301526144a360608401612d3e565b6001600160a01b031660c08301526144bd60808401612d3e565b6001600160a01b031660e08301526144d760a08401612e90565b6101006144ee818501836001600160701b03169052565b6144fa60c08601612ea6565b91506101206145118186018464ffffffffff169052565b61451d60e08701612e90565b6001600160701b038116610140870152925061453a828701612e90565b6001600160701b03811661016087015292505b8086013561018086015250505095945050505050565b8481526001600160a01b038481166020830152831660408201526101808101613b8460608301846138bb565b8481526001600160a01b038481166020830152831660408201526101a081016145be60608301613a7285612d3e565b6145ca60208401612d3e565b6001600160a01b03166080830152604083013560a08301526145ee60608401612d3e565b6001600160a01b031660c083015261460860808401612d3e565b6001600160a01b031660e083015261462260a08401612e90565b610100614639818501836001600160701b03169052565b61464560c08601612ea6565b915061012061465c8186018464ffffffffff169052565b61466860e08701612e9b565b6001600160801b0381166101408701529250614685828701612e9b565b6001600160801b038116610160870152925061454d565b8481526001600160a01b038481166020830152831660408201526101a08101613b846060830184613a65565b6020815260006123636020830184613508565b94855260208501939093526001600160a01b039182166040850152166060830152608082015260a00190565b838152602080820184905282516001600160701b039081166040808501919091529184015116606083015282015163ffffffff16608082015260a08101612b29565b8481526020808201859052604080830185905283516001600160701b03908116606085015291840151909116608083015282015163ffffffff1660a082015260c08101613b84565b6000808335601e198436030181126147a7578283fd5b830160208101925035905067ffffffffffffffff8111156147c757600080fd5b8060051b3603831315612d8e57600080fd5b600082198211156147ec576147ec614877565b500190565b6000826148005761480061488d565b500490565b60008282101561481757614817614877565b500390565b60005b8381101561483757818101518382015260200161481f565b838111156125085750506000910152565b600060001982141561485c5761485c614877565b5060010190565b6000826148725761487261488d565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461215157600080fd5b6001600160701b038116811461215157600080fd5b6001600160801b038116811461215157600080fdfea2646970667358221220f4670042167591e845157d0c9c078b5de6c44601961c79a246a620eadd766e2764736f6c63430008040033

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

0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732

-----Decoded View---------------
Arg [0] : _factory (address): 0x5A94DA7C4daEfdF764107c308142aAA90910989B
Arg [1] : _weth (address): 0x66CAE6D61F266Aa2d1dd6054217B77bd34cDF732

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005a94da7c4daefdf764107c308142aaa90910989b
Arg [1] : 00000000000000000000000066cae6d61f266aa2d1dd6054217b77bd34cdf732


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ 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.