Contract 0x88a1f17ed33bf295e277330760b5514e6a90985b

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x685472725bee9ce49126b2fc24ff50621886d3179d5f624da0a46426855d25fc0x6080604028069792021-11-03 11:45:16456 days 2 hrs ago0x0f3bf5c241b6625c0fa781ed137fde6786b2e66f IN  Create: MCDEXLemma0 ETH0.151301538048 ETH
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x1629e0e7889039327d42c5625bd0bb2c6c20e11baee950b84526e14c444f20f1362469282022-11-08 8:05:3386 days 5 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x1629e0e7889039327d42c5625bd0bb2c6c20e11baee950b84526e14c444f20f1362469282022-11-08 8:05:3386 days 5 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x1629e0e7889039327d42c5625bd0bb2c6c20e11baee950b84526e14c444f20f1362469282022-11-08 8:05:3386 days 5 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x15b8f202558f7491ef65c92d7786073399be89d09d16da2c552db6f6a84e9548362338042022-11-08 7:05:5386 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x15b8f202558f7491ef65c92d7786073399be89d09d16da2c552db6f6a84e9548362338042022-11-08 7:05:5386 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x15b8f202558f7491ef65c92d7786073399be89d09d16da2c552db6f6a84e9548362338042022-11-08 7:05:5386 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd9341935728963126c1b2ef3c5adfe94eda1fc9ab0fa753301fda0309b2529a0362328932022-11-08 7:01:4186 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd9341935728963126c1b2ef3c5adfe94eda1fc9ab0fa753301fda0309b2529a0362328932022-11-08 7:01:4186 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd9341935728963126c1b2ef3c5adfe94eda1fc9ab0fa753301fda0309b2529a0362328932022-11-08 7:01:4186 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x0f42297066e0124daa6dcd8c9ac0138e11ed5e88b07af932a7793aec90fcb6fd362325482022-11-08 7:00:0086 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x0f42297066e0124daa6dcd8c9ac0138e11ed5e88b07af932a7793aec90fcb6fd362325482022-11-08 7:00:0086 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x0f42297066e0124daa6dcd8c9ac0138e11ed5e88b07af932a7793aec90fcb6fd362325482022-11-08 7:00:0086 days 6 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x5f264c3e0e02f736ab885efb6a74c54de3b3d3416482300d16ab1b21e5a734bd362240222022-11-08 6:20:1386 days 7 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x5f264c3e0e02f736ab885efb6a74c54de3b3d3416482300d16ab1b21e5a734bd362240222022-11-08 6:20:1386 days 7 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x5f264c3e0e02f736ab885efb6a74c54de3b3d3416482300d16ab1b21e5a734bd362240222022-11-08 6:20:1386 days 7 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x53990580d8af61d351051d757bebfb7729cfcae16e4ecb2da5666aa5f60a1195350327862022-11-03 18:59:0890 days 18 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x53990580d8af61d351051d757bebfb7729cfcae16e4ecb2da5666aa5f60a1195350327862022-11-03 18:59:0890 days 18 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x53990580d8af61d351051d757bebfb7729cfcae16e4ecb2da5666aa5f60a1195350327862022-11-03 18:59:0890 days 18 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd75b0f02f627a4e3d3901310276feba0d1c41c1e054ae06cd118569cfe4ae69d342204642022-10-31 16:26:5493 days 21 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd75b0f02f627a4e3d3901310276feba0d1c41c1e054ae06cd118569cfe4ae69d342204642022-10-31 16:26:5493 days 21 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xd75b0f02f627a4e3d3901310276feba0d1c41c1e054ae06cd118569cfe4ae69d342204642022-10-31 16:26:5493 days 21 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xdee3354bfd67c67778c192274ee07ddc3ff3b4ce4b80b613b6eb382a2a2fb62a286631502022-10-06 9:17:33119 days 4 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xdee3354bfd67c67778c192274ee07ddc3ff3b4ce4b80b613b6eb382a2a2fb62a286631502022-10-06 9:17:33119 days 4 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0xdee3354bfd67c67778c192274ee07ddc3ff3b4ce4b80b613b6eb382a2a2fb62a286631502022-10-06 9:17:33119 days 4 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
0x49e30cee0a6cebbcd0b8290b752d84b14118ccba63bf5aeafd2d4faff03e1c8c280180072022-10-02 15:08:19122 days 22 hrs ago 0x3092ed676e1c59ee5ab6eb4bf19a11bca84d67bd 0x88a1f17ed33bf295e277330760b5514e6a90985b0 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MCDEXLemma

Compiler Version
v0.8.3+commit.8d00100c

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 16 : MCDEXLemma.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.3;

import { ILiquidityPool, PerpetualState } from "../interfaces/MCDEX/ILiquidityPool.sol";
import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { ERC2771ContextUpgradeable } from "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol";
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { Utils } from "../libraries/Utils.sol";
import { SafeMathExt } from "../libraries/SafeMathExt.sol";
import { IPerpetualDEXWrapper } from "../interfaces/IPerpetualDEXWrapper.sol";

interface IUSDLemma {
    function lemmaTreasury() external view returns (address);
}

