Contract 0x1b6BF7Ab4163f9a7C1D4eCB36299525048083B5e 2

 

Contract Overview

Balance:
0 Ether

EtherValue:
$0.00

Token:
Txn Hash Method
Index
From
To
Value
0xb192feb68a4056adfb27b7bcfba038660cfd84906311f0fb2e9870e7afada146Withdraw153684902022-07-22 12:25:4670 days 9 hrs ago0xae75b29ade678372d77a8b41225654138a7e6ff1 IN  0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e0 Ether0.0001718847370.001
0x93222e194ee175781a4363f50fa31309db2cd5a3fd01c6ae1e9f767baace7be1Withdraw152233252022-07-21 7:53:3071 days 14 hrs ago0xae75b29ade678372d77a8b41225654138a7e6ff1 IN  0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e0 Ether0.0000991166460.001
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683Close Position148428512022-07-18 8:22:3974 days 13 hrs ago0xae75b29ade678372d77a8b41225654138a7e6ff1 IN  0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e0 Ether0.000098382260.001
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3feOpen Position145831752022-07-15 14:36:5777 days 7 hrs ago0xae75b29ade678372d77a8b41225654138a7e6ff1 IN  0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e0 Ether0.0003616556220.001
0x6e479d3abca798ca31782a5211adfe8f4576b3c9fc5f58eadebeaead5a958c160x60806040140212172022-07-07 13:40:5985 days 8 hrs ago0xae75b29ade678372d77a8b41225654138a7e6ff1 IN  Create: PerpPositionHandlerL20 Ether0.0035767421220.001
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xb192feb68a4056adfb27b7bcfba038660cfd84906311f0fb2e9870e7afada146153684902022-07-22 12:25:4670 days 9 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e Socket: Registry0 Ether
0xb192feb68a4056adfb27b7bcfba038660cfd84906311f0fb2e9870e7afada146153684902022-07-22 12:25:4670 days 9 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x7f5c764cbc14f9669b88837ca1490cca17c316070 Ether
0xb192feb68a4056adfb27b7bcfba038660cfd84906311f0fb2e9870e7afada146153684902022-07-22 12:25:4670 days 9 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x7f5c764cbc14f9669b88837ca1490cca17c316070 Ether
0x93222e194ee175781a4363f50fa31309db2cd5a3fd01c6ae1e9f767baace7be1152233252022-07-21 7:53:3071 days 14 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e Socket: Registry0 Ether
0x93222e194ee175781a4363f50fa31309db2cd5a3fd01c6ae1e9f767baace7be1152233252022-07-21 7:53:3071 days 14 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x7f5c764cbc14f9669b88837ca1490cca17c316070 Ether
0x93222e194ee175781a4363f50fa31309db2cd5a3fd01c6ae1e9f767baace7be1152233252022-07-21 7:53:3071 days 14 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x7f5c764cbc14f9669b88837ca1490cca17c316070 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d600 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d600 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d600 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x82ac2ce43e33683c58be4cdc40975e73aa50f4590 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa7f3fc32043757039d5e13d790ee43edbcba8b7c0 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa7f3fc32043757039d5e13d790ee43edbcba8b7c0 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xbd7a3b7dbeb096f0b832cf467b94b091f30c34ec0 Ether
0x4208df1296c321cd4a7ca017a542e224d032658415632f5ff7451d0411da9683148428512022-07-18 8:22:3974 days 13 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa4c817a425d3443baf610ca614c8b11688a288fb0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa7f3fc32043757039d5e13d790ee43edbcba8b7c0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x82ac2ce43e33683c58be4cdc40975e73aa50f4590 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xbd7a3b7dbeb096f0b832cf467b94b091f30c34ec0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa4c817a425d3443baf610ca614c8b11688a288fb0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x8c835dfaa34e2ae61775e80ee29e2c724c6ae2bb0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa4c817a425d3443baf610ca614c8b11688a288fb0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xbd7a3b7dbeb096f0b832cf467b94b091f30c34ec0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xa4c817a425d3443baf610ca614c8b11688a288fb0 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d600 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0x7f5c764cbc14f9669b88837ca1490cca17c316070 Ether
0x9c0d51afa8ebf4511cbbdd1b4833e7599fc96a8a614688ed00ed789cde7bf3fe145831752022-07-15 14:36:5777 days 7 hrs ago 0x1b6bf7ab4163f9a7c1d4ecb36299525048083b5e 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d600 Ether
[ Download CSV Export 
Latest 1 Deposit
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PerpPositionHandlerL2

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 27 : PerpPositionHandlerL2.sol
//SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.7.6;

import "./PerpV2Controller.sol";
import "./OptimismL2Wrapper.sol";
import "./SocketV1Controller.sol";
import "./interfaces/IPositionHandler.sol";

import {SafeMathUpgradeable} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "./interfaces/IERC20.sol";

/// @title PerpPositionHandlerL2
/// @author 0xAd1
/// @notice Acts as positon handler and token bridger on L2 Optimism
contract PerpPositionHandlerL2 is
    IPositionHandler,
    PerpV2Controller,
    SocketV1Controller,
    OptimismL2Wrapper
{
    using SafeMathUpgradeable for uint256;

    /*///////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/

    /// @notice wantTokenL1 address
    address public wantTokenL1;

    /// @notice wantTokenL2 address
    address public wantTokenL2;

    /// @notice Address of PerpTradeExecutor on L1
    address public positionHandlerL1;

    /// @notice Address of socket registry on L2
    address public socketRegistry;

    /// @notice Keeper address
    address public keeper;

    /// @notice Governance address
    address public governance;

    address public pendingGovernance;

    /// @notice Details of current position on Perp
    PerpPosition public perpPosition;

    /*///////////////////////////////////////////////////////////////
                            EVENT LOGS
    //////////////////////////////////////////////////////////////*/

    /// @notice Emitted when keeper is updated.
    /// @param oldKeeper The address of the current keeper.
    /// @param newKeeper The address of new keeper.
    event UpdatedKeeper(address indexed oldKeeper, address indexed newKeeper);

    /// @notice Emitted when governance is updated.
    /// @param oldGovernance The address of the current governance.
    /// @param newGovernance The address of new governance.
    event UpdatedGovernance(
        address indexed oldGovernance,
        address indexed newGovernance
    );

    /// @notice Emitted when socket registry is updated.
    /// @param oldRegistry The address of the current Registry.
    /// @param newRegistry The address of new Registry.
    event UpdatedSocketRegistry(
        address indexed oldRegistry,
        address indexed newRegistry
    );

    /// @notice Emitted when Perp V2 referral code is updated.
    /// @param oldReferral Old Perp V2 Referral code
    /// @param newReferral New Perp V2 Referral code
    event UpdatedPerpReferral(bytes32 oldReferral, bytes32 newReferral);

    /*///////////////////////////////////////////////////////////////
                            INITIALIZING
    //////////////////////////////////////////////////////////////*/
    constructor(
        address _wantTokenL1,
        address _wantTokenL2,
        address _positionHandlerL1,
        address _perpVault,
        address _clearingHouse,
        address _clearingHouseConfig,
        address _accountBalance,
        address _exchange,
        address _baseToken,
        address _quoteTokenvUSDC,
        address _keeper,
        address _governance,
        address _socketRegistry
    ) {
        wantTokenL1 = _wantTokenL1;
        wantTokenL2 = _wantTokenL2;
        positionHandlerL1 = _positionHandlerL1;
        perpVault = IVault(_perpVault);
        clearingHouse = IClearingHouse(_clearingHouse);
        clearingHouseConfig = IClearingHouseConfig(_clearingHouseConfig);
        accountBalance = IAccountBalance(_accountBalance);
        exchange = IExchange(_exchange);
        baseToken = IERC20(_baseToken);
        quoteTokenvUSDC = IERC20(_quoteTokenvUSDC);
        keeper = _keeper;
        governance = _governance;
        socketRegistry = _socketRegistry;
    }

    /*///////////////////////////////////////////////////////////////
                        DEPOSIT / WITHDRAW LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Bridges wantToken back to PerpTE on L1
    /// @dev Check MovrV1Controller for more details on implementation of token bridging
    /// @param amountOut amount needed to be sent to PerpTE
    /// @param allowanceTarget address of contract to provide ERC20 allowance to
    /// @param _socketRegistry address of movr contract to send txn to
    /// @param socketData movr txn calldata
    function withdraw(
        uint256 amountOut,
        address allowanceTarget,
        address _socketRegistry,
        bytes calldata socketData
    ) public override onlyAuthorized {
        require(
            IERC20(wantTokenL2).balanceOf(address(this)) >= amountOut,
            "NOT_ENOUGH_TOKENS"
        );
        require(socketRegistry == _socketRegistry, "INVALID_REGISTRY");
        sendTokens(
            wantTokenL2,
            allowanceTarget,
            socketRegistry,
            positionHandlerL1,
            amountOut,
            1,
            socketData
        );
    }

    /*///////////////////////////////////////////////////////////////
                        OPEN / CLOSE LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Creates a new position on Perp V2
    /// @dev Will deposit all USDC balance to Perp. Will close any existing position, then open a position with given amountIn on Perp.
    /// @param isShort true for short, false for long
    /// @param amountIn the amountIn with respect to free collateral on perp for new position
    /// @param slippage slippage while opening position, calculated out of 10000
    function openPosition(
        bool isShort,
        uint256 amountIn,
        uint24 slippage
    ) public override onlyAuthorized {
        require(perpPosition.isActive == false, "ACTIVE_POSITION");
        uint256 wantTokenBalance = IERC20(wantTokenL2).balanceOf(address(this));
        _depositToPerp(wantTokenBalance);
        perpPosition = PerpPosition({
            entryMarkPrice: formatSqrtPriceX96(getMarkTwapPrice()),
            entryIndexPrice: getIndexTwapPrice(),
            entryAmount: amountIn,
            isShort: isShort,
            isActive: true
        });
        _openPositionByAmount(isShort, amountIn, slippage);
    }

    /// @notice Closes existing position on Perp V2
    /// @dev Closes the position, withdraws all the funds from perp as well.
    /// @param slippage slippage while closing position, calculated out of 10000
    function closePosition(uint24 slippage) public override onlyAuthorized {
        require(perpPosition.isActive, "NO_OPEN_POSITION");
        _closePosition(slippage);
        perpPosition.isActive = false;
        _withdrawFromPerp(getFreeCollateral());
    }

    /*///////////////////////////////////////////////////////////////
                            MAINTAINANCE FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Sweep tokens
    /// @param _token Address of the token to sweepr
    function sweep(address _token) public override onlyGovernance {
        IERC20(_token).transfer(
            msg.sender,
            IERC20(_token).balanceOf(address(this))
        );
    }

    /// @notice referral code setter
    /// @param _referralCode updated referral code
    function setReferralCode(bytes32 _referralCode) public onlyGovernance {
        emit UpdatedPerpReferral(referralCode, _referralCode);
        referralCode = _referralCode;
    }

    /// @notice socket registry setter
    /// @param _socketRegistry new address of socket registry
    function setSocketRegistry(address _socketRegistry) public onlyGovernance {
        emit UpdatedSocketRegistry(socketRegistry, _socketRegistry);
        socketRegistry = _socketRegistry;
    }

    /// @notice keeper setter
    /// @param _keeper new keeper address
    function setKeeper(address _keeper) public onlyGovernance {
        emit UpdatedKeeper(keeper, _keeper);
        keeper = _keeper;
    }

    /// @notice governance setter
    /// @param _newGovernance new governance address
    function setGovernance(address _newGovernance) public onlyGovernance {
        pendingGovernance = _newGovernance;
    }

    /// @notice governance accepter
    function acceptGovernance() public {
        emit UpdatedGovernance(governance, pendingGovernance);
        require(msg.sender == pendingGovernance, "INVALID_ADDRESS");
        governance = pendingGovernance;
    }

    /// @notice checks wether txn sender is keeper address or PerpTradeExecutor using optimism gateway
    modifier onlyAuthorized() {
        require(
            ((msg.sender == L2CrossDomainMessenger &&
                messageSender() == positionHandlerL1) || msg.sender == keeper),
            "ONLY_AUTHORIZED"
        );
        _;
    }

    /// @notice checks wether txn sender is keeper address
    modifier onlyKeeper() {
        require(msg.sender == keeper, "ONLY_KEEPER");
        _;
    }

    /// @notice checks wether txn sender is governance address
    modifier onlyGovernance() {
        require(msg.sender == governance, "ONLY_GOVERNANCE");
        _;
    }
}

File 2 of 27 : PerpV2Controller.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.7.6;
pragma abicoder v2;

import "./interfaces/IERC20.sol";
import "@perp/curie-contract/contracts/interface/IVault.sol";
import "@perp/curie-contract/contracts/interface/IClearingHouse.sol";
import "@perp/curie-contract/contracts/interface/IAccountBalance.sol";
import "@perp/curie-contract/contracts/interface/IVirtualToken.sol";
import "@perp/curie-contract/contracts/interface/IExchange.sol";
import "@perp/curie-contract/contracts/interface/IClearingHouseConfig.sol";
import "@perp/curie-contract/contracts/interface/IIndexPrice.sol";

import {SafeMathUpgradeable} from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";

/// @title PerpV2Controller
/// @author 0xAd1 and Bapireddy
/// @notice Handles positions on PerpV2
contract PerpV2Controller {
    using SafeMathUpgradeable for uint256;

    /*///////////////////////////////////////////////////////////////
                            GLOBAL IMMUTABLES
    //////////////////////////////////////////////////////////////*/
    uint256 public constant MAX_BPS = 1e4;

    /*///////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/

    /// @notice referralCode to be used while opening positions on Perp
    bytes32 public referralCode;

    /*///////////////////////////////////////////////////////////////
                                EXTERNAL CONTRACTS
    //////////////////////////////////////////////////////////////*/

    /// @notice baseToken address of asset traded on Perp
    IERC20 public baseToken;

    /// @notice quoteToken address on Perp (Settlement token)
    IERC20 public quoteTokenvUSDC;

    /// @notice Address of vault contract on Perp
    IVault public perpVault;

    /// @notice Address of clearingHouse contract on Perp
    IClearingHouse public clearingHouse;

    /// @notice Address of clearingHouseConfig contract on Perp
    IClearingHouseConfig public clearingHouseConfig;

    /// @notice Address of accountBalance contract on Perp
    IAccountBalance public accountBalance;

    /// @notice Address of exchange contract on Perp
    IExchange public exchange;

    /*///////////////////////////////////////////////////////////////
                        DEPOSIT / WITHDRAW LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Deposits wantTokens to Perp Vault
    /// @param _value amount of wantTokens to deposit
    function _depositToPerp(uint256 _value) internal {
        address settlementToken = perpVault.getSettlementToken();
        approveQuoteToken(IERC20(settlementToken), _value);
        perpVault.deposit(settlementToken, _value);
    }

    /// @notice Withdraws wantTokens from Perp Vault
    /// @param _value amount of wantTokens to withdraw
    function _withdrawFromPerp(uint256 _value) internal {
        address settlementToken = perpVault.getSettlementToken();
        perpVault.withdraw(settlementToken, _value);
    }

    /*///////////////////////////////////////////////////////////////
                        OPEN / CLOSE LOGIC
    //////////////////////////////////////////////////////////////*/
    /// @notice Opens short or long position on Perp against baseToken
    /// @param short bool true for short position, false for long position
    /// @param amountIn amount of quoteToken to open position with
    /// @param slippage slippage while opening position
    function _openPositionByAmount(
        bool short,
        uint256 amountIn,
        uint24 slippage
    ) internal returns (int256 positionSize) {
        uint256 price = formatSqrtPriceX96(getMarkTwapPrice());

        uint256 amountOut;
        if (slippage == MAX_BPS) {
            amountOut = 0;
        } else {
            // accounting for the slippage provided
            amountOut = short
                ? amountIn.mul(MAX_BPS + slippage).div(MAX_BPS)
                : amountIn.mul(MAX_BPS - slippage).div(MAX_BPS);

            // As deposit is USDC, amountOut will always be in baseToken terms so division by price.
            amountOut = amountOut.mul(MAX_BPS).div(price);
        }

        IClearingHouse.OpenPositionParams memory params = IClearingHouse
            .OpenPositionParams({
                baseToken: address(baseToken),
                isBaseToQuote: short, // true for short, false for long
                isExactInput: !short, // false for short, true for long
                amount: amountIn,
                oppositeAmountBound: amountOut,
                deadline: block.timestamp,
                sqrtPriceLimitX96: 0,
                referralCode: referralCode
            });

        clearingHouse.openPosition(params);
        return
            accountBalance.getTakerPositionSize(
                address(this),
                address(baseToken)
            );
    }

    /// @notice Closes short or long position on Perp against baseToken
    /// @param slippage slippage while opening position
    function _closePosition(uint256 slippage) internal {
        uint256 price = formatSqrtPriceX96(getMarkTwapPrice());
        uint256 amountOut = (getTotalPerpPositionSize() < 0)
            ? uint256(-1 * getTotalPerpPositionSize())
            : uint256(getTotalPerpPositionSize());

        if (slippage == MAX_BPS) {
            amountOut = 0;
        } else {
            amountOut = (getTotalPerpPositionSize() < 0)
                ? amountOut.mul(MAX_BPS + slippage).div(MAX_BPS)
                : amountOut.mul(MAX_BPS - slippage).div(MAX_BPS);
            amountOut = amountOut.mul(price).div(MAX_BPS);
        }

        IClearingHouse.ClosePositionParams memory params = IClearingHouse
            .ClosePositionParams({
                baseToken: address(baseToken),
                sqrtPriceLimitX96: 0,
                oppositeAmountBound: amountOut,
                deadline: block.timestamp,
                referralCode: referralCode
            });

        clearingHouse.closePosition(params);
    }

    /*///////////////////////////////////////////////////////////////
                            HELPER FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Approves given token to perp vault
    /// @param token token to approve
    /// @param _value amount of tokens to approve
    function approveQuoteToken(IERC20 token, uint256 _value) internal {
        token.approve(address(perpVault), _value);
    }

    /// @notice Formats SqrtX96 amount to regular price with MAX_BPS precision
    /// @param sqrtPriceX96 SqrtX96 amount
    /// @return price formatted output
    function formatSqrtPriceX96(uint160 sqrtPriceX96)
        internal
        view
        returns (uint256 price)
    {
        return
            uint256(sqrtPriceX96).mul(uint256(sqrtPriceX96).mul(MAX_BPS)) >>
            (96 * 2);
    }

    /*///////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Get free collateral available on Perp V2
    /// @return Free collateral available on Perp V2 in quoteToken terms
    function getFreeCollateral() public view returns (uint256) {
        return perpVault.getFreeCollateral(address(this));
    }

    /// @notice Gets mark twap price of Perp's uniswap pool (quoteToken/baseToken)
    /// @return uint160 gets SqrtX96 price
    function getMarkTwapPrice() public view returns (uint160) {
        uint160 twapPrice = exchange.getSqrtMarkTwapX96(
            address(baseToken),
            clearingHouseConfig.getTwapInterval()
        );
        return twapPrice;
    }

    /// @notice Gets index twap price from Perp
    /// @return regular decimal price
    function getIndexTwapPrice() public view returns (uint256) {
        uint256 twapPrice = IIndexPrice(address(baseToken)).getIndexPrice(
            clearingHouseConfig.getTwapInterval()
        );
        return twapPrice;
    }

    /// @notice Returns the size of current position in baseTokens
    /// @return amount size of position in baseTokens
    function getTotalPerpPositionSize() public view returns (int256) {
        return
            accountBalance.getTotalPositionSize(
                address(this),
                address(baseToken)
            );
    }

    /// @notice Returns the value of current position in wantToken value
    /// @return amount value of position in wantToken (USDC)
    function positionInWantToken() public view returns (uint256, uint256) {
        int256 posValue = clearingHouse.getAccountValue(address(this));
        uint256 amountOut = (posValue < 0)
            ? uint256(-1 * posValue)
            : uint256(posValue);
        return (
            amountOut.div(1e12) +
                IERC20(perpVault.getSettlementToken()).balanceOf(address(this)),
            block.number
        );
    }
}

File 3 of 27 : OptimismL2Wrapper.sol
//SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.7.6;

import "./interfaces/CrossDomainMessenger.interface.sol";

contract OptimismL2Wrapper {
    /// @notice Address of Optimism L2CrossDomainMessenger
    /// @dev Address is hardcoded, stays same on L2 mainnet and L2 testnet
    address public L2CrossDomainMessenger =
        0x4200000000000000000000000000000000000007;

    ICrossDomainMessenger public optimismMessenger =
        ICrossDomainMessenger(L2CrossDomainMessenger);

    /// @notice Returns the true sender of transaction sent from Optimism L1CrossDomainMessenger
    /// @return address of sender
    function messageSender() public view returns (address) {
        return optimismMessenger.xDomainMessageSender();
    }
}

File 4 of 27 : SocketV1Controller.sol
//SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IERC20.sol";

/// @title SocketV1Controller
/// @author 0xAd1
/// @notice Used to bridge ERC20 tokens cross chain
contract SocketV1Controller {
    struct MiddlewareRequest {
        uint256 id;
        uint256 optionalNativeAmount;
        address inputToken;
        bytes data;
    }
    struct BridgeRequest {
        uint256 id;
        uint256 optionalNativeAmount;
        address inputToken;
        bytes data;
    }
    struct UserRequest {
        address receiverAddress;
        uint256 toChainId;
        uint256 amount;
        MiddlewareRequest middlewareRequest;
        BridgeRequest bridgeRequest;
    }

    /// @notice Decode the Bungee request calldata
    /// @dev Currently not in use due to undertainity in Bungee api response
    /// @param _data Bungee txn calldata
    /// @return userRequest parsed calldata
    function decodeSocketRegistryCalldata(bytes calldata _data)
        internal
        pure
        returns (UserRequest memory userRequest)
    {
        (userRequest) = abi.decode(_data[4:], (UserRequest));
    }

    function verifySocketCalldata(
        bytes calldata _data,
        uint256 _chainId,
        address _inputToken,
        address _receiverAddress
    ) internal pure {
        UserRequest memory userRequest;
        (userRequest) = decodeSocketRegistryCalldata(_data);
        if (userRequest.toChainId != _chainId) {
            revert("Invalid chainId");
        }
        if (userRequest.receiverAddress != _receiverAddress) {
            revert("Invalid receiver address");
        }
        if (userRequest.bridgeRequest.inputToken != _inputToken) {
            revert("Invalid input token");
        }
    }

    /// @notice Sends tokens using Bungee middleware. Assumes tokens already present in contract. Manages allowance and transfer.
    /// @dev Currently not verifying the middleware request calldata. Use very carefully
    /// @param token address of IERC20 token to be sent
    /// @param allowanceTarget address to allow tokens to swipe
    /// @param socketRegistry address to send bridge txn to
    /// @param destinationAddress address of receiver
    /// @param amount amount of tokens to bridge
    /// @param destinationChainId chain Id of receiving chain
    /// @param data calldata of txn to be sent
    function sendTokens(
        address token,
        address allowanceTarget,
        address socketRegistry,
        address destinationAddress,
        uint256 amount,
        uint256 destinationChainId,
        bytes calldata data
    ) internal {
        verifySocketCalldata(
            data,
            destinationChainId,
            token,
            destinationAddress
        );
        IERC20(token).approve(allowanceTarget, amount);
        (bool success, ) = socketRegistry.call(data);
        require(success, "Failed to call socketRegistry");
    }
}

File 5 of 27 : IPositionHandler.sol
/// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

interface IPositionHandler {
    struct PerpPosition {
        uint256 entryMarkPrice;
        uint256 entryIndexPrice;
        uint256 entryAmount;
        bool isShort;
        bool isActive;
    }

    function openPosition(
        bool _isShort,
        uint256 _amount,
        uint24 _slippage
    ) external;

    function closePosition(uint24 _slippage) external;

    function withdraw(
        uint256 amountOut,
        address allowanceTarget,
        address socketRegistry,
        bytes calldata socketData
    ) external;

    function sweep(address _token) external;
}

File 6 of 27 : SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library 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) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.7.6;

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

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

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

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

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

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

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

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

File 8 of 27 : IVault.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

interface IVault {
    event Deposited(address indexed collateralToken, address indexed trader, uint256 amount);

    event Withdrawn(address indexed collateralToken, address indexed trader, uint256 amount);

    /// @param token the address of the token to deposit;
    ///        once multi-collateral is implemented, the token is not limited to settlementToken
    /// @param amountX10_D the amount of the token to deposit in decimals D (D = _decimals)
    function deposit(address token, uint256 amountX10_D) external;

    /// @param token the address of the token sender is going to withdraw
    ///        once multi-collateral is implemented, the token is not limited to settlementToken
    /// @param amountX10_D the amount of the token to withdraw in decimals D (D = _decimals)
    function withdraw(address token, uint256 amountX10_D) external;

    function getBalance(address account) external view returns (int256);

    /// @param trader The address of the trader to query
    /// @return freeCollateral Max(0, amount of collateral available for withdraw or opening new positions or orders)
    function getFreeCollateral(address trader) external view returns (uint256);

    /// @dev there are three configurations for different insolvency risk tolerances: conservative, moderate, aggressive
    ///      we will start with the conservative one and gradually move to aggressive to increase capital efficiency
    /// @param trader the address of the trader
    /// @param ratio the margin requirement ratio, imRatio or mmRatio
    /// @return freeCollateralByRatio freeCollateral, by using the input margin requirement ratio; can be negative
    function getFreeCollateralByRatio(address trader, uint24 ratio) external view returns (int256);