/// @author Lemma Finance
contract MCDEXLemma is OwnableUpgradeable, ERC2771ContextUpgradeable, IPerpetualDEXWrapper {
    using SafeCastUpgradeable for uint256;
    using SafeCastUpgradeable for int256;
    using Utils for int256;
    using SafeMathExt for int256;

    uint256 public constant MAX_UINT256 = type(uint256).max;
    int256 public constant MAX_INT256 = type(int256).max;

    // address of Mai3 liquidity pool
    ILiquidityPool public liquidityPool;

    // pereptual index in the liquidity pool
    uint256 public perpetualIndex;

    IERC20Upgradeable public collateral;
    uint256 public collateralDecimals;

    address public usdLemma;
    address public reBalancer;
    address public referrer;

    int256 public entryFunding;
    int256 public realizedFundingPNL;

    uint256 public positionAtSettlement;

    uint256 public maxPosition;

    //events
    event USDLemmaUpdated(address usdlAddress);
    event ReferrerUpdated(address referrerAddress);
    event RebalancerUpdated(address rebalancerAddress);
    event MaxPositionUpdated(uint256 maxPos);

    function initialize(
        address _trustedForwarder,
        ILiquidityPool _liquidityPool,
        uint256 _perpetualIndex,
        address _usdlemma,
        address _reBalancer,
        uint256 _maxPosition
    ) external initializer {
        __Ownable_init();
        __ERC2771Context_init(_trustedForwarder);
        liquidityPool = _liquidityPool;
        perpetualIndex = _perpetualIndex;
        {
            (bool isRunning, , address[7] memory addresses, , uint256[4] memory uintNums) = liquidityPool
                .getLiquidityPoolInfo();
            require(isRunning, "pool is not running");
            collateral = IERC20Upgradeable(addresses[5]);
            collateralDecimals = uintNums[0];
        }
        setReBalancer(_reBalancer);
        setUSDLemma(_usdlemma);
        setMaxPosition(_maxPosition);

        //approve collateral to
        SafeERC20Upgradeable.safeApprove(collateral, address(liquidityPool), MAX_UINT256);
        //target leverage = 1
        liquidityPool.setTargetLeverage(perpetualIndex, address(this), 1 ether); //1
    }

    ///@notice sets USDLemma address - only owner can set
    ///@param _usdlemma USDLemma address to set
    function setUSDLemma(address _usdlemma) public onlyOwner {
        usdLemma = _usdlemma;
        emit USDLemmaUpdated(usdLemma);
    }

    ///@notice sets refferer address - only owner can set
    ///@param _referrer refferer address to set
    function setReferrer(address _referrer) external onlyOwner {
        referrer = _referrer;
        emit ReferrerUpdated(referrer);
    }

    ///@notice sets reBalncer address - only owner can set
    ///@param _reBalancer reBalancer address to set
    function setReBalancer(address _reBalancer) public onlyOwner {
        reBalancer = _reBalancer;
        emit RebalancerUpdated(reBalancer);
    }

    ///@notice sets Max Positions - only owner can set
    ///@param _maxPosition reBalancer address to set
    function setMaxPosition(uint256 _maxPosition) public onlyOwner {
        maxPosition = _maxPosition;
        emit MaxPositionUpdated(maxPosition);
    }

    /// @notice reset approvals
    function resetApprovals() external {
        SafeERC20Upgradeable.safeApprove(collateral, address(liquidityPool), 0);
        SafeERC20Upgradeable.safeApprove(collateral, address(liquidityPool), MAX_UINT256);
    }

    //this needs to be done before the first withdrawal happens
    //Keeper gas reward needs to be handled seperately which owner can get back when perpetual has settled
    /// @notice Deposit Keeper gas reward for the perpetual - only owner can call
    function depositKeeperGasReward() external onlyOwner {
        int256 keeperGasReward;
        {
            (, , int256[39] memory nums) = liquidityPool.getPerpetualInfo(perpetualIndex);
            keeperGasReward = nums[11];
        }
        SafeERC20Upgradeable.safeTransferFrom(
            collateral,
            _msgSender(),
            address(this),
            getAmountInCollateralDecimals(keeperGasReward.toUint256(), true)
        );
        liquidityPool.deposit(perpetualIndex, address(this), keeperGasReward);
    }

    //go short to open
    /// @notice Open short position on dex and deposit collateral
    /// @param amount worth in USD short position which is to be opened
    /// @param collateralAmountRequired collateral amount required to open the position
    function open(uint256 amount, uint256 collateralAmountRequired) external override {
        require(_msgSender() == usdLemma, "only usdLemma is allowed");
        require(
            collateral.balanceOf(address(this)) >= getAmountInCollateralDecimals(collateralAmountRequired, true),
            "not enough collateral"
        );
        liquidityPool.deposit(perpetualIndex, address(this), collateralAmountRequired.toInt256());

        (, int256 position, , , , , , , ) = liquidityPool.getMarginAccount(perpetualIndex, address(this));

        require(position.abs().toUint256() + amount <= maxPosition, "max position reached");
        liquidityPool.trade(perpetualIndex, address(this), amount.toInt256(), MAX_INT256, MAX_UINT256, referrer, 0);
        updateEntryFunding(position, amount.toInt256());
    }

    //go long and withdraw collateral
    /// @notice Close short position on dex and withdraw collateral
    /// @param amount worth in USD short position which is to be closed
    /// @param collateralAmountToGetBack collateral amount freed up after closing the position
    function close(uint256 amount, uint256 collateralAmountToGetBack) external override {
        require(_msgSender() == usdLemma, "only usdLemma is allowed");

        (PerpetualState perpetualState, , ) = liquidityPool.getPerpetualInfo(perpetualIndex);

        if (perpetualState != PerpetualState.CLEARED) {
            //means perpetual settled
            (, int256 position, , , , , , , ) = liquidityPool.getMarginAccount(perpetualIndex, address(this));
            liquidityPool.trade(
                perpetualIndex,
                address(this),
                -amount.toInt256(), //negative means you want to go short (on USD, that in turn means long on ETH)
                0,
                MAX_UINT256,
                referrer,
                0
            );
            liquidityPool.withdraw(perpetualIndex, address(this), collateralAmountToGetBack.toInt256());
            updateEntryFunding(position, -amount.toInt256());
        }
        SafeERC20Upgradeable.safeTransfer(
            collateral,
            usdLemma,
            getAmountInCollateralDecimals(collateralAmountToGetBack, false)
        );
    }

    //// @notice when perpetual is in CLEARED state, withdraw the collateral
    function settle() public {
        (, int256 position, , , , , , , ) = liquidityPool.getMarginAccount(perpetualIndex, address(this));
        positionAtSettlement = position.abs().toUint256();
        liquidityPool.settle(perpetualIndex, address(this));
    }

    /// @notice Collateral amount required/to get back for amount in USD to open/close position on dex
    /// @param amount worth in USD short position which is to be closed or opened
    /// @param isShorting true if opening short position, false if closing short position
    /// @return collateralAmountRequired equivalent collateral amount
    function getCollateralAmountGivenUnderlyingAssetAmount(uint256 amount, bool isShorting)
        external
        override
        returns (uint256 collateralAmountRequired)
    {
        liquidityPool.forceToSyncState();
        int256 tradeAmount = isShorting ? amount.toInt256() : -amount.toInt256();

        //handle the case when perpetual has settled
        (PerpetualState perpetualState, , ) = liquidityPool.getPerpetualInfo(perpetualIndex);

        if (perpetualState == PerpetualState.CLEARED) {
            require(!isShorting, "cannot open when perpetual has settled");
            (
                ,
                ,
                ,
                ,
                int256 settleableMargin, // bankrupt
                ,
                ,
                ,

            ) = liquidityPool.getMarginAccount(perpetualIndex, address(this));

            if (settleableMargin != 0) {
                settle();
            }
            collateralAmountRequired = (collateral.balanceOf(address(this)) * amount) / positionAtSettlement;
        } else {
            (int256 tradePrice, int256 totalFee, ) = liquidityPool.queryTrade(
                perpetualIndex,
                address(this),
                tradeAmount,
                referrer,
                0
            );

            int256 deltaCash = amount.toInt256().wmul(tradePrice);

            collateralAmountRequired = isShorting
                ? (deltaCash + totalFee).toUint256()
                : (deltaCash - totalFee).toUint256();
        }
    }

    /// @notice Rebalance position of dex based on accumulated funding, since last rebalancing
    /// @param _reBalancer Address of rebalancer who called function on USDL contract
    /// @param amount Amount of accumulated funding fees used to rebalance by opening or closing a short position
    /// @param data Abi encoded data to call respective mcdex function, contains limitPrice and deadline
    /// @return True if successful, False if unsuccessful
    function reBalance(
        address _reBalancer,
        int256 amount,
        bytes calldata data
    ) external override returns (bool) {
        liquidityPool.forceToSyncState();
        require(_msgSender() == usdLemma, "only usdLemma is allowed");
        require(_reBalancer == reBalancer, "only rebalancer is allowed");

        (int256 limitPrice, uint256 deadline) = abi.decode(data, (int256, uint256));
        int256 fundingPNL = getFundingPNL();

        (int256 tradePrice, int256 totalFee, ) = liquidityPool.queryTrade(
            perpetualIndex,
            address(this),
            amount,
            referrer,
            0
        );
        int256 deltaCash = amount.abs().wmul(tradePrice);
        uint256 collateralAmount = (deltaCash + totalFee).toUint256();
        if (amount < 0) {
            realizedFundingPNL -= collateralAmount.toInt256();
        } else {
            realizedFundingPNL += collateralAmount.toInt256();
        }

        int256 difference = fundingPNL - realizedFundingPNL;
        //error +-10**12 is allowed in calculation
        require(difference.abs() <= 10**12, "not allowed");

        liquidityPool.trade(perpetualIndex, address(this), amount, limitPrice, deadline, referrer, 0);

        return true;
    }

    /// @notice calculate entryFunding to be able to calculate the fundingPNL easily
    /// @param position Current position on MCDEX
    /// @param tradeAmount Change in current position on MCDEX
    function updateEntryFunding(int256 position, int256 tradeAmount) internal {
        (int256 closeAmount, int256 openAmount) = Utils.splitAmount(position, tradeAmount);
        int256 unitAccumulativeFunding;
        {
            (, , int256[39] memory nums) = liquidityPool.getPerpetualInfo(perpetualIndex);
            unitAccumulativeFunding = nums[4];
        }
        if (closeAmount != 0) {
            int256 oldPosition = position;
            int256 newPosition = position + closeAmount;
            entryFunding = entryFunding.wmul(newPosition).wdiv(oldPosition);
        }
        if (openAmount != 0) {
            entryFunding = entryFunding + unitAccumulativeFunding.wmul(openAmount);
        }
    }

    /// @notice Get funding PnL for this address till now
    /// @return fundingPNL Funding PnL accumulated till now
    function getFundingPNL() public view returns (int256 fundingPNL) {
        int256 unitAccumulativeFunding;
        {
            (, , int256[39] memory nums) = liquidityPool.getPerpetualInfo(perpetualIndex);
            unitAccumulativeFunding = nums[4];
        }
        (, int256 position, , , , , , , ) = liquidityPool.getMarginAccount(perpetualIndex, address(this));
        fundingPNL = entryFunding - position.wmul(unitAccumulativeFunding);
    }

    /// @notice Get Amount in collateral decimals, provided amount is in 18 decimals
    /// @param amount Amount in 18 decimals
    /// @param roundUp If needs to round up
    /// @return decimal adjusted value
    function getAmountInCollateralDecimals(uint256 amount, bool roundUp) public view override returns (uint256) {
        if (roundUp && (amount % (uint256(10**(18 - collateralDecimals))) != 0)) {
            return amount / uint256(10**(18 - collateralDecimals)) + 1;
        }

        return amount / uint256(10**(18 - collateralDecimals));
    }

    ///@notice send MCB tokens that we may get to lemmaTreasury
    function sendMCBToTreasury() external {
        IERC20Upgradeable mcbToken = IERC20Upgradeable(0x4e352cF164E64ADCBad318C3a1e222E9EBa4Ce42);
        address lemmaTreasury = IUSDLemma(usdLemma).lemmaTreasury();
        SafeERC20Upgradeable.safeTransfer(mcbToken, lemmaTreasury, mcbToken.balanceOf(address(this)));
    }

    function _msgSender()
        internal
        view
        virtual
        override(ContextUpgradeable, ERC2771ContextUpgradeable)
        returns (address sender)
    {
        //ERC2771ContextUpgradeable._msgSender();
        return super._msgSender();
    }

    function _msgData()
        internal
        view
        virtual
        override(ContextUpgradeable, ERC2771ContextUpgradeable)
        returns (bytes calldata)
    {
        //ERC2771ContextUpgradeable._msgData();
        return super._msgData();
    }
}