    function getSettlementToken() external view returns (address);

    /// @dev cached the settlement token's decimal for gas optimization
    function decimals() external view returns (uint8);

    function getTotalDebt() external view returns (uint256);

    function getClearingHouseConfig() external view returns (address);

    function getAccountBalance() external view returns (address);

    function getInsuranceFund() external view returns (address);

    function getExchange() external view returns (address);

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

File 9 of 27 : IClearingHouse.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;
pragma abicoder v2;

interface IClearingHouse {
    /// @param useTakerBalance only accept false now
    struct AddLiquidityParams {
        address baseToken;
        uint256 base;
        uint256 quote;
        int24 lowerTick;
        int24 upperTick;
        uint256 minBase;
        uint256 minQuote;
        bool useTakerBalance;
        uint256 deadline;
    }

    /// @param liquidity collect fee when 0
    struct RemoveLiquidityParams {
        address baseToken;
        int24 lowerTick;
        int24 upperTick;
        uint128 liquidity;
        uint256 minBase;
        uint256 minQuote;
        uint256 deadline;
    }

    struct AddLiquidityResponse {
        uint256 base;
        uint256 quote;
        uint256 fee;
        uint256 liquidity;
    }

    struct RemoveLiquidityResponse {
        uint256 base;
        uint256 quote;
        uint256 fee;
    }

    /// @param oppositeAmountBound
    // B2Q + exact input, want more output quote as possible, so we set a lower bound of output quote
    // B2Q + exact output, want less input base as possible, so we set a upper bound of input base
    // Q2B + exact input, want more output base as possible, so we set a lower bound of output base
    // Q2B + exact output, want less input quote as possible, so we set a upper bound of input quote
    // when it's set to 0, it will disable slippage protection entirely regardless of exact input or output
    // when it's over or under the bound, it will be reverted
    /// @param sqrtPriceLimitX96
    // B2Q: the price cannot be less than this value after the swap
    // Q2B: the price cannot be greater than this value after the swap
    // it will fill the trade until it reaches the price limit but WON'T REVERT
    // when it's set to 0, it will disable price limit;
    // when it's 0 and exact output, the output amount is required to be identical to the param amount
    struct OpenPositionParams {
        address baseToken;
        bool isBaseToQuote;
        bool isExactInput;
        uint256 amount;
        uint256 oppositeAmountBound;
        uint256 deadline;
        uint160 sqrtPriceLimitX96;
        bytes32 referralCode;
    }

    struct ClosePositionParams {
        address baseToken;
        uint160 sqrtPriceLimitX96;
        uint256 oppositeAmountBound;
        uint256 deadline;
        bytes32 referralCode;
    }

    struct CollectPendingFeeParams {
        address trader;
        address baseToken;
        int24 lowerTick;
        int24 upperTick;
    }

    event ReferredPositionChanged(bytes32 indexed referralCode);

    event PositionLiquidated(
        address indexed trader,
        address indexed baseToken,
        uint256 positionNotional,
        uint256 positionSize,
        uint256 liquidationFee,
        address liquidator
    );

    /// @param base the amount of base token added (> 0) / removed (< 0) as liquidity; fees not included
    /// @param quote the amount of quote token added ... (same as the above)
    /// @param liquidity the amount of liquidity unit added (> 0) / removed (< 0)
    /// @param quoteFee the amount of quote token the maker received as fees
    event LiquidityChanged(
        address indexed maker,
        address indexed baseToken,
        address indexed quoteToken,
        int24 lowerTick,
        int24 upperTick,
        int256 base,
        int256 quote,
        int128 liquidity,
        uint256 quoteFee
    );

    event PositionChanged(
        address indexed trader,
        address indexed baseToken,
        int256 exchangedPositionSize,
        int256 exchangedPositionNotional,
        uint256 fee,
        int256 openNotional,
        int256 realizedPnl,
        uint256 sqrtPriceAfterX96
    );

    /// @param fundingPayment > 0: payment, < 0 : receipt
    event FundingPaymentSettled(address indexed trader, address indexed baseToken, int256 fundingPayment);

    event TrustedForwarderChanged(address indexed forwarder);

    /// @dev tx will fail if adding base == 0 && quote == 0 / liquidity == 0
    function addLiquidity(AddLiquidityParams calldata params) external returns (AddLiquidityResponse memory);

    function removeLiquidity(RemoveLiquidityParams calldata params)
        external
        returns (RemoveLiquidityResponse memory response);

    function settleAllFunding(address trader) external;

    function openPosition(OpenPositionParams memory params) external returns (uint256 base, uint256 quote);

    function closePosition(ClosePositionParams calldata params) external returns (uint256 base, uint256 quote);

    /// @notice If trader is underwater, any one can call `liquidate` to liquidate this trader
    /// @dev If trader has open orders, need to call `cancelAllExcessOrders` first
    /// @param trader The address of trader
    /// @param baseToken The address of baseToken
    /// @param oppositeAmountBound please check OpenPositionParams
    /// @return base The amount of baseToken the taker got or spent
    /// @return quote The amount of quoteToken the taker got or spent
    /// @return isPartialClose when it's over price limit return true and only liquidate 25% of the position
    function liquidate(
        address trader,
        address baseToken,
        uint256 oppositeAmountBound
    )
        external
        returns (
            uint256 base,
            uint256 quote,
            bool isPartialClose
        );

    /// @dev This function will be deprecated in the future, recommend to use the function `liquidate()` above
    function liquidate(address trader, address baseToken) external;

    function cancelExcessOrders(
        address maker,
        address baseToken,
        bytes32[] calldata orderIds
    ) external;

    function cancelAllExcessOrders(address maker, address baseToken) external;

    /// @dev accountValue = totalCollateralValue + totalUnrealizedPnl, in 18 decimals
    function getAccountValue(address trader) external view returns (int256);

    function getQuoteToken() external view returns (address);

    function getUniswapV3Factory() external view returns (address);

    function getClearingHouseConfig() external view returns (address);

    function getVault() external view returns (address);

    function getExchange() external view returns (address);

    function getOrderBook() external view returns (address);

    function getAccountBalance() external view returns (address);

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

File 10 of 27 : IAccountBalance.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;
pragma abicoder v2;

import { AccountMarket } from "../lib/AccountMarket.sol";

interface IAccountBalance {
    /// @param vault The address of the vault contract
    event VaultChanged(address indexed vault);

    /// @dev Emit whenever a trader's `owedRealizedPnl` is updated
    /// @param trader The address of the trader
    /// @param amount The amount changed
    event PnlRealized(address indexed trader, int256 amount);

    function modifyTakerBalance(
        address trader,
        address baseToken,
        int256 base,
        int256 quote
    ) external returns (int256, int256);