File 2 of 16 : ILiquidityPool.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.3;

/**
 * @notice  Perpetual state:
 *          - INVALID:      Uninitialized or not non-existent perpetual;
 *          - INITIALIZING: Only when LiquidityPoolStorage.isRunning == false. Traders cannot perform operations;
 *          - NORMAL:       Full functional state. Traders is able to perform all operations;
 *          - EMERGENCY:    Perpetual is unsafe and only clear is available;
 *          - CLEARED:      All margin account is cleared. Trade could withdraw remaining margin balance.
 */
enum PerpetualState {
    INVALID,
    INITIALIZING,
    NORMAL,
    EMERGENCY,
    CLEARED
}

interface ILiquidityPool {
    /**
     * @notice Get the info of the liquidity pool
     * @return isRunning True if the liquidity pool is running
     * @return isFastCreationEnabled True if the operator of the liquidity pool is allowed to create new perpetual
     *                               when the liquidity pool is running
     * @return addresses The related addresses of the liquidity pool
     * @return intNums Int type properties, see below for details.
     * @return uintNums Uint type properties, see below for details.
     */
    function getLiquidityPoolInfo()
        external
        view
        returns (
            bool isRunning,
            bool isFastCreationEnabled,
            // [0] creator,
            // [1] operator,
            // [2] transferringOperator,
            // [3] governor,
            // [4] shareToken,
            // [5] collateralToken,
            // [6] vault,
            address[7] memory addresses,
            // [0] vaultFeeRate,
            // [1] poolCash,
            // [2] insuranceFundCap,
            // [3] insuranceFund,
            // [4] donatedInsuranceFund,
            int256[5] memory intNums,
            // [0] collateralDecimals,
            // [1] perpetualCount
            // [2] fundingTime,
            // [3] operatorExpiration,
            uint256[4] memory uintNums
        );

    /**
     * @notice Get the info of the perpetual. Need to update the funding state and the oracle price
     *         of each perpetual before and update the funding rate of each perpetual after
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return state The state of the perpetual
     * @return oracle The oracle's address of the perpetual
     * @return nums The related numbers of the perpetual
     */
    function getPerpetualInfo(uint256 perpetualIndex)
        external
        view
        returns (
            PerpetualState state,
            address oracle,
            // [0] totalCollateral
            // [1] markPrice, (return settlementPrice if it is in EMERGENCY state)
            // [2] indexPrice,
            // [3] fundingRate,
            // [4] unitAccumulativeFunding,
            // [5] initialMarginRate,
            // [6] maintenanceMarginRate,
            // [7] operatorFeeRate,
            // [8] lpFeeRate,
            // [9] referralRebateRate,
            // [10] liquidationPenaltyRate,
            // [11] keeperGasReward,
            // [12] insuranceFundRate,
            // [13-15] halfSpread value, min, max,
            // [16-18] openSlippageFactor value, min, max,
            // [19-21] closeSlippageFactor value, min, max,
            // [22-24] fundingRateLimit value, min, max,
            // [25-27] ammMaxLeverage value, min, max,
            // [28-30] maxClosePriceDiscount value, min, max,
            // [31] openInterest,
            // [32] maxOpenInterestRate,
            // [33-35] fundingRateFactor value, min, max,
            // [36-38] defaultTargetLeverage value, min, max,
            int256[39] memory nums
        );

    /**
     * @notice Get the account info of the trader. Need to update the funding state and the oracle price
     *         of each perpetual before and update the funding rate of each perpetual after
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param trader The address of the trader
     * @return cash The cash(collateral) of the account
     * @return position The position of the account
     * @return availableMargin The available margin of the account
     * @return margin The margin of the account
     * @return settleableMargin The settleable margin of the account
     * @return isInitialMarginSafe True if the account is initial margin safe
     * @return isMaintenanceMarginSafe True if the account is maintenance margin safe
     * @return isMarginSafe True if the total value of margin account is beyond 0
     * @return targetLeverage   The target leverage for openning position.
     */
    function getMarginAccount(uint256 perpetualIndex, address trader)
        external
        view
        returns (
            int256 cash,
            int256 position,
            int256 availableMargin,
            int256 margin,
            int256 settleableMargin,
            bool isInitialMarginSafe,
            bool isMaintenanceMarginSafe,
            bool isMarginSafe, // bankrupt
            int256 targetLeverage
        );

    /**
     * @notice Initialize the liquidity pool and set up its configuration.
     *
     * @param operator              The operator's address of the liquidity pool.
     * @param collateral            The collateral's address of the liquidity pool.
     * @param collateralDecimals    The collateral's decimals of the liquidity pool.
     * @param governor              The governor's address of the liquidity pool.
     * @param initData              A bytes array contains data to initialize new created liquidity pool.
     */
    function initialize(
        address operator,
        address collateral,
        uint256 collateralDecimals,
        address governor,
        bytes calldata initData
    ) external;

    /**
     * @notice  Deposit collateral to the perpetual.
     *          Can only called when the perpetual's state is "NORMAL".
     *          This method will always increase `cash` amount in trader's margin account.
     *
     * @param   perpetualIndex  The index of the perpetual in the liquidity pool.
     * @param   trader          The address of the trader.
     * @param   amount          The amount of collatetal to deposit. The amount always use decimals 18.
     */
    function deposit(
        uint256 perpetualIndex,
        address trader,
        int256 amount
    ) external;

    /**
     * @notice  Withdraw collateral from the trader's account of the perpetual.
     *          After withdrawn, trader shall at least has maintenance margin left in account.
     *          Can only called when the perpetual's state is "NORMAL".
     *          Margin account must at least keep
     *          The trader's cash will decrease in the perpetual.
     *          Need to update the funding state and the oracle price of each perpetual before
     *          and update the funding rate of each perpetual after
     *
     * @param   perpetualIndex  The index of the perpetual in the liquidity pool.
     * @param   trader          The address of the trader.
     * @param   amount          The amount of collatetal to withdraw. The amount always use decimals 18.
     */
    function withdraw(
        uint256 perpetualIndex,
        address trader,
        int256 amount
    ) external;

    /**
     * @notice Trade with AMM in the perpetual, require sender is granted the trade privilege by the trader.
     *         The trading price is determined by the AMM based on the index price of the perpetual.
     *         Trader must be initial margin safe if opening position and margin safe if closing position
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param trader The address of trader
     * @param amount The position amount of the trade
     * @param limitPrice The worst price the trader accepts
     * @param deadline The deadline of the trade
     * @param referrer The referrer's address of the trade
     * @param flags The flags of the trade
     * @return int256 The update position amount of the trader after the trade
     */
    function trade(
        uint256 perpetualIndex,
        address trader,
        int256 amount,
        int256 limitPrice,
        uint256 deadline,
        address referrer,
        uint32 flags
    ) external returns (int256);

    /**
     * @notice Trade with AMM by the order, initiated by the broker.
     *         The trading price is determined by the AMM based on the index price of the perpetual.
     *         Trader must be initial margin safe if opening position and margin safe if closing position
     * @param orderData The order data object
     * @param amount The position amount of the trade
     * @return int256 The update position amount of the trader after the trade
     */
    function brokerTrade(bytes memory orderData, int256 amount) external returns (int256);

    /**
     * @notice Get the number of active accounts in the perpetual.
     *         Active means the trader's account is not empty in the perpetual.
     *         Empty means cash and position are zero
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return activeAccountCount The number of active accounts in the perpetual
     */
    function getActiveAccountCount(uint256 perpetualIndex) external view returns (uint256);

    /**
     * @notice Get the active accounts in the perpetual whose index between begin and end.
     *         Active means the trader's account is not empty in the perpetual.
     *         Empty means cash and position are zero
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param begin The begin index
     * @param end The end index
     * @return result The active accounts in the perpetual whose index between begin and end
     */
    function listActiveAccounts(
        uint256 perpetualIndex,
        uint256 begin,
        uint256 end
    ) external view returns (address[] memory result);

    /**
     * @notice Get the progress of clearing active accounts.
     *         Return the number of total active accounts and the number of active accounts not cleared
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return left The left active accounts
     * @return total The total active accounts
     */
    function getClearProgress(uint256 perpetualIndex) external view returns (uint256 left, uint256 total);

    /**
     * @notice Get the pool margin of the liquidity pool.
     *         Pool margin is how much collateral of the pool considering the AMM's positions of perpetuals
     * @return poolMargin The pool margin of the liquidity pool
     */
    function getPoolMargin() external view returns (int256 poolMargin, bool isSafe);

    /**
     * @notice Get the update cash amount and the update position amount of trader
     *         if trader trades with AMM in the perpetual
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param amount The trading amount of position
     * @return deltaCash The update cash(collateral) of the trader after the trade
     * @return deltaPosition The update position of the trader after the trade
     */
    function queryTradeWithAMM(uint256 perpetualIndex, int256 amount)
        external
        view
        returns (int256 deltaCash, int256 deltaPosition);

    /**
     * @notice  Query the price, fees and cost when trade agaist amm.
     *          The trading price is determined by the AMM based on the index price of the perpetual.
     *          This method should returns the same result as a 'read-only' trade.
     *          WARN: the result of this function is base on current storage of liquidityPool, not the latest.
     *          To get the latest status, call `syncState` first.
     *
     *          Flags is a 32 bit uint value which indicates: (from highest bit)
     *            - close only      only close position during trading;
     *            - market order    do not check limit price during trading;
     *            - stop loss       only available in brokerTrade mode;
     *            - take profit     only available in brokerTrade mode;
     *          For stop loss and take profit, see `validateTriggerPrice` in OrderModule.sol for details.
     *
     * @param   perpetualIndex  The index of the perpetual in liquidity pool.
     * @param   trader          The address of trader.
     * @param   amount          The amount of position to trader, positive for buying and negative for selling. The amount always use decimals 18.
     * @param   referrer        The address of referrer who will get rebate from the deal.
     * @param   flags           The flags of the trade.
     * @return  tradePrice      The average fill price.
     * @return  totalFee        The total fee collected from the trader after the trade.
     * @return  cost            Deposit or withdraw to let effective leverage == targetLeverage if flags contain USE_TARGET_LEVERAGE. > 0 if deposit, < 0 if withdraw.
     */
    function queryTrade(
        uint256 perpetualIndex,
        address trader,
        int256 amount,
        address referrer,
        uint32 flags
    )
        external
        view
        returns (
            int256 tradePrice,
            int256 totalFee,
            int256 cost
        );

    /**
     * @notice Get claimable fee of the operator in the liquidity pool
     * @return int256 The claimable fee of the operator in the liquidity pool
     */
    function getClaimableOperatorFee() external view returns (int256);

    /**
     * @notice Get claimable fee of the claimer in the liquidity pool
     * @param claimer The address of the claimer
     * @return int256 The claimable fee of the claimer in the liquidity pool. always use decimals 18.
     */
    function getClaimableFee(address claimer) external view returns (int256);

    /**
     * @notice  If you want to get the real-time data, call this function first
     */
    function forceToSyncState() external;

    /**
     * @notice Returns the current implementation of UpgradeableProxy.
     */
    function implementation() external view returns (address);

    /**
     * @notice  Query cash to add / share to mint when adding liquidity to the liquidity pool.
     *          Only one of cashToAdd or shareToMint may be non-zero.
     *
     * @param   cashToAdd         The amount of cash to add, always use decimals 18.
     * @param   shareToMint       The amount of share token to mint, always use decimals 18.
     * @return  cashToAddResult   The amount of cash to add, always use decimals 18. Equal to cashToAdd if cashToAdd is non-zero.
     * @return  shareToMintResult The amount of cash to add, always use decimals 18. Equal to shareToMint if shareToMint is non-zero.
     */
    function queryAddLiquidity(int256 cashToAdd, int256 shareToMint)
        external
        view
        returns (int256 cashToAddResult, int256 shareToMintResult);

    /**
     * @notice  Query cash to return / share to redeem when removing liquidity from the liquidity pool.
     *          Only one of shareToRemove or cashToReturn may be non-zero.
     *          Can only called when the pool is running.
     *
     * @param   shareToRemove       The amount of share token to redeem, always use decimals 18.
     * @param   cashToReturn        The amount of cash to return, always use decimals 18.
     * @return  shareToRemoveResult The amount of share token to redeem, always use decimals 18. Equal to shareToRemove if shareToRemove is non-zero.
     * @return  cashToReturnResult  The amount of cash to return, always use decimals 18. Equal to cashToReturn if cashToReturn is non-zero.
     */
    function queryRemoveLiquidity(int256 shareToRemove, int256 cashToReturn)
        external
        view
        returns (int256 shareToRemoveResult, int256 cashToReturnResult);

    function settle(uint256 perpetualIndex, address trader) external;

    /**
     * @dev     Get the fees of the trade. If the margin of the trader is not enough for fee:
     *            1. If trader open position, the trade will be reverted.
     *            2. If trader close position, the fee will be decreasing in proportion according to
     *               the margin left in the trader's account
     *          The rebate of referral will only calculate the lpFee and operatorFee.
     *          The vault fee will not be counted in.
     *
     * @param   liquidityPool   The reference of liquidity pool storage.
     * @param   perpetual       The reference of pereptual storage.
     * @param   trader          The address of trader.
     * @param   referrer        The address of referrer who will get rebate from the deal.
     * @param   tradeValue      The amount of trading value, measured by collateral, abs of deltaCash.
     * @return  lpFee           The amount of fee to the Liquidity provider.
     * @return  operatorFee     The amount of fee to the operator.
     * @return  vaultFee        The amount of fee to the vault.
     * @return  referralRebate  The amount of rebate of the refferral.
     */
    function getFees(
        address liquidityPool,
        address perpetual,
        address trader,
        address referrer,
        int256 tradeValue,
        bool hasOpened
    )
        external
        view
        returns (
            int256 lpFee,
            int256 operatorFee,
            int256 vaultFee,
            int256 referralRebate
        );

    function setTargetLeverage(
        uint256 perpetualIndex,
        address trader,
        int256 targetLeverage
    ) external;
}