    function modifyOwedRealizedPnl(address trader, int256 amount) external;

    /// @dev this function is now only called by Vault.withdraw()
    function settleOwedRealizedPnl(address trader) external returns (int256 pnl);

    function settleQuoteToOwedRealizedPnl(
        address trader,
        address baseToken,
        int256 amount
    ) external;

    /// @dev Settle account balance and deregister base token
    /// @param maker The address of the maker
    /// @param baseToken The address of the market's base token
    /// @param realizedPnl Amount of pnl realized
    /// @param fee Amount of fee collected from pool
    function settleBalanceAndDeregister(
        address maker,
        address baseToken,
        int256 takerBase,
        int256 takerQuote,
        int256 realizedPnl,
        int256 fee
    ) external;

    /// @dev every time a trader's position value is checked, the base token list of this trader will be traversed;
    ///      thus, this list should be kept as short as possible
    /// @param trader The address of the trader
    /// @param baseToken The address of the trader's base token
    function registerBaseToken(address trader, address baseToken) external;

    /// @dev this function is expensive
    /// @param trader The address of the trader
    /// @param baseToken The address of the trader's base token
    function deregisterBaseToken(address trader, address baseToken) external;

    function updateTwPremiumGrowthGlobal(
        address trader,
        address baseToken,
        int256 lastTwPremiumGrowthGlobalX96
    ) external;

    function getClearingHouseConfig() external view returns (address);

    function getOrderBook() external view returns (address);

    function getVault() external view returns (address);

    function getBaseTokens(address trader) external view returns (address[] memory);

    function getAccountInfo(address trader, address baseToken) external view returns (AccountMarket.Info memory);

    function getTakerOpenNotional(address trader, address baseToken) external view returns (int256);

    /// @return totalOpenNotional the amount of quote token paid for a position when opening
    function getTotalOpenNotional(address trader, address baseToken) external view returns (int256);

    function getTotalDebtValue(address trader) external view returns (uint256);

    /// @dev this is different from Vault._getTotalMarginRequirement(), which is for freeCollateral calculation
    /// @return int instead of uint, as it is compared with ClearingHouse.getAccountValue(), which is also an int
    function getMarginRequirementForLiquidation(address trader) external view returns (int256);

    /// @return owedRealizedPnl the pnl realized already but stored temporarily in AccountBalance
    /// @return unrealizedPnl the pnl not yet realized
    /// @return pendingFee the pending fee of maker earned
    function getPnlAndPendingFee(address trader)
        external
        view
        returns (
            int256 owedRealizedPnl,
            int256 unrealizedPnl,
            uint256 pendingFee
        );

    function hasOrder(address trader) external view returns (bool);

    function getBase(address trader, address baseToken) external view returns (int256);

    function getQuote(address trader, address baseToken) external view returns (int256);

    function getTakerPositionSize(address trader, address baseToken) external view returns (int256);

    function getTotalPositionSize(address trader, address baseToken) external view returns (int256);

    /// @dev a negative returned value is only be used when calculating pnl
    /// @dev we use 15 mins twap to calc position value
    function getTotalPositionValue(address trader, address baseToken) external view returns (int256);

    /// @return sum up positions value of every market, it calls `getTotalPositionValue` internally
    function getTotalAbsPositionValue(address trader) external view returns (uint256);
}

File 11 of 27 : IVirtualToken.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

interface IVirtualToken {
    function isInWhitelist(address account) external view returns (bool);
}

File 12 of 27 : IExchange.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;
pragma abicoder v2;

import { Funding } from "../lib/Funding.sol";

interface IExchange {
    /// @param amount when closing position, amount(uint256) == takerPositionSize(int256),
    ///        as amount is assigned as takerPositionSize in ClearingHouse.closePosition()
    struct SwapParams {
        address trader;
        address baseToken;
        bool isBaseToQuote;
        bool isExactInput;
        bool isClose;
        uint256 amount;
        uint160 sqrtPriceLimitX96;
    }

    struct SwapResponse {
        uint256 base;
        uint256 quote;
        int256 exchangedPositionSize;
        int256 exchangedPositionNotional;
        uint256 fee;
        uint256 insuranceFundFee;
        int256 pnlToBeRealized;
        uint256 sqrtPriceAfterX96;
        int24 tick;
        bool isPartialClose;
    }

    struct SwapCallbackData {
        address trader;
        address baseToken;
        address pool;
        uint24 uniswapFeeRatio;
        uint256 fee;
    }

    struct RealizePnlParams {
        address trader;
        address baseToken;
        int256 base;
        int256 quote;
    }

    event FundingUpdated(address indexed baseToken, uint256 markTwap, uint256 indexTwap);

    event MaxTickCrossedWithinBlockChanged(address indexed baseToken, uint24 maxTickCrossedWithinBlock);

    /// @param accountBalance The address of accountBalance contract
    event AccountBalanceChanged(address accountBalance);

    function swap(SwapParams memory params) external returns (SwapResponse memory);

    /// @dev this function should be called at the beginning of every high-level function, such as openPosition()
    ///      while it doesn't matter who calls this function
    ///      this function 1. settles personal funding payment 2. updates global funding growth
    ///      personal funding payment is settled whenever there is pending funding payment
    ///      the global funding growth update only happens once per unique timestamp (not blockNumber, due to Arbitrum)
    /// @return fundingPayment the funding payment of a trader in one market should be settled into owned realized Pnl
    /// @return fundingGrowthGlobal the up-to-date globalFundingGrowth, usually used for later calculations
    function settleFunding(address trader, address baseToken)
        external
        returns (int256 fundingPayment, Funding.Growth memory fundingGrowthGlobal);

    function getMaxTickCrossedWithinBlock(address baseToken) external view returns (uint24);

    function getAllPendingFundingPayment(address trader) external view returns (int256);

    /// @dev this is the view version of _updateFundingGrowth()
    /// @return the pending funding payment of a trader in one market, including liquidity & balance coefficients
    function getPendingFundingPayment(address trader, address baseToken) external view returns (int256);

    function getSqrtMarkTwapX96(address baseToken, uint32 twapInterval) external view returns (uint160);

    function getPnlToBeRealized(RealizePnlParams memory params) external view returns (int256);

    function getOrderBook() external view returns (address);

    function getAccountBalance() external view returns (address);

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

File 13 of 27 : IClearingHouseConfig.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

interface IClearingHouseConfig {
    function getMaxMarketsPerAccount() external view returns (uint8);

    function getImRatio() external view returns (uint24);

    function getMmRatio() external view returns (uint24);

    function getLiquidationPenaltyRatio() external view returns (uint24);

    function getPartialCloseRatio() external view returns (uint24);

    /// @return twapInterval for funding and prices (mark & index) calculations
    function getTwapInterval() external view returns (uint32);

    function getSettlementTokenBalanceCap() external view returns (uint256);

    function getMaxFundingRate() external view returns (uint24);

    function isBackstopLiquidityProvider(address account) external view returns (bool);
}

File 14 of 27 : IIndexPrice.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

interface IIndexPrice {
    /// @dev Returns the index price of the token.
    /// @param interval The interval represents twap interval.
    function getIndexPrice(uint256 interval) external view returns (uint256);
}

File 15 of 27 : AccountMarket.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

library AccountMarket {
    /// @param lastTwPremiumGrowthGlobalX96 the last time weighted premiumGrowthGlobalX96
    struct Info {
        int256 takerPositionSize;
        int256 takerOpenNotional;
        int256 lastTwPremiumGrowthGlobalX96;
    }
}

File 16 of 27 : Funding.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

import { Tick } from "./Tick.sol";
import { PerpMath } from "./PerpMath.sol";
import { OpenOrder } from "./OpenOrder.sol";
import { PerpSafeCast } from "./PerpSafeCast.sol";
import { PerpFixedPoint96 } from "./PerpFixedPoint96.sol";
import { TickMath } from "@uniswap/v3-core/contracts/libraries/TickMath.sol";
import { LiquidityAmounts } from "@uniswap/v3-periphery/contracts/libraries/LiquidityAmounts.sol";
import { SignedSafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol";

library Funding {
    using PerpSafeCast for uint256;
    using PerpSafeCast for uint128;
    using SignedSafeMathUpgradeable for int256;

    //
    // STRUCT
    //

    /// @dev tw: time-weighted
    /// @param twPremiumX96 overflow inspection (as twPremiumX96 > twPremiumDivBySqrtPriceX96):
    //         max = 2 ^ (255 - 96) = 2 ^ 159 = 7.307508187E47
    //         assume premium = 10000, time = 10 year = 60 * 60 * 24 * 365 * 10 -> twPremium = 3.1536E12
    struct Growth {
        int256 twPremiumX96;
        int256 twPremiumDivBySqrtPriceX96;
    }

    //
    // CONSTANT
    //

    /// @dev block-based funding is calculated as: premium * timeFraction / 1 day, for 1 day as the default period
    int256 internal constant _DEFAULT_FUNDING_PERIOD = 1 days;

    //
    // INTERNAL PURE
    //

    function calcPendingFundingPaymentWithLiquidityCoefficient(
        int256 baseBalance,
        int256 twPremiumGrowthGlobalX96,
        Growth memory fundingGrowthGlobal,
        int256 liquidityCoefficientInFundingPayment
    ) internal pure returns (int256) {
        int256 balanceCoefficientInFundingPayment =
            PerpMath.mulDiv(
                baseBalance,
                fundingGrowthGlobal.twPremiumX96.sub(twPremiumGrowthGlobalX96),
                uint256(PerpFixedPoint96._IQ96)
            );

        return
            liquidityCoefficientInFundingPayment.add(balanceCoefficientInFundingPayment).div(_DEFAULT_FUNDING_PERIOD);
    }

    /// @dev the funding payment of an order/liquidity is composed of
    ///      1. funding accrued inside the range 2. funding accrued below the range
    ///      there is no funding when the price goes above the range, as liquidity is all swapped into quoteToken
    /// @return liquidityCoefficientInFundingPayment the funding payment of an order/liquidity
    function calcLiquidityCoefficientInFundingPaymentByOrder(
        OpenOrder.Info memory order,
        Tick.FundingGrowthRangeInfo memory fundingGrowthRangeInfo
    ) internal pure returns (int256) {
        uint160 sqrtPriceX96AtUpperTick = TickMath.getSqrtRatioAtTick(order.upperTick);

        // base amount below the range
        uint256 baseAmountBelow =
            LiquidityAmounts.getAmount0ForLiquidity(
                TickMath.getSqrtRatioAtTick(order.lowerTick),
                sqrtPriceX96AtUpperTick,
                order.liquidity
            );
        // funding below the range
        int256 fundingBelowX96 =
            baseAmountBelow.toInt256().mul(
                fundingGrowthRangeInfo.twPremiumGrowthBelowX96.sub(order.lastTwPremiumGrowthBelowX96)
            );

        // funding inside the range =
        // liquidity * (ΔtwPremiumDivBySqrtPriceGrowthInsideX96 - ΔtwPremiumGrowthInsideX96 / sqrtPriceAtUpperTick)
        int256 fundingInsideX96 =
            order.liquidity.toInt256().mul(
                // ΔtwPremiumDivBySqrtPriceGrowthInsideX96
                fundingGrowthRangeInfo
                    .twPremiumDivBySqrtPriceGrowthInsideX96
                    .sub(order.lastTwPremiumDivBySqrtPriceGrowthInsideX96)
                    .sub(
                    // ΔtwPremiumGrowthInsideX96
                    PerpMath.mulDiv(
                        fundingGrowthRangeInfo.twPremiumGrowthInsideX96.sub(order.lastTwPremiumGrowthInsideX96),
                        PerpFixedPoint96._IQ96,
                        sqrtPriceX96AtUpperTick
                    )
                )
            );

        return fundingBelowX96.add(fundingInsideX96).div(PerpFixedPoint96._IQ96);
    }
}

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

library Tick {
    struct GrowthInfo {
        uint256 feeX128;
        int256 twPremiumX96;
        int256 twPremiumDivBySqrtPriceX96;
    }

    struct FundingGrowthRangeInfo {
        int256 twPremiumGrowthInsideX96;
        int256 twPremiumGrowthBelowX96;
        int256 twPremiumDivBySqrtPriceGrowthInsideX96;
    }

    /// @dev call this function only if (liquidityGrossBefore == 0 && liquidityDelta != 0)
    /// @dev per Uniswap: we assume that all growths before a tick is initialized happen "below" the tick
    function initialize(
        mapping(int24 => GrowthInfo) storage self,
        int24 tick,
        int24 currentTick,
        GrowthInfo memory globalGrowthInfo
    ) internal {
        if (tick <= currentTick) {
            GrowthInfo storage growthInfo = self[tick];
            growthInfo.feeX128 = globalGrowthInfo.feeX128;
            growthInfo.twPremiumX96 = globalGrowthInfo.twPremiumX96;
            growthInfo.twPremiumDivBySqrtPriceX96 = globalGrowthInfo.twPremiumDivBySqrtPriceX96;
        }
    }

    function cross(
        mapping(int24 => GrowthInfo) storage self,
        int24 tick,
        GrowthInfo memory globalGrowthInfo
    ) internal {
        GrowthInfo storage growthInfo = self[tick];
        growthInfo.feeX128 = globalGrowthInfo.feeX128 - growthInfo.feeX128;
        growthInfo.twPremiumX96 = globalGrowthInfo.twPremiumX96 - growthInfo.twPremiumX96;
        growthInfo.twPremiumDivBySqrtPriceX96 =
            globalGrowthInfo.twPremiumDivBySqrtPriceX96 -
            growthInfo.twPremiumDivBySqrtPriceX96;
    }

    function clear(mapping(int24 => GrowthInfo) storage self, int24 tick) internal {
        delete self[tick];
    }

    /// @dev all values in this function are scaled by 2^128 (X128), thus adding the suffix to external params
    /// @return feeGrowthInsideX128 this value can underflow per Tick.feeGrowthOutside specs
    function getFeeGrowthInsideX128(
        mapping(int24 => GrowthInfo) storage self,
        int24 lowerTick,
        int24 upperTick,
        int24 currentTick,
        uint256 feeGrowthGlobalX128
    ) internal view returns (uint256 feeGrowthInsideX128) {
        uint256 lowerFeeGrowthOutside = self[lowerTick].feeX128;
        uint256 upperFeeGrowthOutside = self[upperTick].feeX128;

        uint256 feeGrowthBelow =
            currentTick >= lowerTick ? lowerFeeGrowthOutside : feeGrowthGlobalX128 - lowerFeeGrowthOutside;
        uint256 feeGrowthAbove =
            currentTick < upperTick ? upperFeeGrowthOutside : feeGrowthGlobalX128 - upperFeeGrowthOutside;

        return feeGrowthGlobalX128 - feeGrowthBelow - feeGrowthAbove;
    }

    /// @return all values returned can underflow per feeGrowthOutside specs;
    ///         see https://www.notion.so/32990980ba8b43859f6d2541722a739b
    function getAllFundingGrowth(
        mapping(int24 => GrowthInfo) storage self,
        int24 lowerTick,
        int24 upperTick,
        int24 currentTick,
        int256 twPremiumGrowthGlobalX96,
        int256 twPremiumDivBySqrtPriceGrowthGlobalX96
    ) internal view returns (FundingGrowthRangeInfo memory) {
        GrowthInfo storage lowerTickGrowthInfo = self[lowerTick];
        GrowthInfo storage upperTickGrowthInfo = self[upperTick];

        int256 lowerTwPremiumGrowthOutsideX96 = lowerTickGrowthInfo.twPremiumX96;
        int256 upperTwPremiumGrowthOutsideX96 = upperTickGrowthInfo.twPremiumX96;

        FundingGrowthRangeInfo memory fundingGrowthRangeInfo;
        fundingGrowthRangeInfo.twPremiumGrowthBelowX96 = currentTick >= lowerTick
            ? lowerTwPremiumGrowthOutsideX96
            : twPremiumGrowthGlobalX96 - lowerTwPremiumGrowthOutsideX96;
        int256 twPremiumGrowthAboveX96 =
            currentTick < upperTick
                ? upperTwPremiumGrowthOutsideX96
                : twPremiumGrowthGlobalX96 - upperTwPremiumGrowthOutsideX96;

        int256 lowerTwPremiumDivBySqrtPriceGrowthOutsideX96 = lowerTickGrowthInfo.twPremiumDivBySqrtPriceX96;
        int256 upperTwPremiumDivBySqrtPriceGrowthOutsideX96 = upperTickGrowthInfo.twPremiumDivBySqrtPriceX96;

        int256 twPremiumDivBySqrtPriceGrowthBelowX96 =
            currentTick >= lowerTick
                ? lowerTwPremiumDivBySqrtPriceGrowthOutsideX96
                : twPremiumDivBySqrtPriceGrowthGlobalX96 - lowerTwPremiumDivBySqrtPriceGrowthOutsideX96;
        int256 twPremiumDivBySqrtPriceGrowthAboveX96 =
            currentTick < upperTick
                ? upperTwPremiumDivBySqrtPriceGrowthOutsideX96
                : twPremiumDivBySqrtPriceGrowthGlobalX96 - upperTwPremiumDivBySqrtPriceGrowthOutsideX96;

        fundingGrowthRangeInfo.twPremiumGrowthInsideX96 =
            twPremiumGrowthGlobalX96 -
            fundingGrowthRangeInfo.twPremiumGrowthBelowX96 -
            twPremiumGrowthAboveX96;
        fundingGrowthRangeInfo.twPremiumDivBySqrtPriceGrowthInsideX96 =
            twPremiumDivBySqrtPriceGrowthGlobalX96 -
            twPremiumDivBySqrtPriceGrowthBelowX96 -
            twPremiumDivBySqrtPriceGrowthAboveX96;

        return fundingGrowthRangeInfo;
    }
}

File 18 of 27 : PerpMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;
pragma abicoder v2;

import { FixedPoint96 } from "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol";
import { FullMath } from "@uniswap/v3-core/contracts/libraries/FullMath.sol";
import { PerpSafeCast } from "./PerpSafeCast.sol";
import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import { SignedSafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol";

library PerpMath {
    using PerpSafeCast for int256;
    using SignedSafeMathUpgradeable for int256;
    using SafeMathUpgradeable for uint256;

    function formatSqrtPriceX96ToPriceX96(uint160 sqrtPriceX96) internal pure returns (uint256) {
        return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);
    }

    function formatX10_18ToX96(uint256 valueX10_18) internal pure returns (uint256) {
        return FullMath.mulDiv(valueX10_18, FixedPoint96.Q96, 1 ether);
    }

    function formatX96ToX10_18(uint256 valueX96) internal pure returns (uint256) {
        return FullMath.mulDiv(valueX96, 1 ether, FixedPoint96.Q96);
    }

    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 abs(int256 value) internal pure returns (uint256) {
        return value >= 0 ? value.toUint256() : neg256(value).toUint256();
    }

    function neg256(int256 a) internal pure returns (int256) {
        require(a > -2**255, "PerpMath: inversion overflow");
        return -a;
    }

    function neg256(uint256 a) internal pure returns (int256) {
        return -PerpSafeCast.toInt256(a);
    }

    function neg128(int128 a) internal pure returns (int128) {
        require(a > -2**127, "PerpMath: inversion overflow");
        return -a;
    }

    function neg128(uint128 a) internal pure returns (int128) {
        return -PerpSafeCast.toInt128(a);
    }

    function divBy10_18(int256 value) internal pure returns (int256) {
        // no overflow here
        return value / (1 ether);
    }

    function divBy10_18(uint256 value) internal pure returns (uint256) {
        // no overflow here
        return value / (1 ether);
    }

    function mulRatio(uint256 value, uint24 ratio) internal pure returns (uint256) {
        return FullMath.mulDiv(value, ratio, 1e6);
    }

    /// @param denominator cannot be 0 and is checked in FullMath.mulDiv()
    function mulDiv(
        int256 a,
        int256 b,
        uint256 denominator
    ) internal pure returns (int256 result) {
        uint256 unsignedA = a < 0 ? uint256(neg256(a)) : uint256(a);
        uint256 unsignedB = b < 0 ? uint256(neg256(b)) : uint256(b);
        bool negative = ((a < 0 && b > 0) || (a > 0 && b < 0)) ? true : false;

        uint256 unsignedResult = FullMath.mulDiv(unsignedA, unsignedB, denominator);

        result = negative ? neg256(unsignedResult) : PerpSafeCast.toInt256(unsignedResult);

        return result;
    }
}

File 19 of 27 : OpenOrder.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

library OpenOrder {
    /// @param lastFeeGrowthInsideX128 fees in quote token recorded in Exchange
    ///        because of block-based funding, quote-only and customized fee, all fees are in quote token
    struct Info {
        uint128 liquidity;
        int24 lowerTick;
        int24 upperTick;
        uint256 lastFeeGrowthInsideX128;
        int256 lastTwPremiumGrowthInsideX96;
        int256 lastTwPremiumGrowthBelowX96;
        int256 lastTwPremiumDivBySqrtPriceGrowthInsideX96;
        uint256 baseDebt;
        uint256 quoteDebt;
    }

    function calcOrderKey(
        address trader,
        address baseToken,
        int24 lowerTick,
        int24 upperTick
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(trader, baseToken, lowerTick, upperTick));
    }
}

File 20 of 27 : PerpSafeCast.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;

/**
 * @dev copy from "@openzeppelin/contracts-upgradeable/utils/SafeCastUpgradeable.sol"
 * and rename to avoid naming conflict with uniswap
 */
library PerpSafeCast {
    /**
     * @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 returnValue) {
        require(((returnValue = uint128(value)) == value), "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = uint64(value)) == value), "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = uint32(value)) == value), "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = uint16(value)) == value), "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = uint8(value)) == value), "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = int128(value)) == value), "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = int64(value)) == value), "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = int32(value)) == value), "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = int16(value)) == value), "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @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 returnValue) {
        require(((returnValue = int8(value)) == value), "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @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) {
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }

    /**
     * @dev Returns the downcasted uint24 from int256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0 and into 24 bit.
     */
    function toUint24(int256 value) internal pure returns (uint24 returnValue) {
        require(
            ((returnValue = uint24(value)) == value),
            "SafeCast: value must be positive or value doesn't fit in an 24 bits"
        );
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 returnValue) {
        require(((returnValue = int24(value)) == value), "SafeCast: value doesn't fit in an 24 bits");
    }
}

File 21 of 27 : PerpFixedPoint96.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.6;

library PerpFixedPoint96 {
    int256 internal constant _IQ96 = 0x1000000000000000000000000;
}

File 22 of 27 : TickMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0 <0.8.0;

/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
    int24 internal constant MIN_TICK = -887272;
    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
    int24 internal constant MAX_TICK = -MIN_TICK;

    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
    uint160 internal constant MIN_SQRT_RATIO = 4295128739;
    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