File 3 of 16 : SafeCastUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCastUpgradeable {
    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 4 of 16 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
    uint256[49] private __gap;
}

File 5 of 16 : ERC2771ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Context variant with ERC2771 support.
 */
abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {
    address private _trustedForwarder;

    function __ERC2771Context_init(address trustedForwarder) internal initializer {
        __Context_init_unchained();
        __ERC2771Context_init_unchained(trustedForwarder);
    }

    function __ERC2771Context_init_unchained(address trustedForwarder) internal initializer {
        _trustedForwarder = trustedForwarder;
    }

    function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
        return forwarder == _trustedForwarder;
    }

    function _msgSender() internal view virtual override returns (address sender) {
        if (isTrustedForwarder(msg.sender)) {
            // The assembly code is more direct than the Solidity version using `abi.decode`.
            assembly {
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }
        } else {
            return super._msgSender();
        }
    }

    function _msgData() internal view virtual override returns (bytes calldata) {
        if (isTrustedForwarder(msg.sender)) {
            return msg.data[:msg.data.length - 20];
        } else {
            return super._msgData();
        }
    }
    uint256[49] private __gap;
}

File 6 of 16 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 7 of 16 : SafeERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20Upgradeable.sol";
import "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {
    using AddressUpgradeable for address;

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

    function safeTransferFrom(
        IERC20Upgradeable 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(
        IERC20Upgradeable 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(
        IERC20Upgradeable 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(
        IERC20Upgradeable 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(IERC20Upgradeable 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 8 of 16 : Utils.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.3;
import "./SafeMathExt.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/SignedSafeMathUpgradeable.sol";

//recreating https://github.com/mcdexio/mai-protocol-v3/blob/master/contracts/libraries/Utils.sol
library Utils {
    using SafeMathExt for int256;
    using SignedSafeMathUpgradeable for int256;

    /*
     * @dev Check if two numbers have the same sign. Zero has the same sign with any number
     */
    function hasTheSameSign(int256 x, int256 y) internal pure returns (bool) {
        if (x == 0 || y == 0) {
            return true;
        }
        return (x ^ y) >> 255 == 0;
    }

    /*
     * @dev Split the delta to two numbers.
     *      Use for splitting the trading amount to the amount to close position and the amount to open position.
     *      Examples: 2, 1 => 0, 1; 2, -1 => -1, 0; 2, -3 => -2, -1
     */
    function splitAmount(int256 amount, int256 delta) internal pure returns (int256, int256) {
        if (Utils.hasTheSameSign(amount, delta)) {
            return (0, delta);
        } else if (amount.abs() >= delta.abs()) {
            return (delta, 0);
        } else {
            return (amount.neg(), amount.add(delta));
        }
    }
}

File 9 of 16 : SafeMathExt.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.3;

import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/math/SignedSafeMathUpgradeable.sol";
import "./Constant.sol";
import "./Utils.sol";

enum Round {
    CEIL,
    FLOOR
}

library SafeMathExt {
    using SafeMathUpgradeable for uint256;
    using SignedSafeMathUpgradeable for int256;

    /*
     * @dev Always half up for uint256
     */
    function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x.mul(y).add(Constant.UNSIGNED_ONE / 2) / Constant.UNSIGNED_ONE;
    }

    /*
     * @dev Always half up for uint256
     */
    function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x.mul(Constant.UNSIGNED_ONE).add(y / 2).div(y);
    }

    /*
     * @dev Always half up for uint256
     */
    function wfrac(
        uint256 x,
        uint256 y,
        uint256 z
    ) internal pure returns (uint256 r) {
        r = x.mul(y).add(z / 2).div(z);
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wmul(int256 x, int256 y) internal pure returns (int256 z) {
        z = roundHalfUp(x.mul(y), Constant.SIGNED_ONE) / Constant.SIGNED_ONE;
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wdiv(int256 x, int256 y) internal pure returns (int256 z) {
        if (y < 0) {
            y = neg(y);
            x = neg(x);
        }
        z = roundHalfUp(x.mul(Constant.SIGNED_ONE), y).div(y);
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wfrac(
        int256 x,
        int256 y,
        int256 z
    ) internal pure returns (int256 r) {
        int256 t = x.mul(y);
        if (z < 0) {
            z = neg(z);
            t = neg(t);
        }
        r = roundHalfUp(t, z).div(z);
    }

    function wmul(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 z) {
        z = div(x.mul(y), Constant.SIGNED_ONE, round);
    }

    function wdiv(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 z) {
        z = div(x.mul(Constant.SIGNED_ONE), y, round);
    }

    function wfrac(
        int256 x,
        int256 y,
        int256 z,
        Round round
    ) internal pure returns (int256 r) {
        int256 t = x.mul(y);
        r = div(t, z, round);
    }

    function abs(int256 x) internal pure returns (int256) {
        return x >= 0 ? x : neg(x);
    }

    function neg(int256 a) internal pure returns (int256) {
        return SignedSafeMathUpgradeable.sub(int256(0), a);
    }

    /*
     * @dev ROUND_HALF_UP rule helper.
     *      You have to call roundHalfUp(x, y) / y to finish the rounding operation.
     *      0.5 ≈ 1, 0.4 ≈ 0, -0.5 ≈ -1, -0.4 ≈ 0
     */
    function roundHalfUp(int256 x, int256 y) internal pure returns (int256) {
        require(y > 0, "roundHalfUp only supports y > 0");
        if (x >= 0) {
            return x.add(y / 2);
        }
        return x.sub(y / 2);
    }

    /*
     * @dev Division, rounding ceil or rounding floor
     */
    function div(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 divResult) {
        require(y != 0, "division by zero");
        divResult = x.div(y);
        if (x % y == 0) {
            return divResult;
        }
        bool isSameSign = Utils.hasTheSameSign(x, y);
        if (round == Round.CEIL && isSameSign) {
            divResult = divResult.add(1);
        }
        if (round == Round.FLOOR && !isSameSign) {
            divResult = divResult.sub(1);
        }
    }

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

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

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

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

File 10 of 16 : IPerpetualDEXWrapper.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.3;

interface IPerpetualDEXWrapper {
    function open(uint256 amount, uint256 collateralAmountRequired) external;

    function close(uint256 amount, uint256 collateralAmountToGetBack) external;

    function getCollateralAmountGivenUnderlyingAssetAmount(uint256 amount, bool isShorting)
        external
        returns (uint256 collateralAmountRequired);

    function reBalance(
        address _reBalancer,
        int256 amount,
        bytes calldata data
    ) external returns (bool);

    function getAmountInCollateralDecimals(uint256 amount, bool roundUp) external view returns (uint256);
}

File 11 of 16 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}

File 12 of 16 : Initializable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

File 13 of 16 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        (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 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);
            }
        }
    }
}

File 14 of 16 : SignedSafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SignedSafeMathUpgradeable {
    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        return a / b;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        return a - b;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        return a + b;
    }
}

File 15 of 16 : SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMathUpgradeable {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

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

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

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

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 16 of 16 : Constant.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.3;

library Constant {
    address internal constant INVALID_ADDRESS = address(0);

    int256 internal constant SIGNED_ONE = 10**18;
    uint256 internal constant UNSIGNED_ONE = 10**18;

    uint256 internal constant PRIVILEGE_DEPOSIT = 0x1;
    uint256 internal constant PRIVILEGE_WITHDRAW = 0x2;
    uint256 internal constant PRIVILEGE_TRADE = 0x4;
    uint256 internal constant PRIVILEGE_LIQUIDATE = 0x8;
    uint256 internal constant PRIVILEGE_GUARD =
        PRIVILEGE_DEPOSIT | PRIVILEGE_WITHDRAW | PRIVILEGE_TRADE | PRIVILEGE_LIQUIDATE;
    // max number of uint256
    uint256 internal constant SET_ALL_PERPETUALS_TO_EMERGENCY_STATE =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPos","type":"uint256"}],"name":"MaxPositionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rebalancerAddress","type":"address"}],"name":"RebalancerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"referrerAddress","type":"address"}],"name":"ReferrerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"usdlAddress","type":"address"}],"name":"USDLemmaUpdated","type":"event"},{"inputs":[],"name":"MAX_INT256","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_UINT256","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"collateralAmountToGetBack","type":"uint256"}],"name":"close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositKeeperGasReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entryFunding","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"roundUp","type":"bool"}],"name":"getAmountInCollateralDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"isShorting","type":"bool"}],"name":"getCollateralAmountGivenUnderlyingAssetAmount","outputs":[{"internalType":"uint256","name":"collateralAmountRequired","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getFundingPNL","outputs":[{"internalType":"int256","name":"fundingPNL","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_trustedForwarder","type":"address"},{"internalType":"contract ILiquidityPool","name":"_liquidityPool","type":"address"},{"internalType":"uint256","name":"_perpetualIndex","type":"uint256"},{"internalType":"address","name":"_usdlemma","type":"address"},{"internalType":"address","name":"_reBalancer","type":"address"},{"internalType":"uint256","name":"_maxPosition","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityPool","outputs":[{"internalType":"contract ILiquidityPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"collateralAmountRequired","type":"uint256"}],"name":"open","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpetualIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionAtSettlement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reBalancer","type":"address"},{"internalType":"int256","name":"amount","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"reBalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reBalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"realizedFundingPNL","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referrer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetApprovals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sendMCBToTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPosition","type":"uint256"}],"name":"setMaxPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_reBalancer","type":"address"}],"name":"setReBalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"}],"name":"setReferrer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdlemma","type":"address"}],"name":"setUSDLemma","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdLemma","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506130a7806100206000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638da5cb5b1161010f578063bcc9c0f6116100a2578063d555f62311610071578063d555f623146103c7578063d8dfeb45146103da578063ec9c6c30146103ed578063f2fde38b146103f6576101f0565b8063bcc9c0f614610385578063beba14e114610398578063beeb9dfb146103ab578063d1870db9146103b4576101f0565b80639a919991116100de5780639a91999114610344578063a18a7bfc14610357578063a1f9637d1461036a578063a29558341461037d576101f0565b80638da5cb5b146103185780638ed59fd01461032057806392f72def1461032957806399cbad761461033c576101f0565b80634082de6711610187578063665a11ca11610156578063665a11ca146102bf57806368447c93146102ea578063715018a6146102fd578063851b137b14610305576101f0565b80634082de671461025e57806342bf732514610271578063572b6c051461027a578063596c8976146102ac576101f0565b80631d868875116101c35780631d8688751461023b57806333a581d214610244578063379afccc1461024d5780633d7bfaaa14610255576101f0565b80630d7e5a79146101f557806310dd5686146101ff57806311da60b414610212578063122e7b071461021a575b600080fd5b6101fd610409565b005b6101fd61020d366004612b28565b61052a565b6101fd6105ae565b6102286001600160ff1b0381565b6040519081526020015b60405180910390f35b61022860a05481565b61022860001981565b6101fd6106c0565b61022860a15481565b6101fd61026c366004612b07565b6106ff565b61022860985481565b61029c610288366004612794565b6065546001600160a01b0390811691161490565b6040519015158152602001610232565b6101fd6102ba366004612b07565b610a4c565b6097546102d2906001600160a01b031681565b6040516001600160a01b039091168152602001610232565b609d546102d2906001600160a01b031681565b6101fd610d42565b6101fd610313366004612794565b610d8b565b6102d2610e18565b610228609f5481565b610228610337366004612b40565b610e28565b6102286111ee565b610228610352366004612b40565b611335565b6101fd610365366004612794565b6113cb565b609c546102d2906001600160a01b031681565b6101fd611458565b61029c61039336600461283b565b6115a0565b609b546102d2906001600160a01b031681565b610228609e5481565b6101fd6103c23660046127cc565b6118f4565b6101fd6103d5366004612794565b611b36565b6099546102d2906001600160a01b031681565b610228609a5481565b6101fd610404366004612794565b611bc3565b609b546040805163019cd46760e71b81529051734e352cf164e64adcbad318c3a1e222e9eba4ce42926000926001600160a01b039091169163ce6a338091600480820192602092909190829003018186803b15801561046757600080fd5b505afa15801561047b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049f91906127b0565b6040516370a0823160e01b815230600482015290915061052690839083906001600160a01b038316906370a082319060240160206040518083038186803b1580156104e957600080fd5b505afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190612a3b565b611c73565b5050565b610532611cd6565b6001600160a01b0316610543610e18565b6001600160a01b0316146105725760405162461bcd60e51b815260040161056990612c43565b60405180910390fd5b60a18190556040518181527feb5034f650e091336850d826e4106a3b618d7d113464b5ad3d1f432900a0283c906020015b60405180910390a150565b609754609854604051637d3ba80f60e01b815260048101919091523060248201526000916001600160a01b031690637d3ba80f906044016101206040518083038186803b1580156105fe57600080fd5b505afa158015610612573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106369190612a80565b5050505050505091505061065161064c82611ce5565b611d01565b60a0556097546098546040516312c5a32760e31b815260048101919091523060248201526001600160a01b039091169063962d1938906044015b600060405180830381600087803b1580156106a557600080fd5b505af11580156106b9573d6000803e3d6000fd5b5050505050565b6099546097546106de916001600160a01b0390811691166000611d53565b6099546097546106fd916001600160a01b039081169116600019611d53565b565b609b546001600160a01b0316610713611cd6565b6001600160a01b0316146107395760405162461bcd60e51b815260040161056990612bbe565b610744816001611335565b6099546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561078757600080fd5b505afa15801561079b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107bf9190612a3b565b10156108055760405162461bcd60e51b81526020600482015260156024820152741b9bdd08195b9bdd59da0818dbdb1b185d195c985b605a1b6044820152606401610569565b6097546098546001600160a01b03909116906378f140ea903061082785611e77565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526044820152606401600060405180830381600087803b15801561087557600080fd5b505af1158015610889573d6000803e3d6000fd5b5050609754609854604051637d3ba80f60e01b81526004810191909152306024820152600093506001600160a01b039091169150637d3ba80f906044016101206040518083038186803b1580156108df57600080fd5b505afa1580156108f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109179190612a80565b5050505050505091505060a1548361093161064c84611ce5565b61093b9190612d4c565b11156109805760405162461bcd60e51b81526020600482015260146024820152731b585e081c1bdcda5d1a5bdb881c995858da195960621b6044820152606401610569565b6097546098546001600160a01b039091169063709240c490306109a287611e77565b609d546040516001600160e01b031960e087901b1681526109e2949392916001600160ff1b0391600019916001600160a01b031690600090600401612c78565b602060405180830381600087803b1580156109fc57600080fd5b505af1158015610a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a349190612a3b565b50610a4781610a4285611e77565b611ee1565b505050565b609b546001600160a01b0316610a60611cd6565b6001600160a01b031614610a865760405162461bcd60e51b815260040161056990612bbe565b6097546098546040516204966760e11b815260048101919091526000916001600160a01b03169062092cce906024016105206040518083038186803b158015610ace57600080fd5b505afa158015610ae2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0691906129a1565b5090915060049050816004811115610b2e57634e487b7160e01b600052602160045260246000fd5b14610d2057609754609854604051637d3ba80f60e01b815260048101919091523060248201526000916001600160a01b031690637d3ba80f906044016101206040518083038186803b158015610b8357600080fd5b505afa158015610b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbb9190612a80565b50506097546098549698506001600160a01b0316965063709240c4959450309350610beb92508a9150611e779050565b610bf490612ff2565b609d546040516001600160e01b031960e087901b168152610c2d94939291600091600019916001600160a01b0316908390600401612c78565b602060405180830381600087803b158015610c4757600080fd5b505af1158015610c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7f9190612a3b565b506097546098546001600160a01b0390911690636ef05a409030610ca287611e77565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526044820152606401600060405180830381600087803b158015610cf057600080fd5b505af1158015610d04573d6000803e3d6000fd5b50505050610d1e81610d1586611e77565b610a4290612ff2565b505b609954609b54610a47916001600160a01b039081169116610521856000611335565b610d4a611cd6565b6001600160a01b0316610d5b610e18565b6001600160a01b031614610d815760405162461bcd60e51b815260040161056990612c43565b6106fd6000611fe2565b610d93611cd6565b6001600160a01b0316610da4610e18565b6001600160a01b031614610dca5760405162461bcd60e51b815260040161056990612c43565b609b80546001600160a01b0319166001600160a01b0383169081179091556040519081527fad0d6ee71196e4951edb077b61a235f17f0399e1bbd7bd8b7433fc34702ade79906020016105a3565b6033546001600160a01b03165b90565b609754604080516338437e9960e11b815290516000926001600160a01b031691637086fd32916004808301928692919082900301818387803b158015610e6d57600080fd5b505af1158015610e81573d6000803e3d6000fd5b50505050600082610ea357610e9584611e77565b610e9e90612ff2565b610eac565b610eac84611e77565b6097546098546040516204966760e11b81529293506000926001600160a01b039092169162092cce91610ee59160040190815260200190565b6105206040518083038186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3691906129a1565b5090915060049050816004811115610f5e57634e487b7160e01b600052602160045260246000fd5b14156110fd578315610fc15760405162461bcd60e51b815260206004820152602660248201527f63616e6e6f74206f70656e207768656e2070657270657475616c206861732073604482015265195d1d1b195960d21b6064820152608401610569565b609754609854604051637d3ba80f60e01b815260048101919091523060248201526000916001600160a01b031690637d3ba80f906044016101206040518083038186803b15801561101157600080fd5b505afa158015611025573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110499190612a80565b5050505094505050505080600014611063576110636105ae565b60a0546099546040516370a0823160e01b815230600482015288916001600160a01b0316906370a082319060240160206040518083038186803b1580156110a957600080fd5b505afa1580156110bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e19190612a3b565b6110eb9190612f3d565b6110f59190612d92565b9350506111e6565b609754609854609d546040516342ee6b0560e11b81526004810192909252306024830152604482018590526001600160a01b0390811660648301526000608483018190529283929116906385dcd60a9060a40160606040518083038186803b15801561116857600080fd5b505afa15801561117c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a09190612a53565b509150915060006111ba836111b48a611e77565b90612034565b9050866111d3576111ce61064c8383612f5c565b6111e0565b6111e061064c8383612d0b565b95505050505b505092915050565b6097546098546040516204966760e11b81526004810191909152600091829182916001600160a01b03169062092cce906024016105206040518083038186803b15801561123a57600080fd5b505afa15801561124e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127291906129a1565b60800151609754609854604051637d3ba80f60e01b81526004810191909152306024820152919550600094506001600160a01b03169250637d3ba80f91506044016101206040518083038186803b1580156112cc57600080fd5b505afa1580156112e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113049190612a80565b50505050505050915050611321828261203490919063ffffffff16565b609e5461132e9190612f5c565b9250505090565b60008180156113655750609a5461134d906012612f9b565b61135890600a612dec565b6113629084612fde565b15155b1561139f57609a54611378906012612f9b565b61138390600a612dec565b61138d9084612d92565b611398906001612d4c565b90506113c5565b609a546113ad906012612f9b565b6113b890600a612dec565b6113c29084612d92565b90505b92915050565b6113d3611cd6565b6001600160a01b03166113e4610e18565b6001600160a01b03161461140a5760405162461bcd60e51b815260040161056990612c43565b609d80546001600160a01b0319166001600160a01b0383169081179091556040519081527f3568f651c15bce2b453765b9ef9c58098f430d7c749b81132e5661a20fbc12fe906020016105a3565b611460611cd6565b6001600160a01b0316611471610e18565b6001600160a01b0316146114975760405162461bcd60e51b815260040161056990612c43565b6097546098546040516204966760e11b815260009283926001600160a01b039091169162092cce916114cf9160040190815260200190565b6105206040518083038186803b1580156114e857600080fd5b505afa1580156114fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152091906129a1565b610160015160995490945061155e93506001600160a01b031691506115459050611cd6565b3061155961155286611d01565b6001611335565b612064565b609754609854604051633c78a07560e11b81526004810191909152306024820152604481018390526001600160a01b03909116906378f140ea9060640161068b565b609754604080516338437e9960e11b815290516000926001600160a01b031691637086fd32916004808301928692919082900301818387803b1580156115e557600080fd5b505af11580156115f9573d6000803e3d6000fd5b5050609b546001600160a01b031691506116139050611cd6565b6001600160a01b0316146116395760405162461bcd60e51b815260040161056990612bbe565b609c546001600160a01b038681169116146116965760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920726562616c616e63657220697320616c6c6f7765640000000000006044820152606401610569565b6000806116a584860186612b07565b9150915060006116b36111ee565b609754609854609d546040516342ee6b0560e11b81526004810192909252306024830152604482018b90526001600160a01b039081166064830152600060848301819052939450839216906385dcd60a9060a40160606040518083038186803b15801561171f57600080fd5b505afa158015611733573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117579190612a53565b5091509150600061176b836111b48c611ce5565b9050600061177c61064c8484612d0b565b905060008b12156117ac5761179081611e77565b609f60008282546117a19190612f5c565b909155506117cc9050565b6117b581611e77565b609f60008282546117c69190612d0b565b90915550505b6000609f54866117dc9190612f5c565b905064e8d4a510006117ed82611ce5565b13156118295760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b6044820152606401610569565b609760009054906101000a90046001600160a01b03166001600160a01b031663709240c4609854308f8c8c609d60009054906101000a90046001600160a01b031660006040518863ffffffff1660e01b815260040161188e9796959493929190612c78565b602060405180830381600087803b1580156118a857600080fd5b505af11580156118bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e09190612a3b565b5060019d9c50505050505050505050505050565b600054610100900460ff168061190d575060005460ff16155b6119295760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff1615801561194b576000805461ffff19166101011790555b6119536120a2565b61195c8761211d565b609780546001600160a01b0319166001600160a01b03881690811790915560988690556040805163066e082d60e11b8152905160009283928392630cdc105a9160048082019261024092909190829003018186803b1580156119bd57600080fd5b505afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906128db565b945050935050925082611a405760405162461bcd60e51b8152602060048201526013602482015272706f6f6c206973206e6f742072756e6e696e6760681b6044820152606401610569565b60a09190910151609980546001600160a01b0319166001600160a01b0390921691909117905551609a5550611a7483611b36565b611a7d84610d8b565b611a868261052a565b609954609754611aa5916001600160a01b039081169116600019611d53565b609754609854604051632d47ba5760e01b81526004810191909152306024820152670de0b6b3a764000060448201526001600160a01b0390911690632d47ba5790606401600060405180830381600087803b158015611b0357600080fd5b505af1158015611b17573d6000803e3d6000fd5b505050508015611b2d576000805461ff00191690555b50505050505050565b611b3e611cd6565b6001600160a01b0316611b4f610e18565b6001600160a01b031614611b755760405162461bcd60e51b815260040161056990612c43565b609c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f82932c2bbe344307ce4c4d0134c032fd62927625f9603697984f4f2668bc1ddc906020016105a3565b611bcb611cd6565b6001600160a01b0316611bdc610e18565b6001600160a01b031614611c025760405162461bcd60e51b815260040161056990612c43565b6001600160a01b038116611c675760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610569565b611c7081611fe2565b50565b6040516001600160a01b038316602482015260448101829052610a4790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261219a565b6000611ce061226c565b905090565b600080821215611cfd57611cf882612298565b6113c5565b5090565b600080821215611cfd5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152606401610569565b801580611ddc5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015611da257600080fd5b505afa158015611db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dda9190612a3b565b155b611e475760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610569565b6040516001600160a01b038316602482015260448101829052610a4790849063095ea7b360e01b90606401611c9f565b60006001600160ff1b03821115611cfd5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610569565b600080611eee84846122a5565b6097546098546040516204966760e11b8152600481019190915292945090925060009182916001600160a01b03169062092cce906024016105206040518083038186803b158015611f3e57600080fd5b505afa158015611f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7691906129a1565b6080015193505084159150611fbb905057846000611f948583612d0b565b9050611fb582611faf83609e5461203490919063ffffffff16565b90612303565b609e5550505b81156106b957611fcb8183612034565b609e54611fd89190612d0b565b609e555050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000670de0b6b3a764000061205a61204c8585612349565b670de0b6b3a7640000612355565b6113c29190612d64565b6040516001600160a01b038085166024830152831660448201526064810182905261209c9085906323b872dd60e01b90608401611c9f565b50505050565b600054610100900460ff16806120bb575060005460ff16155b6120d75760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff161580156120f9576000805461ffff19166101011790555b6121016123d8565b612109612442565b8015611c70576000805461ff001916905550565b600054610100900460ff1680612136575060005460ff16155b6121525760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff16158015612174576000805461ffff19166101011790555b61217c6123d8565b612185826124a9565b8015610526576000805461ff00191690555050565b60006121ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166125309092919063ffffffff16565b805190915015610a47578080602001905181019061220d91906128bf565b610a475760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610569565b6065546000906001600160a01b0316331415612291575060131936013560601c610e25565b5033610e25565b60006113c5600083612549565b6000806122b28484612555565b156122c2575060009050816122fc565b6122cb83611ce5565b6122d485611ce5565b126122e4575081905060006122fc565b6122ed84612298565b6122f78585612578565b915091505b9250929050565b6000808212156123245761231682612298565b915061232183612298565b92505b6113c28261234361233d86670de0b6b3a7640000612349565b85612355565b90612584565b60006113c28284612eba565b60008082136123a65760405162461bcd60e51b815260206004820152601f60248201527f726f756e6448616c665570206f6e6c7920737570706f7274732079203e2030006044820152606401610569565b600083126123c3576113986123bc600284612d64565b8490612578565b6113c26123d1600284612d64565b8490612549565b600054610100900460ff16806123f1575060005460ff16155b61240d5760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff16158015612109576000805461ffff19166101011790558015611c70576000805461ff001916905550565b600054610100900460ff168061245b575060005460ff16155b6124775760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff16158015612499576000805461ffff19166101011790555b6121096124a4611cd6565b611fe2565b600054610100900460ff16806124c2575060005460ff16155b6124de5760405162461bcd60e51b815260040161056990612bf5565b600054610100900460ff16158015612500576000805461ffff19166101011790555b606580546001600160a01b0319166001600160a01b0384161790558015610526576000805461ff00191690555050565b606061253f8484600085612590565b90505b9392505050565b60006113c28284612f5c565b6000821580612562575081155b1561256f575060016113c5565b501860ff1d1590565b60006113c28284612d0b565b60006113c28284612d64565b6060824710156125f15760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610569565b843b61263f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610569565b600080866001600160a01b0316858760405161265b9190612b6f565b60006040518083038185875af1925050503d8060008114612698576040519150601f19603f3d011682016040523d82523d6000602084013e61269d565b606091505b50915091506126ad8282866126b8565b979650505050505050565b606083156126c7575081612542565b8251156126d75782518084602001fd5b8160405162461bcd60e51b81526004016105699190612b8b565b600082601f830112612701578081fd5b61270b60a0612cb9565b80838560a08601111561271c578384fd5b835b600581101561273d57815184526020938401939091019060010161271e565b509095945050505050565b600082601f830112612758578081fd5b6127626080612cb9565b808385608086011115612773578384fd5b835b600481101561273d578151845260209384019390910190600101612775565b6000602082840312156127a5578081fd5b81356125428161304e565b6000602082840312156127c1578081fd5b81516125428161304e565b60008060008060008060c087890312156127e4578182fd5b86356127ef8161304e565b955060208701356127ff8161304e565b94506040870135935060608701356128168161304e565b925060808701356128268161304e565b8092505060a087013590509295509295509295565b60008060008060608587031215612850578384fd5b843561285b8161304e565b935060208501359250604085013567ffffffffffffffff8082111561287e578384fd5b818701915087601f830112612891578384fd5b81358181111561289f578485fd5b8860208285010111156128b0578485fd5b95989497505060200194505050565b6000602082840312156128d0578081fd5b815161254281613063565b600080600080600061024086880312156128f3578283fd5b85516128fe81613063565b8095505060208087015161291181613063565b9450605f87018813612921578384fd5b600761293461292f82612cea565b612cb9565b8060408a016101208b018c81111561294a578889fd5b885b8581101561297157825161295f8161304e565b8552938601939186019160010161294c565b5082985061297f8d826126f1565b9750505050505050612995876101c08801612748565b90509295509295909350565b60008060006105208085870312156129b7578182fd5b8451600581106129c5578283fd5b809450506020808601516129d88161304e565b9350605f860187136129e8578283fd5b60276129f661292f82612cea565b80604089018a868b011115612a09578687fd5b8695505b83861015612a2b578051835260019590950194918401918401612a0d565b5080955050505050509250925092565b600060208284031215612a4c578081fd5b5051919050565b600080600060608486031215612a67578081fd5b8351925060208401519150604084015190509250925092565b60008060008060008060008060006101208a8c031215612a9e578687fd5b8951985060208a0151975060408a0151965060608a0151955060808a0151945060a08a0151612acc81613063565b60c08b0151909450612add81613063565b60e08b0151909350612aee81613063565b809250506101008a015190509295985092959850929598565b60008060408385031215612b19578182fd5b50508035926020909101359150565b600060208284031215612b39578081fd5b5035919050565b60008060408385031215612b52578182fd5b823591506020830135612b6481613063565b809150509250929050565b60008251612b81818460208701612fb2565b9190910192915050565b6000602082528251806020840152612baa816040850160208701612fb2565b601f01601f19169190910160400192915050565b60208082526018908201527f6f6e6c79207573644c656d6d6120697320616c6c6f7765640000000000000000604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b9687526001600160a01b03958616602088015260408701949094526060860192909252608085015290911660a083015263ffffffff1660c082015260e00190565b604051601f8201601f1916810167ffffffffffffffff81118282101715612ce257612ce2613038565b604052919050565b600067ffffffffffffffff821115612d0457612d04613038565b5060051b90565b600080821280156001600160ff1b0384900385131615612d2d57612d2d61300c565b600160ff1b8390038412811615612d4657612d4661300c565b50500190565b60008219821115612d5f57612d5f61300c565b500190565b600082612d7357612d73613022565b600160ff1b821460001984141615612d8d57612d8d61300c565b500590565b600082612da157612da1613022565b500490565b80825b6001808611612db85750612de3565b818704821115612dca57612dca61300c565b80861615612dd757918102915b9490941c938002612da9565b94509492505050565b60006113c26000198484600082612e0557506001612542565b81612e1257506000612542565b8160018114612e285760028114612e3257612e5f565b6001915050612542565b60ff841115612e4357612e4361300c565b6001841b915084821115612e5957612e5961300c565b50612542565b5060208310610133831016604e8410600b8410161715612e92575081810a83811115612e8d57612e8d61300c565b612542565b612e9f8484846001612da6565b808604821115612eb157612eb161300c565b02949350505050565b60006001600160ff1b0381841382841380821686840486111615612ee057612ee061300c565b600160ff1b84871282811687830589121615612efe57612efe61300c565b858712925087820587128484161615612f1957612f1961300c565b87850587128184161615612f2f57612f2f61300c565b505050929093029392505050565b6000816000190483118215151615612f5757612f5761300c565b500290565b60008083128015600160ff1b850184121615612f7a57612f7a61300c565b6001600160ff1b0384018313811615612f9557612f9561300c565b50500390565b600082821015612fad57612fad61300c565b500390565b60005b83811015612fcd578181015183820152602001612fb5565b8381111561209c5750506000910152565b600082612fed57612fed613022565b500690565b6000600160ff1b8214156130085761300861300c565b0390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611c7057600080fd5b8015158114611c7057600080fdfea2646970667358221220d284b3caf5e7fb3058740f5daf4b698f904d727333ef9e2b5e9d2a6a238a373064736f6c63430008030033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.