    /// @notice Calculates sqrt(1.0001^tick) * 2^96
    /// @dev Throws if |tick| > max tick
    /// @param tick The input tick for the above formula
    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
    /// at the given tick
    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
        require(absTick <= uint256(MAX_TICK), 'T');

        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

        if (tick > 0) ratio = type(uint256).max / ratio;

        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint
        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent
        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
    }

    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
    /// ever return.
    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
        // second inequality must be < because the price can never reach the price at the max tick
        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');
        uint256 ratio = uint256(sqrtPriceX96) << 32;

        uint256 r = ratio;
        uint256 msb = 0;

        assembly {
            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(5, gt(r, 0xFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(4, gt(r, 0xFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(3, gt(r, 0xFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(2, gt(r, 0xF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(1, gt(r, 0x3))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := gt(r, 0x1)
            msb := or(msb, f)
        }

        if (msb >= 128) r = ratio >> (msb - 127);
        else r = ratio << (127 - msb);

        int256 log_2 = (int256(msb) - 128) << 64;

        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(63, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(62, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(61, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(60, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(59, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(58, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(57, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(56, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(55, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(54, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(53, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(52, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(51, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(50, f))
        }

        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number

        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);

        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
    }
}

File 23 of 27 : LiquidityAmounts.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

import '@uniswap/v3-core/contracts/libraries/FullMath.sol';
import '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';

/// @title Liquidity amount functions
/// @notice Provides functions for computing liquidity amounts from token amounts and prices
library LiquidityAmounts {
    /// @notice Downcasts uint256 to uint128
    /// @param x The uint258 to be downcasted
    /// @return y The passed value, downcasted to uint128
    function toUint128(uint256 x) private pure returns (uint128 y) {
        require((y = uint128(x)) == x);
    }

    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range
    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount0 The amount0 being sent in
    /// @return liquidity The amount of returned liquidity
    function getLiquidityForAmount0(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount0
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);
        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));
    }

    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range
    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount1 The amount1 being sent in
    /// @return liquidity The amount of returned liquidity
    function getLiquidityForAmount1(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount1
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));
    }

    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current
    /// pool prices and the prices at the tick boundaries
    /// @param sqrtRatioX96 A sqrt price representing the current pool prices
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount0 The amount of token0 being sent in
    /// @param amount1 The amount of token1 being sent in
    /// @return liquidity The maximum amount of liquidity received
    function getLiquidityForAmounts(
        uint160 sqrtRatioX96,
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount0,
        uint256 amount1
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        if (sqrtRatioX96 <= sqrtRatioAX96) {
            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
        } else if (sqrtRatioX96 < sqrtRatioBX96) {
            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);

            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
        } else {
            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
        }
    }

    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount0 The amount of token0
    function getAmount0ForLiquidity(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount0) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        return
            FullMath.mulDiv(
                uint256(liquidity) << FixedPoint96.RESOLUTION,
                sqrtRatioBX96 - sqrtRatioAX96,
                sqrtRatioBX96
            ) / sqrtRatioAX96;
    }

    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount1 The amount of token1
    function getAmount1ForLiquidity(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount1) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);
    }

    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current
    /// pool prices and the prices at the tick boundaries
    /// @param sqrtRatioX96 A sqrt price representing the current pool prices
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount0 The amount of token0
    /// @return amount1 The amount of token1
    function getAmountsForLiquidity(
        uint160 sqrtRatioX96,
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount0, uint256 amount1) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        if (sqrtRatioX96 <= sqrtRatioAX96) {
            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
        } else if (sqrtRatioX96 < sqrtRatioBX96) {
            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);
            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);
        } else {
            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
        }
    }
}

File 24 of 27 : SignedSafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMathUpgradeable {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @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) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @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. 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(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @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) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

    /**
     * @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) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

        return c;
    }
}

File 25 of 27 : FixedPoint96.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.4.0;

/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
    uint8 internal constant RESOLUTION = 96;
    uint256 internal constant Q96 = 0x1000000000000000000000000;
}

File 26 of 27 : FullMath.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.0 <0.8.0;

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 512-bit multiply [prod1 prod0] = a * b
        // Compute the product mod 2**256 and mod 2**256 - 1
        // then use the Chinese Remainder Theorem to reconstruct
        // the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2**256 + prod0
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(a, b, not(0))
            prod0 := mul(a, b)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        // Handle non-overflow cases, 256 by 256 division
        if (prod1 == 0) {
            require(denominator > 0);
            assembly {
                result := div(prod0, denominator)
            }
            return result;
        }

        // Make sure the result is less than 2**256.
        // Also prevents denominator == 0
        require(denominator > prod1);

        ///////////////////////////////////////////////
        // 512 by 256 division.
        ///////////////////////////////////////////////

        // Make division exact by subtracting the remainder from [prod1 prod0]
        // Compute remainder using mulmod
        uint256 remainder;
        assembly {
            remainder := mulmod(a, b, denominator)
        }
        // Subtract 256 bit number from 512 bit number
        assembly {
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }

        // Factor powers of two out of denominator
        // Compute largest power of two divisor of denominator.
        // Always >= 1.
        uint256 twos = -denominator & denominator;
        // Divide denominator by power of two
        assembly {
            denominator := div(denominator, twos)
        }

        // Divide [prod1 prod0] by the factors of two
        assembly {
            prod0 := div(prod0, twos)
        }
        // Shift in bits from prod1 into prod0. For this we need
        // to flip `twos` such that it is 2**256 / twos.
        // If twos is zero, then it becomes one
        assembly {
            twos := add(div(sub(0, twos), twos), 1)
        }
        prod0 |= prod1 * twos;

        // Invert denominator mod 2**256
        // Now that denominator is an odd number, it has an inverse
        // modulo 2**256 such that denominator * inv = 1 mod 2**256.
        // Compute the inverse by starting with a seed that is correct
        // correct for four bits. That is, denominator * inv = 1 mod 2**4
        uint256 inv = (3 * denominator) ^ 2;
        // Now use Newton-Raphson iteration to improve the precision.
        // Thanks to Hensel's lifting lemma, this also works in modular
        // arithmetic, doubling the correct bits in each step.
        inv *= 2 - denominator * inv; // inverse mod 2**8
        inv *= 2 - denominator * inv; // inverse mod 2**16
        inv *= 2 - denominator * inv; // inverse mod 2**32
        inv *= 2 - denominator * inv; // inverse mod 2**64
        inv *= 2 - denominator * inv; // inverse mod 2**128
        inv *= 2 - denominator * inv; // inverse mod 2**256

        // Because the division is now exact we can divide by multiplying
        // with the modular inverse of denominator. This will give us the
        // correct result modulo 2**256. Since the precoditions guarantee
        // that the outcome is less than 2**256, this is the final result.
        // We don't need to compute the high bits of the result and prod1
        // is no longer required.
        result = prod0 * inv;
        return result;
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        result = mulDiv(a, b, denominator);
        if (mulmod(a, b, denominator) > 0) {
            require(result < type(uint256).max);
            result++;
        }
    }
}

File 27 of 27 : CrossDomainMessenger.interface.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;

/**
 * @title ICrossDomainMessenger
 */
interface ICrossDomainMessenger {
    /********************
     * View Functions *
     ********************/

    function receivedMessages(bytes32 messageHash) external view returns (bool);

    function sentMessages(bytes32 messageHash) external view returns (bool);

    function targetMessengerAddress() external view returns (address);

    function messageNonce() external view returns (uint256);

    function xDomainMessageSender() external view returns (address);

    /********************
     * Public Functions *
     ********************/

    /**
     * Sets the target messenger address.
     * @param _targetMessengerAddress New messenger address.
     */
    function setTargetMessengerAddress(address _targetMessengerAddress)
        external;

    /**
     * Sends a cross domain message to the target messenger.
     * @param _target Target contract address.
     * @param _message Message to send to the target.
     * @param _gasLimit Gas limit for the provided message.
     */
    function sendMessage(
        address _target,
        bytes calldata _message,
        uint32 _gasLimit
    ) external;
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_wantTokenL1","type":"address"},{"internalType":"address","name":"_wantTokenL2","type":"address"},{"internalType":"address","name":"_positionHandlerL1","type":"address"},{"internalType":"address","name":"_perpVault","type":"address"},{"internalType":"address","name":"_clearingHouse","type":"address"},{"internalType":"address","name":"_clearingHouseConfig","type":"address"},{"internalType":"address","name":"_accountBalance","type":"address"},{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"address","name":"_baseToken","type":"address"},{"internalType":"address","name":"_quoteTokenvUSDC","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_socketRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernance","type":"address"}],"name":"UpdatedGovernance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldKeeper","type":"address"},{"indexed":true,"internalType":"address","name":"newKeeper","type":"address"}],"name":"UpdatedKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"oldReferral","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newReferral","type":"bytes32"}],"name":"UpdatedPerpReferral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRegistry","type":"address"},{"indexed":true,"internalType":"address","name":"newRegistry","type":"address"}],"name":"UpdatedSocketRegistry","type":"event"},{"inputs":[],"name":"L2CrossDomainMessenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accountBalance","outputs":[{"internalType":"contract IAccountBalance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clearingHouse","outputs":[{"internalType":"contract IClearingHouse","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clearingHouseConfig","outputs":[{"internalType":"contract IClearingHouseConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"slippage","type":"uint24"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchange","outputs":[{"internalType":"contract IExchange","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFreeCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIndexTwapPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarkTwapPrice","outputs":[{"internalType":"uint160","name":"","type":"uint160"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPerpPositionSize","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isShort","type":"bool"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint24","name":"slippage","type":"uint24"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"optimismMessenger","outputs":[{"internalType":"contract ICrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpPosition","outputs":[{"internalType":"uint256","name":"entryMarkPrice","type":"uint256"},{"internalType":"uint256","name":"entryIndexPrice","type":"uint256"},{"internalType":"uint256","name":"entryAmount","type":"uint256"},{"internalType":"bool","name":"isShort","type":"bool"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"perpVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionHandlerL1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionInWantToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteTokenvUSDC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralCode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_referralCode","type":"bytes32"}],"name":"setReferralCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_socketRegistry","type":"address"}],"name":"setSocketRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"socketRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wantTokenL1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wantTokenL2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"address","name":"_socketRegistry","type":"address"},{"internalType":"bytes","name":"socketData","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600880546001600160a01b03199081167342000000000000000000000000000000000000071791829055600980549091166001600160a01b039290921691909117905534801561005357600080fd5b506040516122e83803806122e883398181016040526101a081101561007757600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e08801516101008901516101208a01516101408b01516101608c0151610180909c0151600a80546001600160a01b03199081166001600160a01b039e8f1617909155600b805482169c8e169c909c17909b55600c80548c169a8d169a909a17909955600380548b16988c1698909817909755600480548a16968b1696909617909555600580548916948a169490941790935560068054881692891692909217909155600780548716918816919091179055600180548616918716919091179055600280548516918616919091179055600e80548416918516919091179055600f8054831694841694909417909355600d805490911691909216179055612144806101a46000396000f3fe608060405234801561001057600080fd5b50600436106101c65760003560e01c8063999d5c69116100fa578063c55dae631161009d578063c55dae631461043a578063c81f2c3014610442578063d0e196b91461044a578063d2f7265a1461047a578063d67bdd2514610482578063d8b6d2521461048a578063ea32afae14610492578063f39c38a01461049a578063fd967f47146104a2576101c6565b8063999d5c6914610321578063a7b7e98814610342578063ab033ea9146103d2578063aced1661146103f8578063ad71b23a14610400578063b0a1c1c414610422578063b3d320101461042a578063c2075b2114610432576101c6565b80634c8ac3381161016d5780634c8ac3381461026e5780635aa6e675146102765780636273010d1461027e5780636f18741714610286578063748747e61461028e5780638b860e65146102b45780638dc7d733146102bc5780638faef7bd146102c457806394f6abfc146102fb576101c6565b806301681a62146101cb5780630af96800146101f3578063209c69d914610217578063238efcbc1461021f57806324205697146102275780632d5aa3ad1461022f5780633a43af111461024c5780634486c58b14610254575b600080fd5b6101f1600480360360208110156101e157600080fd5b50356001600160a01b03166104aa565b005b6101fb610602565b604080516001600160a01b039092168252519081900360200190f35b6101fb610611565b6101f1610620565b6101fb6106d4565b6101f16004803603602081101561024557600080fd5b50356106e3565b6101fb610776565b61025c61087e565b60408051918252519081900360200190f35b6101fb610979565b6101fb610988565b6101fb610997565b61025c6109a6565b6101f1600480360360208110156102a457600080fd5b50356001600160a01b0316610a2c565b6101fb610ad9565b6101fb610ae8565b6102cc610af7565b604080519586526020860194909452848401929092521515606084015215156080830152519081900360a00190f35b6101f16004803603602081101561031157600080fd5b50356001600160a01b0316610b12565b610329610bbf565b6040805192835260208301919091528051918290030190f35b6101f16004803603608081101561035857600080fd5b8135916001600160a01b0360208201358116926040830135909116919081019060808101606082013564010000000081111561039357600080fd5b8201836020820111156103a557600080fd5b803590602001918460018302840111640100000000831117156103c757600080fd5b509092509050610d79565b6101f1600480360360208110156103e857600080fd5b50356001600160a01b0316610f48565b6101fb610fbb565b6101f16004803603602081101561041657600080fd5b503562ffffff16610fca565b6101fb6110d1565b6101fb6110e0565b6101fb6110ef565b6101fb6110fe565b61025c61110d565b6101f16004803603606081101561046057600080fd5b5080351515906020810135906040013562ffffff16611145565b6101fb611333565b6101fb611342565b61025c6113b8565b6101fb6113be565b6101fb6113cd565b61025c6113dc565b600f546001600160a01b031633146104fb576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b806001600160a01b031663a9059cbb33836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561055857600080fd5b505afa15801561056c573d6000803e3d6000fd5b505050506040513d602081101561058257600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156105d357600080fd5b505af11580156105e7573d6000803e3d6000fd5b505050506040513d60208110156105fd57600080fd5b505050565b6004546001600160a01b031681565b6002546001600160a01b031681565b601054600f546040516001600160a01b0392831692909116907fff0b32b909f3fb702fe6ac1f682adcca675b9dfaa03ad8f46b4b17c4058a93fc90600090a36010546001600160a01b031633146106b0576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b601054600f80546001600160a01b0319166001600160a01b03909216919091179055565b6009546001600160a01b031681565b600f546001600160a01b03163314610734576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b600054604080519182526020820183905280517ff003b49d650ea18e23aa3dc5c1042bcde96ef01a3d7f87a5980eeba74420cb799281900390910190a1600055565b60075460015460055460408051633e742e3b60e01b8152905160009485946001600160a01b03918216946399e4a7719491831693921691633e742e3b91600480820192602092909190829003018186803b1580156107d357600080fd5b505afa1580156107e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080b9190611e9a565b6040518363ffffffff1660e01b8152600401610828929190611f15565b60206040518083038186803b15801561084057600080fd5b505afa158015610854573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108789190611d62565b91505090565b60015460055460408051633e742e3b60e01b8152905160009384936001600160a01b03918216936312080647939190921691633e742e3b916004808301926020929190829003018186803b1580156108d557600080fd5b505afa1580156108e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090d9190611e9a565b6040518263ffffffff1660e01b8152600401610929919061209f565b60206040518083038186803b15801561094157600080fd5b505afa158015610955573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108789190611d9e565b600a546001600160a01b031681565b600f546001600160a01b031681565b6003546001600160a01b031681565b6003546040516330e6651160e21b81526000916001600160a01b03169063c3999444906109d7903090600401611ece565b60206040518083038186803b1580156109ef57600080fd5b505afa158015610a03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a279190611d9e565b905090565b600f546001600160a01b03163314610a7d576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b600e546040516001600160a01b038084169216907f60ed9ffad04b70bf58c43b18d1f0e54642250116c1137ac1cc4831449124350890600090a3600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6008546001600160a01b031681565b600c546001600160a01b031681565b60115460125460135460145460ff8082169161010090041685565b600f546001600160a01b03163314610b63576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b600d546040516001600160a01b038084169216907fd38cd7a28764cf6ebbaf7ee1ccf8f3b825cfbd5d1b1cd08af390afc71d309dcc90600090a3600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60048054604051635ae8095160e01b8152600092839283926001600160a01b0390911691635ae8095191610bf591309101611ece565b60206040518083038186803b158015610c0d57600080fd5b505afa158015610c21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c459190611d9e565b90506000808212610c565781610c5c565b81600019025b9050600360009054906101000a90046001600160a01b03166001600160a01b03166312803c7d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cac57600080fd5b505afa158015610cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce49190611d62565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610d0f9190611ece565b60206040518083038186803b158015610d2757600080fd5b505afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190611d9e565b610d6e8264e8d4a510006113e2565b019443945092505050565b6008546001600160a01b031633148015610dad5750600c546001600160a01b0316610da2611342565b6001600160a01b0316145b80610dc25750600e546001600160a01b031633145b610e05576040805162461bcd60e51b815260206004820152600f60248201526e13d3931657d055551213d492569151608a1b604482015290519081900360640190fd5b600b54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610e4f57600080fd5b505afa158015610e63573d6000803e3d6000fd5b505050506040513d6020811015610e7957600080fd5b50511015610ec2576040805162461bcd60e51b81526020600482015260116024820152704e4f545f454e4f5547485f544f4b454e5360781b604482015290519081900360640190fd5b600d546001600160a01b03848116911614610f17576040805162461bcd60e51b815260206004820152601060248201526f494e56414c49445f524547495354525960801b604482015290519081900360640190fd5b600b54600d54600c54610f41926001600160a01b039081169288929082169116896001888861144b565b5050505050565b600f546001600160a01b03163314610f99576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b601080546001600160a01b0319166001600160a01b0392909216919091179055565b600e546001600160a01b031681565b6008546001600160a01b031633148015610ffe5750600c546001600160a01b0316610ff3611342565b6001600160a01b0316145b806110135750600e546001600160a01b031633145b611056576040805162461bcd60e51b815260206004820152600f60248201526e13d3931657d055551213d492569151608a1b604482015290519081900360640190fd5b601454610100900460ff166110a5576040805162461bcd60e51b815260206004820152601060248201526f2727afa7a822a72fa827a9a4aa24a7a760811b604482015290519081900360640190fd5b6110b38162ffffff1661156c565b6014805461ff00191690556110ce6110c96109a6565b6116c0565b50565b6006546001600160a01b031681565b600b546001600160a01b031681565b6005546001600160a01b031681565b6001546001600160a01b031681565b600654600154604051633478970960e11b81526000926001600160a01b03908116926368f12e12926109d79230921690600401611ee2565b6008546001600160a01b0316331480156111795750600c546001600160a01b031661116e611342565b6001600160a01b0316145b8061118e5750600e546001600160a01b031633145b6111d1576040805162461bcd60e51b815260206004820152600f60248201526e13d3931657d055551213d492569151608a1b604482015290519081900360640190fd5b601454610100900460ff1615611220576040805162461bcd60e51b815260206004820152600f60248201526e20a1aa24ab22afa827a9a4aa24a7a760891b604482015290519081900360640190fd5b600b54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561126b57600080fd5b505afa15801561127f573d6000803e3d6000fd5b505050506040513d602081101561129557600080fd5b505190506112a28161179e565b6040518060a001604052806112bd6112b8610776565b611859565b81526020016112ca61087e565b8152602080820186905286151560408084019190915260016060938401528351601155908301516012558201516013558101516014805460809093015115156101000261ff001992151560ff199094169390931791909116919091179055610f4184848461188f565b6007546001600160a01b031681565b60095460408051636e296e4560e01b815290516000926001600160a01b031691636e296e45916004808301926020929190829003018186803b15801561138757600080fd5b505afa15801561139b573d6000803e3d6000fd5b505050506040513d60208110156113b157600080fd5b5051905090565b60005481565b600d546001600160a01b031681565b6010546001600160a01b031681565b61271081565b6000808211611438576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161144157fe5b0490505b92915050565b6114588282858b89611a5d565b60405163095ea7b360e01b81526001600160a01b0389169063095ea7b390611486908a908890600401611efc565b602060405180830381600087803b1580156114a057600080fd5b505af11580156114b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d89190611d7e565b506000866001600160a01b031683836040516114f5929190611ebe565b6000604051808303816000865af19150503d8060008114611532576040519150601f19603f3d011682016040523d82523d6000602084013e611537565b606091505b50509050806115615760405162461bcd60e51b815260040161155890611f5d565b60405180910390fd5b505050505050505050565b60006115796112b8610776565b905060008061158661110d565b126115985761159361110d565b6115a5565b6115a061110d565b600019025b90506127108314156115b95750600061160c565b60006115c361110d565b126115e5576115e06127106115da83868303611b02565b906113e2565b6115f7565b6115f76127106115da83868301611b02565b90506116096127106115da8385611b02565b90505b6040805160a0810182526001546001600160a01b03908116825260006020830181905282840185905242606084015254608083015260048054935162aa9a8960e01b815292939091169162aa9a899161166791859101611ff3565b6040805180830381600087803b15801561168057600080fd5b505af1158015611694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b89190611e77565b505050505050565b600354604080516312803c7d60e01b815290516000926001600160a01b0316916312803c7d916004808301926020929190829003018186803b15801561170557600080fd5b505afa158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190611d62565b60035460405163f3fef3a360e01b81529192506001600160a01b03169063f3fef3a3906117709084908690600401611efc565b600060405180830381600087803b15801561178a57600080fd5b505af11580156116b8573d6000803e3d6000fd5b600354604080516312803c7d60e01b815290516000926001600160a01b0316916312803c7d916004808301926020929190829003018186803b1580156117e357600080fd5b505afa1580156117f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181b9190611d62565b90506118278183611b62565b6003546040516311f9fbc960e21b81526001600160a01b03909116906347e7ef24906117709084908690600401611efc565b600060c06118856118756001600160a01b038516612710611b02565b6001600160a01b03851690611b02565b901c90505b919050565b60008061189d6112b8610776565b905060006127108462ffffff1614156118b857506000611905565b856118d9576118d46127106115da8762ffffff88168303611b02565b6118f0565b6118f06127106115da8762ffffff88168301611b02565b9050611902826115da83612710611b02565b90505b60408051610100810182526001546001600160a01b0390811682528815801560208401528284015260608201889052608082018490524260a0830152600060c083018190525460e083015260048054935163b6b1b6c360e01b815292939091169163b6b1b6c39161197891859101612036565b6040805180830381600087803b15801561199157600080fd5b505af11580156119a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c99190611e77565b505060065460015460405163165c4e2960e31b81526001600160a01b039283169263b2e2714892611a0292309290911690600401611ee2565b60206040518083038186803b158015611a1a57600080fd5b505afa158015611a2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a529190611d9e565b979650505050505050565b611a65611c0a565b611a6f8686611be8565b905083816020015114611a945760405162461bcd60e51b815260040161155890611f34565b816001600160a01b031681600001516001600160a01b031614611ac95760405162461bcd60e51b815260040161155890611f94565b826001600160a01b03168160800151604001516001600160a01b0316146116b85760405162461bcd60e51b815260040161155890611fc6565b600082611b1157506000611445565b82820282848281611b1e57fe5b0414611b5b5760405162461bcd60e51b81526004018080602001828103825260218152602001806120ee6021913960400191505060405180910390fd5b9392505050565b60035460405163095ea7b360e01b81526001600160a01b038481169263095ea7b392611b9692909116908590600401611efc565b602060405180830381600087803b158015611bb057600080fd5b505af1158015611bc4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fd9190611d7e565b611bf0611c0a565b611bfd82600481866120b0565b810190611b5b9190611db6565b6040518060a0016040528060006001600160a01b031681526020016000815260200160008152602001611c3b611c4d565b8152602001611c48611c4d565b905290565b6040518060800160405280600081526020016000815260200160006001600160a01b03168152602001606081525090565b803561188a816120d8565b600060808284031215611c9a578081fd5b604080516080810167ffffffffffffffff8282108183111715611cb957fe5b8184528294508535835260209150818601358284015283860135611cdc816120d8565b83850152606086013581811115611cf257600080fd5b8601601f81018813611d0357600080fd5b803582811115611d0f57fe5b8551601f8201601f1916810185018481118282101715611d2b57fe5b875281815282820185018a1015611d4157600080fd5b81858401868301376000918101909401525050606091909101525092915050565b600060208284031215611d73578081fd5b8151611b5b816120d8565b600060208284031215611d8f578081fd5b81518015158114611b5b578182fd5b600060208284031215611daf578081fd5b5051919050565b600060208284031215611dc7578081fd5b813567ffffffffffffffff80821115611dde578283fd5b9083019060a08286031215611df1578283fd5b60405160a081018181108382111715611e0657fe5b604052611e1283611c7e565b81526020830135602082015260408301356040820152606083013582811115611e39578485fd5b611e4587828601611c89565b606083015250608083013582811115611e5c578485fd5b611e6887828601611c89565b60808301525095945050505050565b60008060408385031215611e89578081fd5b505080516020909101519092909150565b600060208284031215611eab578081fd5b815163ffffffff81168114611b5b578182fd5b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392909216825263ffffffff16602082015260400190565b6020808252600f908201526e125b9d985b1a590818da185a5b9259608a1b604082015260600190565b6020808252601d908201527f4661696c656420746f2063616c6c20736f636b65745265676973747279000000604082015260600190565b602080825260189082015277496e76616c6964207265636569766572206164647265737360401b604082015260600190565b60208082526013908201527224b73b30b634b21034b7383aba103a37b5b2b760691b604082015260600190565b81516001600160a01b0390811682526020808401519091169082015260408083015190820152606080830151908201526080918201519181019190915260a00190565b60006101008201905060018060a01b03808451168352602084015115156020840152604084015115156040840152606084015160608401526080840151608084015260a084015160a08401528060c08501511660c08401525060e083015160e083015292915050565b63ffffffff91909116815260200190565b600080858511156120bf578182fd5b838611156120cb578182fd5b5050820193919092039150565b6001600160a01b03811681146110ce57600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220c41d6fe5935f7cb1dab3ed0bee84d07921d9e2f50bb723b0beb0a4c7814fe99264736f6c63430007060033000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000c31587a61179ffe6d0d87130b2e704927c7a48e2000000000000000000000000ad7b4c162707e0b2b5f6fddbd3f8538a5fba0d6000000000000000000000000082ac2ce43e33683c58be4cdc40975e73aa50f459000000000000000000000000a4c817a425d3443baf610ca614c8b11688a288fb000000000000000000000000a7f3fc32043757039d5e13d790ee43edbcba8b7c000000000000000000000000bd7a3b7dbeb096f0b832cf467b94b091f30c34ec0000000000000000000000008c835dfaa34e2ae61775e80ee29e2c724c6ae2bb000000000000000000000000c84da6c8ec7a57cd10b939e79eaf9d2d17834e04000000000000000000000000ae75b29ade678372d77a8b41225654138a7e6ff10000000000000000000000006b29610d6c6a9e47812be40f1335918bd63321bf000000000000000000000000c30141b657f4216252dc59af2e7cdb9d8792e1b0

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000c31587a61179ffe6d0d87130b2e704927c7a48e2000000000000000000000000ad7b4c162707e0b2b5f6fddbd3f8538a5fba0d6000000000000000000000000082ac2ce43e33683c58be4cdc40975e73aa50f459000000000000000000000000a4c817a425d3443baf610ca614c8b11688a288fb000000000000000000000000a7f3fc32043757039d5e13d790ee43edbcba8b7c000000000000000000000000bd7a3b7dbeb096f0b832cf467b94b091f30c34ec0000000000000000000000008c835dfaa34e2ae61775e80ee29e2c724c6ae2bb000000000000000000000000c84da6c8ec7a57cd10b939e79eaf9d2d17834e04000000000000000000000000ae75b29ade678372d77a8b41225654138a7e6ff10000000000000000000000006b29610d6c6a9e47812be40f1335918bd63321bf000000000000000000000000c30141b657f4216252dc59af2e7cdb9d8792e1b0

-----Decoded View---------------
Arg [0] : _wantTokenL1 (address): 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : _wantTokenL2 (address): 0x7f5c764cbc14f9669b88837ca1490cca17c31607
Arg [2] : _positionHandlerL1 (address): 0xc31587a61179ffe6d0d87130b2e704927c7a48e2
Arg [3] : _perpVault (address): 0xad7b4c162707e0b2b5f6fddbd3f8538a5fba0d60
Arg [4] : _clearingHouse (address): 0x82ac2ce43e33683c58be4cdc40975e73aa50f459
Arg [5] : _clearingHouseConfig (address): 0xa4c817a425d3443baf610ca614c8b11688a288fb
Arg [6] : _accountBalance (address): 0xa7f3fc32043757039d5e13d790ee43edbcba8b7c
Arg [7] : _exchange (address): 0xbd7a3b7dbeb096f0b832cf467b94b091f30c34ec
Arg [8] : _baseToken (address): 0x8c835dfaa34e2ae61775e80ee29e2c724c6ae2bb
Arg [9] : _quoteTokenvUSDC (address): 0xc84da6c8ec7a57cd10b939e79eaf9d2d17834e04
Arg [10] : _keeper (address): 0xae75b29ade678372d77a8b41225654138a7e6ff1
Arg [11] : _governance (address): 0x6b29610d6c6a9e47812be40f1335918bd63321bf
Arg [12] : _socketRegistry (address): 0xc30141b657f4216252dc59af2e7cdb9d8792e1b0

-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607
Arg [2] : 000000000000000000000000c31587a61179ffe6d0d87130b2e704927c7a48e2
Arg [3] : 000000000000000000000000ad7b4c162707e0b2b5f6fddbd3f8538a5fba0d60
Arg [4] : 00000000000000000000000082ac2ce43e33683c58be4cdc40975e73aa50f459
Arg [5] : 000000000000000000000000a4c817a425d3443baf610ca614c8b11688a288fb
Arg [6] : 000000000000000000000000a7f3fc32043757039d5e13d790ee43edbcba8b7c
Arg [7] : 000000000000000000000000bd7a3b7dbeb096f0b832cf467b94b091f30c34ec
Arg [8] : 0000000000000000000000008c835dfaa34e2ae61775e80ee29e2c724c6ae2bb
Arg [9] : 000000000000000000000000c84da6c8ec7a57cd10b939e79eaf9d2d17834e04
Arg [10] : 000000000000000000000000ae75b29ade678372d77a8b41225654138a7e6ff1
Arg [11] : 0000000000000000000000006b29610d6c6a9e47812be40f1335918bd63321bf
Arg [12] : 000000000000000000000000c30141b657f4216252dc59af2e7cdb9d8792e1b0


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.