{
  "address": "0x8B98991EEd7C25280BE5532C3b23a095654868c0",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_priceFeedAddress",
          "type": "address"
        },
        {
          "internalType": "string",
          "name": "_tokenName",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "_tokenSymbol",
          "type": "string"
        },
        {
          "internalType": "address",
          "name": "_arbSysAddress",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Approval",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "productId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "fundingRate",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "amountFundingPaidPerPosition",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "fundingPaidPerPosition",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "poolReceived",
          "type": "int256"
        }
      ],
      "name": "FundingPayment",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "minSlippageToleranceOfHedge",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "maxSlippageToleranceOfHedge",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "hedgeRateOfReturnThreshold",
          "type": "uint256"
        }
      ],
      "name": "SetHedgeParams",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "int256",
          "name": "perpFutureMaxFundingRate",
          "type": "int256"
        }
      ],
      "name": "SetPerpFutureMaxFundingRate",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "int256",
          "name": "poolMarginRiskParam",
          "type": "int256"
        }
      ],
      "name": "SetPoolMarginRiskParam",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "safetyPeriod",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "numBlocksPerSpreadDecreasing",
          "type": "uint256"
        }
      ],
      "name": "SetSpreadParams",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "int256",
          "name": "squaredPerpFundingMultiplier",
          "type": "int256"
        }
      ],
      "name": "SetSquaredPerpFundingMultiplier",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "int256",
          "name": "tradeFeeRate",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "protocolFeeRate",
          "type": "int256"
        }
      ],
      "name": "SetTradeFeeRate",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "int256",
          "name": "variance",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "underlyingPrice",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "timestamp",
          "type": "uint256"
        }
      ],
      "name": "VarianceUpdated",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "addLiquidity",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "amountLiquidity",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "approve",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "amountUsdc",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountUnderlying",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "futureWeight",
              "type": "uint256"
            },
            {
              "internalType": "bool",
              "name": "isLong",
              "type": "bool"
            }
          ],
          "internalType": "struct NettingLib.CompleteParams",
          "name": "_completeParams",
          "type": "tuple"
        }
      ],
      "name": "completeHedgingProcedure",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "subtractedValue",
          "type": "uint256"
        }
      ],
      "name": "decreaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_depositAmount",
          "type": "uint256"
        }
      ],
      "name": "deposit",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "mintAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "executeFundingPayment",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_deltaLiquidityAmount",
          "type": "int256"
        }
      ],
      "name": "getLPTokenPrice",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getNettingInfo",
      "outputs": [
        {
          "components": [
            {
              "internalType": "int256[2]",
              "name": "amountsUsdc",
              "type": "int256[2]"
            },
            {
              "internalType": "uint256",
              "name": "amountUnderlying",
              "type": "uint256"
            }
          ],
          "internalType": "struct NettingLib.Info",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getTokenAmountForHedging",
      "outputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "amountUsdc",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "amountUnderlying",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "futureWeight",
              "type": "uint256"
            },
            {
              "internalType": "bool",
              "name": "isLong",
              "type": "bool"
            }
          ],
          "internalType": "struct NettingLib.CompleteParams",
          "name": "completeParams",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_productId",
          "type": "uint256"
        },
        {
          "internalType": "int256[2]",
          "name": "_tradeAmounts",
          "type": "int256[2]"
        }
      ],
      "name": "getTradePrice",
      "outputs": [
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256[2]",
          "name": "_tradeAmounts",
          "type": "int256[2]"
        }
      ],
      "name": "getTradePriceInfo",
      "outputs": [
        {
          "components": [
            {
              "internalType": "uint128",
              "name": "spotPrice",
              "type": "uint128"
            },
            {
              "internalType": "int256[2]",
              "name": "tradePrices",
              "type": "int256[2]"
            },
            {
              "internalType": "int256[2]",
              "name": "fundingRates",
              "type": "int256[2]"
            },
            {
              "internalType": "int256[2]",
              "name": "amountsFundingPaidPerPosition",
              "type": "int256[2]"
            }
          ],
          "internalType": "struct IPerpetualMarketCore.TradePriceInfo",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getUtilizationRatio",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "addedValue",
          "type": "uint256"
        }
      ],
      "name": "increaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_depositAmount",
          "type": "uint256"
        },
        {
          "internalType": "int256",
          "name": "_initialFundingRate",
          "type": "int256"
        }
      ],
      "name": "initialize",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "mintAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "lastHedgeSpotPrice",
      "outputs": [
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "poolSnapshot",
      "outputs": [
        {
          "internalType": "int128",
          "name": "futureBaseFundingRate",
          "type": "int128"
        },
        {
          "internalType": "int128",
          "name": "ethVariance",
          "type": "int128"
        },
        {
          "internalType": "int128",
          "name": "ethPrice",
          "type": "int128"
        },
        {
          "internalType": "uint128",
          "name": "lastSnapshotTime",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "pools",
      "outputs": [
        {
          "internalType": "uint128",
          "name": "amountLockedLiquidity",
          "type": "uint128"
        },
        {
          "internalType": "int128",
          "name": "positionPerpetuals",
          "type": "int128"
        },
        {
          "internalType": "uint128",
          "name": "entryPrice",
          "type": "uint128"
        },
        {
          "internalType": "int256",
          "name": "amountFundingPaidPerPosition",
          "type": "int256"
        },
        {
          "internalType": "uint128",
          "name": "lastFundingPaymentTime",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "rebalance",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_minSlippageToleranceOfHedge",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_maxSlippageToleranceOfHedge",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_hedgeRateOfReturnThreshold",
          "type": "uint256"
        }
      ],
      "name": "setHedgeParams",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_perpFutureMaxFundingRate",
          "type": "int256"
        }
      ],
      "name": "setPerpFutureMaxFundingRate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_perpetualMarket",
          "type": "address"
        }
      ],
      "name": "setPerpetualMarket",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_poolMarginRiskParam",
          "type": "int256"
        }
      ],
      "name": "setPoolMarginRiskParam",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_safetyPeriod",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_numBlocksPerSpreadDecreasing",
          "type": "uint256"
        }
      ],
      "name": "setSpreadParams",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_squaredPerpFundingMultiplier",
          "type": "int256"
        }
      ],
      "name": "setSquaredPerpFundingMultiplier",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_tradeFeeRate",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "_protocolFeeRate",
          "type": "int256"
        }
      ],
      "name": "setTradeFeeRate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transferFrom",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256[2]",
          "name": "_tradeAmounts",
          "type": "int256[2]"
        }
      ],
      "name": "updatePoolPositions",
      "outputs": [
        {
          "internalType": "uint256[2]",
          "name": "tradePrice",
          "type": "uint256[2]"
        },
        {
          "internalType": "int256[2]",
          "name": "fundingPaidPerPosition",
          "type": "int256[2]"
        },
        {
          "internalType": "uint256",
          "name": "protocolFee",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "updatePoolSnapshot",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_withdrawer",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_withdrawnAmount",
          "type": "uint256"
        }
      ],
      "name": "withdraw",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "burnAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0xe493b98aedf736ffd1895616aa9f23b4f7b084309eff851885b5d4d80551ff0e",
  "receipt": {
    "to": null,
    "from": "0x4f071924D66BBC71A5254217893CC7D49938B1c4",
    "contractAddress": "0x8B98991EEd7C25280BE5532C3b23a095654868c0",
    "transactionIndex": 1,
    "gasUsed": "72463225",
    "logsBloom": "0x00000000000000000000000000000000000200000000000020800000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000020400000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000",
    "blockHash": "0xfed4d10aeef37b982354de1a1e4801266b0668d36a986332eff5bf4c36caadab",
    "transactionHash": "0xe493b98aedf736ffd1895616aa9f23b4f7b084309eff851885b5d4d80551ff0e",
    "logs": [
      {
        "transactionIndex": 1,
        "blockNumber": 14570781,
        "transactionHash": "0xe493b98aedf736ffd1895616aa9f23b4f7b084309eff851885b5d4d80551ff0e",
        "address": "0x8B98991EEd7C25280BE5532C3b23a095654868c0",
        "topics": [
          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0000000000000000000000004f071924d66bbc71a5254217893cc7d49938b1c4"
        ],
        "data": "0x",
        "logIndex": 7,
        "blockHash": "0xfed4d10aeef37b982354de1a1e4801266b0668d36a986332eff5bf4c36caadab"
      }
    ],
    "blockNumber": 14570781,
    "cumulativeGasUsed": "33448904",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612",
    "Predy V202 ETH USDC LP Token",
    "PREDY2-ETH-USDC-LP",
    "0x0000000000000000000000000000000000000064"
  ],
  "solcInputHash": "4053827aa146c622da7f45f0acacb57f",
  "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_priceFeedAddress\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_tokenName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_tokenSymbol\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_arbSysAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"productId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fundingRate\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"amountFundingPaidPerPosition\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fundingPaidPerPosition\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"poolReceived\",\"type\":\"int256\"}],\"name\":\"FundingPayment\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minSlippageToleranceOfHedge\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSlippageToleranceOfHedge\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"hedgeRateOfReturnThreshold\",\"type\":\"uint256\"}],\"name\":\"SetHedgeParams\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"perpFutureMaxFundingRate\",\"type\":\"int256\"}],\"name\":\"SetPerpFutureMaxFundingRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"poolMarginRiskParam\",\"type\":\"int256\"}],\"name\":\"SetPoolMarginRiskParam\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"safetyPeriod\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"numBlocksPerSpreadDecreasing\",\"type\":\"uint256\"}],\"name\":\"SetSpreadParams\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"squaredPerpFundingMultiplier\",\"type\":\"int256\"}],\"name\":\"SetSquaredPerpFundingMultiplier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"tradeFeeRate\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"protocolFeeRate\",\"type\":\"int256\"}],\"name\":\"SetTradeFeeRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"variance\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"underlyingPrice\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"VarianceUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountUsdc\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"futureWeight\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct NettingLib.CompleteParams\",\"name\":\"_completeParams\",\"type\":\"tuple\"}],\"name\":\"completeHedgingProcedure\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"executeFundingPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_deltaLiquidityAmount\",\"type\":\"int256\"}],\"name\":\"getLPTokenPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNettingInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"int256[2]\",\"name\":\"amountsUsdc\",\"type\":\"int256[2]\"},{\"internalType\":\"uint256\",\"name\":\"amountUnderlying\",\"type\":\"uint256\"}],\"internalType\":\"struct NettingLib.Info\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenAmountForHedging\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountUsdc\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"futureWeight\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isLong\",\"type\":\"bool\"}],\"internalType\":\"struct NettingLib.CompleteParams\",\"name\":\"completeParams\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_productId\",\"type\":\"uint256\"},{\"internalType\":\"int256[2]\",\"name\":\"_tradeAmounts\",\"type\":\"int256[2]\"}],\"name\":\"getTradePrice\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256[2]\",\"name\":\"_tradeAmounts\",\"type\":\"int256[2]\"}],\"name\":\"getTradePriceInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"spotPrice\",\"type\":\"uint128\"},{\"internalType\":\"int256[2]\",\"name\":\"tradePrices\",\"type\":\"int256[2]\"},{\"internalType\":\"int256[2]\",\"name\":\"fundingRates\",\"type\":\"int256[2]\"},{\"internalType\":\"int256[2]\",\"name\":\"amountsFundingPaidPerPosition\",\"type\":\"int256[2]\"}],\"internalType\":\"struct IPerpetualMarketCore.TradePriceInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUtilizationRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"_initialFundingRate\",\"type\":\"int256\"}],\"name\":\"initialize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastHedgeSpotPrice\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolSnapshot\",\"outputs\":[{\"internalType\":\"int128\",\"name\":\"futureBaseFundingRate\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"ethVariance\",\"type\":\"int128\"},{\"internalType\":\"int128\",\"name\":\"ethPrice\",\"type\":\"int128\"},{\"internalType\":\"uint128\",\"name\":\"lastSnapshotTime\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"amountLockedLiquidity\",\"type\":\"uint128\"},{\"internalType\":\"int128\",\"name\":\"positionPerpetuals\",\"type\":\"int128\"},{\"internalType\":\"uint128\",\"name\":\"entryPrice\",\"type\":\"uint128\"},{\"internalType\":\"int256\",\"name\":\"amountFundingPaidPerPosition\",\"type\":\"int256\"},{\"internalType\":\"uint128\",\"name\":\"lastFundingPaymentTime\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rebalance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minSlippageToleranceOfHedge\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSlippageToleranceOfHedge\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_hedgeRateOfReturnThreshold\",\"type\":\"uint256\"}],\"name\":\"setHedgeParams\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_perpFutureMaxFundingRate\",\"type\":\"int256\"}],\"name\":\"setPerpFutureMaxFundingRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_perpetualMarket\",\"type\":\"address\"}],\"name\":\"setPerpetualMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_poolMarginRiskParam\",\"type\":\"int256\"}],\"name\":\"setPoolMarginRiskParam\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_safetyPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_numBlocksPerSpreadDecreasing\",\"type\":\"uint256\"}],\"name\":\"setSpreadParams\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_squaredPerpFundingMultiplier\",\"type\":\"int256\"}],\"name\":\"setSquaredPerpFundingMultiplier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_tradeFeeRate\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"_protocolFeeRate\",\"type\":\"int256\"}],\"name\":\"setTradeFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256[2]\",\"name\":\"_tradeAmounts\",\"type\":\"int256[2]\"}],\"name\":\"updatePoolPositions\",\"outputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"tradePrice\",\"type\":\"uint256[2]\"},{\"internalType\":\"int256[2]\",\"name\":\"fundingPaidPerPosition\",\"type\":\"int256[2]\"},{\"internalType\":\"uint256\",\"name\":\"protocolFee\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updatePoolSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_withdrawer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_withdrawnAmount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"burnAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"getLPTokenPrice(int256)\":{\"returns\":{\"_0\":\"LPTokenPrice scaled by 1e16\"}},\"getTradePrice(uint256,int256[2])\":{\"params\":{\"_productId\":\"product id\",\"_tradeAmounts\":\"amount of position to trade. positive for pool short and negative for pool long.\"}},\"getUtilizationRatio()\":{\"returns\":{\"_0\":\"Utilization Ratio scaled by 1e8\"}},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"updatePoolPositions(int256[2])\":{\"params\":{\"_tradeAmounts\":\"amount of positions to trade. positive for pool short and negative for pool long.\"}}},\"title\":\"PerpetualMarketCore\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"completeHedgingProcedure((uint256,uint256,uint256,bool))\":{\"notice\":\"Update netting info to complete heging procedure\"},\"deposit(address,uint256)\":{\"notice\":\"Provides liquidity\"},\"getLPTokenPrice(int256)\":{\"notice\":\"Gets LP token price LPTokenPrice = (L + \\u03a3UnrealizedPnL_i - \\u03a3AmountLockedLiquidity_i) / Supply\"},\"getTokenAmountForHedging()\":{\"notice\":\"Gets USDC and underlying amount to make the pool delta neutral\"},\"getTradePrice(uint256,int256[2])\":{\"notice\":\"Gets trade price\"},\"getUtilizationRatio()\":{\"notice\":\"Gets utilization ratio Utilization Ratio = (\\u03a3AmountLockedLiquidity_i) / L\"},\"initialize(address,uint256,int256)\":{\"notice\":\"Initialize pool with initial liquidity and funding rate\"},\"rebalance()\":{\"notice\":\"Locks liquidity if more collateral required and unlocks liquidity if there is unrequied collateral.\"},\"updatePoolPositions(int256[2])\":{\"notice\":\"Adds or removes pool positions\"},\"updatePoolSnapshot()\":{\"notice\":\"Updates pool snapshot Calculates ETH variance and base funding rate for future pool.\"},\"withdraw(address,uint256)\":{\"notice\":\"xxWithdraws liquidity\"}},\"notice\":\"Perpetual Market Core Contract manages perpetual pool positions and calculates amount of collaterals. Error Code PMC0: No available liquidity PMC1: No available liquidity PMC2: caller must be PerpetualMarket contract PMC3: underlying price must not be 0 PMC4: pool delta must be negative PMC5: invalid params\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/PerpetualMarketCore.sol\":\"PerpetualMarketCore\"},\"evmVersion\":\"istanbul\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363535313831393733373438\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.7.0;\\n\\ninterface AggregatorV3Interface {\\n  function decimals() external view returns (uint8);\\n\\n  function description() external view returns (string memory);\\n\\n  function version() external view returns (uint256);\\n\\n  // getRoundData and latestRoundData should both raise \\\"No data present\\\"\\n  // if they do not have data to report, instead of returning unset values\\n  // which could be misinterpreted as actual reported values.\\n  function getRoundData(uint80 _roundId)\\n    external\\n    view\\n    returns (\\n      uint80 roundId,\\n      int256 answer,\\n      uint256 startedAt,\\n      uint256 updatedAt,\\n      uint80 answeredInRound\\n    );\\n\\n  function latestRoundData()\\n    external\\n    view\\n    returns (\\n      uint80 roundId,\\n      int256 answer,\\n      uint256 startedAt,\\n      uint256 updatedAt,\\n      uint80 answeredInRound\\n    );\\n}\\n\",\"keccak256\":\"0x5cf082133e64f5f90f446c011681ea7ab719e2992c7247074b943771c176494a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n    address private _owner;\\n\\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n    /**\\n     * @dev Initializes the contract setting the deployer as the initial owner.\\n     */\\n    constructor () {\\n        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), msgSender);\\n    }\\n\\n    /**\\n     * @dev Returns the address of the current owner.\\n     */\\n    function owner() public view virtual returns (address) {\\n        return _owner;\\n    }\\n\\n    /**\\n     * @dev Throws if called by any account other than the owner.\\n     */\\n    modifier onlyOwner() {\\n        require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @dev Leaves the contract without owner. It will not be possible to call\\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\\n     *\\n     * NOTE: Renouncing ownership will leave the contract without an owner,\\n     * thereby removing any functionality that is only available to the owner.\\n     */\\n    function renounceOwnership() public virtual onlyOwner {\\n        emit OwnershipTransferred(_owner, address(0));\\n        _owner = address(0);\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Can only be called by the current owner.\\n     */\\n    function transferOwnership(address newOwner) public virtual onlyOwner {\\n        require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n}\\n\",\"keccak256\":\"0x549c5343ad9f7e3f38aa4c4761854403502574bbc15b822db2ce892ff9b79da7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        uint256 c = a + b;\\n        if (c < a) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b > a) return (false, 0);\\n        return (true, a - b);\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) return (true, 0);\\n        uint256 c = a * b;\\n        if (c / a != b) return (false, 0);\\n        return (true, c);\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a / b);\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        if (b == 0) return (false, 0);\\n        return (true, a % b);\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        if (a == 0) return 0;\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: division by zero\\\");\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\",\"keccak256\":\"0xe22a1fc7400ae196eba2ad1562d0386462b00a6363b742d55a2fd2021a58586f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SignedSafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @title SignedSafeMath\\n * @dev Signed math operations with safety checks that revert on error.\\n */\\nlibrary SignedSafeMath {\\n    int256 constant private _INT256_MIN = -2**255;\\n\\n    /**\\n     * @dev Returns the multiplication of two signed integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(int256 a, int256 b) internal pure returns (int256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        require(!(a == -1 && b == _INT256_MIN), \\\"SignedSafeMath: multiplication overflow\\\");\\n\\n        int256 c = a * b;\\n        require(c / a == b, \\\"SignedSafeMath: multiplication overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two signed integers. Reverts on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(int256 a, int256 b) internal pure returns (int256) {\\n        require(b != 0, \\\"SignedSafeMath: division by zero\\\");\\n        require(!(b == -1 && a == _INT256_MIN), \\\"SignedSafeMath: division overflow\\\");\\n\\n        int256 c = a / b;\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two signed integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(int256 a, int256 b) internal pure returns (int256) {\\n        int256 c = a - b;\\n        require((b >= 0 && c <= a) || (b < 0 && c > a), \\\"SignedSafeMath: subtraction overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two signed integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(int256 a, int256 b) internal pure returns (int256) {\\n        int256 c = a + b;\\n        require((b >= 0 && c >= a) || (b < 0 && c < a), \\\"SignedSafeMath: addition overflow\\\");\\n\\n        return c;\\n    }\\n}\\n\",\"keccak256\":\"0xba085261d44cf28d2583f7c8cdb2f0a6a495ff1a640f86d995ea9d36b42b0046\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20 {\\n    using SafeMath for uint256;\\n\\n    mapping (address => uint256) private _balances;\\n\\n    mapping (address => mapping (address => uint256)) private _allowances;\\n\\n    uint256 private _totalSupply;\\n\\n    string private _name;\\n    string private _symbol;\\n    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three of these values are immutable: they can only be set once during\\n     * construction.\\n     */\\n    constructor (string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev Returns the symbol of the token, usually a shorter version of the\\n     * name.\\n     */\\n    function symbol() public view virtual returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev Returns the number of decimals used to get its user representation.\\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n     * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n     *\\n     * Tokens usually opt for a value of 18, imitating the relationship between\\n     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\\n     * called.\\n     *\\n     * NOTE: This information is only used for _display_ purposes: it in\\n     * no way affects any of the arithmetic of the contract, including\\n     * {IERC20-balanceOf} and {IERC20-transfer}.\\n     */\\n    function decimals() public view virtual returns (uint8) {\\n        return _decimals;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        return _totalSupply;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-balanceOf}.\\n     */\\n    function balanceOf(address account) public view virtual override returns (uint256) {\\n        return _balances[account];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transfer}.\\n     *\\n     * Requirements:\\n     *\\n     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-allowance}.\\n     */\\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n        return _allowances[owner][spender];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-approve}.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), spender, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transferFrom}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance. This is not\\n     * required by the EIP. See the note at the beginning of {ERC20}.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `spender` must have allowance for the caller of at least\\n     * `subtractedValue`.\\n     */\\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is internal function is equivalent to {transfer}, and can be used to\\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\\n     *\\n     * Emits a {Transfer} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, amount);\\n    }\\n\\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n     * the total supply.\\n     *\\n     * Emits a {Transfer} event with `from` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     */\\n    function _mint(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n        _beforeTokenTransfer(address(0), account, amount);\\n\\n        _totalSupply = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(address(0), account, amount);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens from `account`, reducing the\\n     * total supply.\\n     *\\n     * Emits a {Transfer} event with `to` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     * - `account` must have at least `amount` tokens.\\n     */\\n    function _burn(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n        _beforeTokenTransfer(account, address(0), amount);\\n\\n        _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(account, address(0), amount);\\n    }\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n     *\\n     * This internal function is equivalent to `approve`, and can be used to\\n     * e.g. set automatic allowances for certain subsystems, etc.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `owner` cannot be the zero address.\\n     * - `spender` cannot be the zero address.\\n     */\\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\\n        require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n        require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n        _allowances[owner][spender] = amount;\\n        emit Approval(owner, spender, amount);\\n    }\\n\\n    /**\\n     * @dev Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal virtual {\\n        _decimals = decimals_;\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any transfer of tokens. This includes\\n     * minting and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * will be to transferred to `to`.\\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n     * - `from` and `to` are never both zero.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0x36b5ca4eabe888b39b10973621ca0dcc9b1508f8d06db9ddf045d7aa7c867d4a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbd74f587ab9b9711801baf667db1426e4a03fd2d7f15af33e0e0d0394e7cef76\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n\\n    /**\\n     * @dev Returns the downcasted uint128 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint128).\\n     *\\n     * Counterpart to Solidity's `uint128` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 128 bits\\n     */\\n    function toUint128(uint256 value) internal pure returns (uint128) {\\n        require(value < 2**128, \\\"SafeCast: value doesn\\\\'t fit in 128 bits\\\");\\n        return uint128(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint64 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint64).\\n     *\\n     * Counterpart to Solidity's `uint64` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 64 bits\\n     */\\n    function toUint64(uint256 value) internal pure returns (uint64) {\\n        require(value < 2**64, \\\"SafeCast: value doesn\\\\'t fit in 64 bits\\\");\\n        return uint64(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint32 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint32).\\n     *\\n     * Counterpart to Solidity's `uint32` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 32 bits\\n     */\\n    function toUint32(uint256 value) internal pure returns (uint32) {\\n        require(value < 2**32, \\\"SafeCast: value doesn\\\\'t fit in 32 bits\\\");\\n        return uint32(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint16 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint16).\\n     *\\n     * Counterpart to Solidity's `uint16` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 16 bits\\n     */\\n    function toUint16(uint256 value) internal pure returns (uint16) {\\n        require(value < 2**16, \\\"SafeCast: value doesn\\\\'t fit in 16 bits\\\");\\n        return uint16(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint8 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint8).\\n     *\\n     * Counterpart to Solidity's `uint8` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 8 bits.\\n     */\\n    function toUint8(uint256 value) internal pure returns (uint8) {\\n        require(value < 2**8, \\\"SafeCast: value doesn\\\\'t fit in 8 bits\\\");\\n        return uint8(value);\\n    }\\n\\n    /**\\n     * @dev Converts a signed int256 into an unsigned uint256.\\n     *\\n     * Requirements:\\n     *\\n     * - input must be greater than or equal to 0.\\n     */\\n    function toUint256(int256 value) internal pure returns (uint256) {\\n        require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n        return uint256(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int128 from int256, reverting on\\n     * overflow (when the input is less than smallest int128 or\\n     * greater than largest int128).\\n     *\\n     * Counterpart to Solidity's `int128` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 128 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt128(int256 value) internal pure returns (int128) {\\n        require(value >= -2**127 && value < 2**127, \\\"SafeCast: value doesn\\\\'t fit in 128 bits\\\");\\n        return int128(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int64 from int256, reverting on\\n     * overflow (when the input is less than smallest int64 or\\n     * greater than largest int64).\\n     *\\n     * Counterpart to Solidity's `int64` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 64 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt64(int256 value) internal pure returns (int64) {\\n        require(value >= -2**63 && value < 2**63, \\\"SafeCast: value doesn\\\\'t fit in 64 bits\\\");\\n        return int64(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int32 from int256, reverting on\\n     * overflow (when the input is less than smallest int32 or\\n     * greater than largest int32).\\n     *\\n     * Counterpart to Solidity's `int32` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 32 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt32(int256 value) internal pure returns (int32) {\\n        require(value >= -2**31 && value < 2**31, \\\"SafeCast: value doesn\\\\'t fit in 32 bits\\\");\\n        return int32(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int16 from int256, reverting on\\n     * overflow (when the input is less than smallest int16 or\\n     * greater than largest int16).\\n     *\\n     * Counterpart to Solidity's `int16` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 16 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt16(int256 value) internal pure returns (int16) {\\n        require(value >= -2**15 && value < 2**15, \\\"SafeCast: value doesn\\\\'t fit in 16 bits\\\");\\n        return int16(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int8 from int256, reverting on\\n     * overflow (when the input is less than smallest int8 or\\n     * greater than largest int8).\\n     *\\n     * Counterpart to Solidity's `int8` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 8 bits.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt8(int256 value) internal pure returns (int8) {\\n        require(value >= -2**7 && value < 2**7, \\\"SafeCast: value doesn\\\\'t fit in 8 bits\\\");\\n        return int8(value);\\n    }\\n\\n    /**\\n     * @dev Converts an unsigned uint256 into a signed int256.\\n     *\\n     * Requirements:\\n     *\\n     * - input must be less than or equal to maxInt256.\\n     */\\n    function toInt256(uint256 value) internal pure returns (int256) {\\n        require(value < 2**255, \\\"SafeCast: value doesn't fit in an int256\\\");\\n        return int256(value);\\n    }\\n}\\n\",\"keccak256\":\"0x79004a1d1471abe87e92c4497acba06d5dfa5b1f3e9894a0991a7c4669c5c02c\",\"license\":\"MIT\"},\"arbos-precompiles/arbos/builtin/ArbSys.sol\":{\"content\":\"pragma solidity >=0.4.21 <0.9.0;\\n\\n/**\\n* @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.\\n */\\ninterface ArbSys {\\n    /**\\n    * @notice Get internal version number identifying an ArbOS build\\n    * @return version number as int\\n     */\\n    function arbOSVersion() external pure returns (uint);\\n\\n    function arbChainID() external view returns(uint);\\n\\n    /**\\n    * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\\n    * @return block number as int\\n     */ \\n    function arbBlockNumber() external view returns (uint);\\n\\n    /** \\n    * @notice Send given amount of Eth to dest from sender.\\n    * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.\\n    * @param destination recipient address on L1\\n    * @return unique identifier for this L2-to-L1 transaction.\\n    */\\n    function withdrawEth(address destination) external payable returns(uint);\\n\\n    /** \\n    * @notice Send a transaction to L1\\n    * @param destination recipient address on L1 \\n    * @param calldataForL1 (optional) calldata for L1 contract call\\n    * @return a unique identifier for this L2-to-L1 transaction.\\n    */\\n    function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns(uint);\\n\\n    /** \\n    * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract\\n    * @param account target account\\n    * @return the number of transactions issued by the given external account or the account sequence number of the given contract\\n    */\\n    function getTransactionCount(address account) external view returns(uint256);\\n\\n    /**  \\n    * @notice get the value of target L2 storage slot \\n    * This function is only callable from address 0 to prevent contracts from being able to call it\\n    * @param account target account\\n    * @param index target index of storage slot \\n    * @return stotage value for the given account at the given index\\n    */\\n    function getStorageAt(address account, uint256 index) external view returns (uint256);\\n\\n    /**\\n    * @notice check if current call is coming from l1\\n    * @return true if the caller of this was called directly from L1\\n    */\\n    function isTopLevelCall() external view returns (bool);\\n\\n    /**\\n     * @notice check if the caller (of this caller of this) is an aliased L1 contract address\\n     * @return true iff the caller's address is an alias for an L1 contract address\\n     */\\n    function wasMyCallersAddressAliased() external view returns (bool);\\n\\n    /**\\n     * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing\\n     * @return address of the caller's caller, without applying L1 contract address aliasing\\n     */\\n    function myCallersAddressWithoutAliasing() external view returns (address);\\n\\n    /**\\n     * @notice map L1 sender contract address to its L2 alias\\n     * @param sender sender address\\n     * @param dest destination address\\n     * @return aliased sender address\\n     */\\n    function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns(address);\\n\\n    /**\\n     * @notice get the caller's amount of available storage gas\\n     * @return amount of storage gas available to the caller\\n     */\\n    function getStorageGasAvailable() external view returns(uint);\\n\\n    event L2ToL1Transaction(address caller, address indexed destination, uint indexed uniqueId,\\n                            uint indexed batchNumber, uint indexInBatch,\\n                            uint arbBlockNum, uint ethBlockNum, uint timestamp,\\n                            uint callvalue, bytes data);\\n}\\n\\n\",\"keccak256\":\"0xad18d82436bfea8c09caf466f8982f84f3cf52530132a6aa3518e5efa33045b7\"},\"src/PerpetualMarketCore.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@chainlink/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"./interfaces/IPerpetualMarketCore.sol\\\";\\nimport \\\"./lib/NettingLib.sol\\\";\\nimport \\\"./lib/IndexPricer.sol\\\";\\nimport \\\"./lib/SpreadLib.sol\\\";\\nimport \\\"./lib/EntryPriceMath.sol\\\";\\nimport \\\"./lib/PoolMath.sol\\\";\\n\\nimport \\\"arbos-precompiles/arbos/builtin/ArbSys.sol\\\";\\n\\n/**\\n * @title PerpetualMarketCore\\n * @notice Perpetual Market Core Contract manages perpetual pool positions and calculates amount of collaterals.\\n * Error Code\\n * PMC0: No available liquidity\\n * PMC1: No available liquidity\\n * PMC2: caller must be PerpetualMarket contract\\n * PMC3: underlying price must not be 0\\n * PMC4: pool delta must be negative\\n * PMC5: invalid params\\n */\\ncontract PerpetualMarketCore is IPerpetualMarketCore, Ownable, ERC20 {\\n    using NettingLib for NettingLib.Info;\\n    using SpreadLib for SpreadLib.Info;\\n    using SafeCast for uint256;\\n    using SafeCast for uint128;\\n    using SafeCast for int256;\\n    using SafeMath for uint256;\\n    using SafeMath for uint128;\\n    using SignedSafeMath for int256;\\n    using SignedSafeMath for int128;\\n\\n    uint256 private constant MAX_PRODUCT_ID = 2;\\n\\n    // \\u03bb for exponentially weighted moving average is 94%\\n    int256 private constant LAMBDA = 94 * 1e6;\\n\\n    // funding period is 1 days\\n    int256 private constant FUNDING_PERIOD = 1 days;\\n\\n    // max ratio of (IV/RV)^2 for squeeth pool\\n    int256 private squaredPerpFundingMultiplier;\\n\\n    // max funding rate of future pool\\n    int256 private perpFutureMaxFundingRate;\\n\\n    // min slippage tolerance of a hedge\\n    uint256 private minSlippageToleranceOfHedge;\\n\\n    // max slippage tolerance of a hedge\\n    uint256 private maxSlippageToleranceOfHedge;\\n\\n    // rate of return threshold of a hedge\\n    uint256 private hedgeRateOfReturnThreshold;\\n\\n    // allowable percentage of movement in the underlying spot price\\n    int256 private poolMarginRiskParam;\\n\\n    // trade fee\\n    int256 private tradeFeeRate;\\n\\n    // protocol fee\\n    int256 private protocolFeeRate;\\n\\n    struct Pool {\\n        uint128 amountLockedLiquidity;\\n        int128 positionPerpetuals;\\n        uint128 entryPrice;\\n        int256 amountFundingPaidPerPosition;\\n        uint128 lastFundingPaymentTime;\\n    }\\n\\n    struct PoolSnapshot {\\n        int128 futureBaseFundingRate;\\n        int128 ethVariance;\\n        int128 ethPrice;\\n        uint128 lastSnapshotTime;\\n    }\\n\\n    enum MarginChange {\\n        ShortToShort,\\n        ShortToLong,\\n        LongToLong,\\n        LongToShort\\n    }\\n\\n    // Total amount of liquidity provided by LPs\\n    uint256 public amountLiquidity;\\n\\n    // Pools information storage\\n    mapping(uint256 => Pool) public pools;\\n\\n    // Infos for spread calculation\\n    mapping(uint256 => SpreadLib.Info) private spreadInfos;\\n\\n    // Infos for LPToken's spread calculation\\n    SpreadLib.Info private lpTokenSpreadInfo;\\n\\n    // Snapshot of pool state at last ETH variance calculation\\n    PoolSnapshot public poolSnapshot;\\n\\n    // Infos for collateral calculation\\n    NettingLib.Info private nettingInfo;\\n\\n    // The address of Chainlink price feed\\n    AggregatorV3Interface private priceFeed;\\n\\n    // The address of ArbSys\\n    ArbSys private arbSys;\\n\\n    // The last spot price at heding\\n    int256 public lastHedgeSpotPrice;\\n\\n    // The address of Perpetual Market Contract\\n    address private perpetualMarket;\\n\\n    event FundingPayment(\\n        uint256 productId,\\n        int256 fundingRate,\\n        int256 amountFundingPaidPerPosition,\\n        int256 fundingPaidPerPosition,\\n        int256 poolReceived\\n    );\\n    event VarianceUpdated(int256 variance, int256 underlyingPrice, uint256 timestamp);\\n\\n    event SetSquaredPerpFundingMultiplier(int256 squaredPerpFundingMultiplier);\\n    event SetPerpFutureMaxFundingRate(int256 perpFutureMaxFundingRate);\\n    event SetHedgeParams(\\n        uint256 minSlippageToleranceOfHedge,\\n        uint256 maxSlippageToleranceOfHedge,\\n        uint256 hedgeRateOfReturnThreshold\\n    );\\n    event SetPoolMarginRiskParam(int256 poolMarginRiskParam);\\n    event SetTradeFeeRate(int256 tradeFeeRate, int256 protocolFeeRate);\\n    event SetSpreadParams(uint256 safetyPeriod, uint256 numBlocksPerSpreadDecreasing);\\n\\n    modifier onlyPerpetualMarket() {\\n        require(msg.sender == perpetualMarket, \\\"PMC2\\\");\\n        _;\\n    }\\n\\n    constructor(\\n        address _priceFeedAddress,\\n        string memory _tokenName,\\n        string memory _tokenSymbol,\\n        address _arbSysAddress\\n    ) ERC20(_tokenName, _tokenSymbol) {\\n        // The decimals of LP token is 8\\n        _setupDecimals(8);\\n\\n        priceFeed = AggregatorV3Interface(_priceFeedAddress);\\n\\n        arbSys = ArbSys(_arbSysAddress);\\n\\n        // initialize spread infos\\n        spreadInfos[0].init();\\n        spreadInfos[1].init();\\n        lpTokenSpreadInfo.init();\\n\\n        // 550%\\n        squaredPerpFundingMultiplier = 550 * 1e6;\\n        // 0.22%\\n        perpFutureMaxFundingRate = 22 * 1e4;\\n        // min slippage tolerance of a hedge is 0.4%\\n        minSlippageToleranceOfHedge = 40;\\n        // max slippage tolerance of a hedge is 0.8%\\n        maxSlippageToleranceOfHedge = 80;\\n        // rate of return threshold of a hedge is 2.5 %\\n        hedgeRateOfReturnThreshold = 25 * 1e5;\\n        // Pool collateral risk param is 40%\\n        poolMarginRiskParam = 4000;\\n        // Trade fee is 0.05%\\n        tradeFeeRate = 5 * 1e4;\\n        // Protocol fee is 0.01%\\n        protocolFeeRate = 1 * 1e4;\\n    }\\n\\n    function setPerpetualMarket(address _perpetualMarket) external onlyOwner {\\n        require(perpetualMarket == address(0) && _perpetualMarket != address(0));\\n        perpetualMarket = _perpetualMarket;\\n    }\\n\\n    /**\\n     * @notice Initialize pool with initial liquidity and funding rate\\n     */\\n    function initialize(\\n        address _depositor,\\n        uint256 _depositAmount,\\n        int256 _initialFundingRate\\n    ) external override onlyPerpetualMarket returns (uint256 mintAmount) {\\n        require(totalSupply() == 0);\\n        mintAmount = _depositAmount;\\n\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        // initialize pool snapshot\\n        poolSnapshot.ethVariance = _initialFundingRate.toInt128();\\n        poolSnapshot.ethPrice = spotPrice.toInt128();\\n        poolSnapshot.lastSnapshotTime = block.timestamp.toUint128();\\n\\n        // initialize last spot price at heding\\n        lastHedgeSpotPrice = spotPrice;\\n\\n        amountLiquidity = amountLiquidity.add(_depositAmount);\\n        _mint(_depositor, mintAmount);\\n    }\\n\\n    /**\\n     * @notice Provides liquidity\\n     */\\n    function deposit(address _depositor, uint256 _depositAmount)\\n        external\\n        override\\n        onlyPerpetualMarket\\n        returns (uint256 mintAmount)\\n    {\\n        require(totalSupply() > 0);\\n\\n        uint256 lpTokenPrice = getLPTokenPrice(_depositAmount.toInt256());\\n\\n        lpTokenPrice = lpTokenSpreadInfo.checkPrice(true, int256(lpTokenPrice), arbSys.arbBlockNumber()).toUint256();\\n\\n        mintAmount = _depositAmount.mul(1e16).div(lpTokenPrice);\\n\\n        amountLiquidity = amountLiquidity.add(_depositAmount);\\n        _mint(_depositor, mintAmount);\\n    }\\n\\n    /**xx\\n     * @notice Withdraws liquidity\\n     */\\n    function withdraw(address _withdrawer, uint256 _withdrawnAmount)\\n        external\\n        override\\n        onlyPerpetualMarket\\n        returns (uint256 burnAmount)\\n    {\\n        require(getAvailableLiquidityAmount() >= _withdrawnAmount, \\\"PMC0\\\");\\n\\n        uint256 lpTokenPrice = getLPTokenPrice(-_withdrawnAmount.toInt256());\\n\\n        lpTokenPrice = lpTokenSpreadInfo.checkPrice(false, int256(lpTokenPrice), arbSys.arbBlockNumber()).toUint256();\\n\\n        burnAmount = _withdrawnAmount.mul(1e16).div(lpTokenPrice);\\n\\n        amountLiquidity = amountLiquidity.sub(_withdrawnAmount);\\n        _burn(_withdrawer, burnAmount);\\n    }\\n\\n    function addLiquidity(uint256 _amount) external override onlyPerpetualMarket {\\n        amountLiquidity = amountLiquidity.add(_amount);\\n    }\\n\\n    /**\\n     * @notice Adds or removes pool positions\\n     * @param _tradeAmounts amount of positions to trade.\\n     * positive for pool short and negative for pool long.\\n     */\\n    function updatePoolPositions(int256[2] memory _tradeAmounts)\\n        public\\n        override\\n        onlyPerpetualMarket\\n        returns (\\n            uint256[2] memory tradePrice,\\n            int256[2] memory fundingPaidPerPosition,\\n            uint256 protocolFee\\n        )\\n    {\\n        require(amountLiquidity > 0, \\\"PMC1\\\");\\n\\n        int256 profitValue = 0;\\n\\n        // Updates pool positions\\n        pools[0].positionPerpetuals = pools[0].positionPerpetuals.sub(_tradeAmounts[0]).toInt128();\\n        pools[1].positionPerpetuals = pools[1].positionPerpetuals.sub(_tradeAmounts[1]).toInt128();\\n\\n        if (_tradeAmounts[0] != 0) {\\n            uint256 futureProtocolFee;\\n            int256 futureProfitValue;\\n            (tradePrice[0], fundingPaidPerPosition[0], futureProtocolFee, futureProfitValue) = updatePoolPosition(\\n                0,\\n                _tradeAmounts[0]\\n            );\\n            protocolFee = protocolFee.add(futureProtocolFee);\\n            profitValue = profitValue.add(futureProfitValue);\\n        }\\n        if (_tradeAmounts[1] != 0) {\\n            uint256 squaredProtocolFee;\\n            int256 squaredProfitValue;\\n            (tradePrice[1], fundingPaidPerPosition[1], squaredProtocolFee, squaredProfitValue) = updatePoolPosition(\\n                1,\\n                _tradeAmounts[1]\\n            );\\n            protocolFee = protocolFee.add(squaredProtocolFee);\\n            profitValue = profitValue.add(squaredProfitValue);\\n        }\\n\\n        amountLiquidity = Math.addDelta(amountLiquidity, profitValue.sub(protocolFee.toInt256()));\\n    }\\n\\n    /**\\n     * @notice Adds or removes pool position for a product\\n     * @param _productId product id\\n     * @param _tradeAmount amount of position to trade. positive for pool short and negative for pool long.\\n     */\\n    function updatePoolPosition(uint256 _productId, int256 _tradeAmount)\\n        internal\\n        returns (\\n            uint256 tradePrice,\\n            int256,\\n            uint256 protocolFee,\\n            int256 profitValue\\n        )\\n    {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        // Calculate trade price\\n        (tradePrice, protocolFee) = calculateSafeTradePrice(_productId, spotPrice, _tradeAmount);\\n\\n        {\\n            int256 newEntryPrice;\\n            (newEntryPrice, profitValue) = EntryPriceMath.updateEntryPrice(\\n                int256(pools[_productId].entryPrice),\\n                pools[_productId].positionPerpetuals.add(_tradeAmount),\\n                int256(tradePrice),\\n                -_tradeAmount\\n            );\\n\\n            pools[_productId].entryPrice = newEntryPrice.toUint256().toUint128();\\n        }\\n\\n        return (tradePrice, pools[_productId].amountFundingPaidPerPosition, protocolFee, profitValue);\\n    }\\n\\n    /**\\n     * @notice Locks liquidity if more collateral required\\n     * and unlocks liquidity if there is unrequied collateral.\\n     */\\n    function rebalance() external override onlyPerpetualMarket {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            int256 deltaMargin;\\n            int256 deltaLiquidity;\\n\\n            {\\n                int256 hedgePositionValue;\\n                (deltaMargin, hedgePositionValue) = addMargin(i, spotPrice);\\n\\n                (, deltaMargin, deltaLiquidity) = calculatePreTrade(\\n                    i,\\n                    deltaMargin,\\n                    hedgePositionValue,\\n                    MarginChange.LongToLong\\n                );\\n            }\\n\\n            if (deltaLiquidity != 0) {\\n                amountLiquidity = Math.addDelta(amountLiquidity, deltaLiquidity);\\n            }\\n            if (deltaMargin != 0) {\\n                pools[i].amountLockedLiquidity = Math.addDelta(pools[i].amountLockedLiquidity, deltaMargin).toUint128();\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets USDC and underlying amount to make the pool delta neutral\\n     */\\n    function getTokenAmountForHedging()\\n        external\\n        view\\n        override\\n        returns (NettingLib.CompleteParams memory completeParams)\\n    {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        (int256 futurePoolDelta, int256 sqeethPoolDelta) = getDeltas(\\n            spotPrice,\\n            pools[0].positionPerpetuals,\\n            pools[1].positionPerpetuals\\n        );\\n\\n        int256[2] memory deltas;\\n\\n        deltas[0] = futurePoolDelta;\\n        deltas[1] = sqeethPoolDelta;\\n\\n        completeParams = NettingLib.getRequiredTokenAmountsForHedge(nettingInfo.amountUnderlying, deltas, spotPrice);\\n\\n        uint256 slippageTolerance = calculateSlippageToleranceForHedging(spotPrice);\\n\\n        if (completeParams.isLong) {\\n            completeParams.amountUsdc = (completeParams.amountUsdc.mul(uint256(10000).add(slippageTolerance))).div(\\n                10000\\n            );\\n        } else {\\n            completeParams.amountUsdc = (completeParams.amountUsdc.mul(uint256(10000).sub(slippageTolerance))).div(\\n                10000\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @notice Update netting info to complete heging procedure\\n     */\\n    function completeHedgingProcedure(NettingLib.CompleteParams memory _completeParams)\\n        external\\n        override\\n        onlyPerpetualMarket\\n    {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        lastHedgeSpotPrice = spotPrice;\\n\\n        nettingInfo.complete(_completeParams);\\n    }\\n\\n    function getNettingInfo() external view returns (NettingLib.Info memory) {\\n        return nettingInfo;\\n    }\\n\\n    /**\\n     * @notice Updates pool snapshot\\n     * Calculates ETH variance and base funding rate for future pool.\\n     */\\n    function updatePoolSnapshot() external override onlyPerpetualMarket {\\n        if (block.timestamp < poolSnapshot.lastSnapshotTime + 12 hours) {\\n            return;\\n        }\\n\\n        updateVariance(block.timestamp);\\n        updateBaseFundingRate();\\n    }\\n\\n    function executeFundingPayment() external override onlyPerpetualMarket {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        // Funding payment\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            _executeFundingPayment(i, spotPrice);\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates ETH variance under the Exponentially Weighted Moving Average Model.\\n     */\\n    function updateVariance(uint256 _timestamp) internal {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        // u_{t-1} = (S_t - S_{t-1}) / S_{t-1}\\n        int256 u = spotPrice.sub(poolSnapshot.ethPrice).mul(1e8).div(poolSnapshot.ethPrice);\\n\\n        int256 uPower2 = u.mul(u).div(1e8);\\n\\n        // normalization\\n        uPower2 = (uPower2.mul(FUNDING_PERIOD)).div((_timestamp - poolSnapshot.lastSnapshotTime).toInt256());\\n\\n        // Updates snapshot\\n        // variance_{t} = \\u03bb * variance_{t-1} + (1 - \\u03bb) * u_{t-1}^2\\n        poolSnapshot.ethVariance = ((LAMBDA.mul(poolSnapshot.ethVariance).add((1e8 - LAMBDA).mul(uPower2))) / 1e8)\\n            .toInt128();\\n        poolSnapshot.ethPrice = spotPrice.toInt128();\\n        poolSnapshot.lastSnapshotTime = _timestamp.toUint128();\\n\\n        emit VarianceUpdated(poolSnapshot.ethVariance, poolSnapshot.ethPrice, _timestamp);\\n    }\\n\\n    function updateBaseFundingRate() internal {\\n        poolSnapshot.futureBaseFundingRate = 0;\\n    }\\n\\n    /////////////////////////\\n    //  Admin Functions    //\\n    /////////////////////////\\n\\n    function setSquaredPerpFundingMultiplier(int256 _squaredPerpFundingMultiplier) external onlyOwner {\\n        require(_squaredPerpFundingMultiplier >= 0 && _squaredPerpFundingMultiplier <= 2000 * 1e6);\\n        squaredPerpFundingMultiplier = _squaredPerpFundingMultiplier;\\n        emit SetSquaredPerpFundingMultiplier(_squaredPerpFundingMultiplier);\\n    }\\n\\n    function setPerpFutureMaxFundingRate(int256 _perpFutureMaxFundingRate) external onlyOwner {\\n        require(_perpFutureMaxFundingRate >= 0 && _perpFutureMaxFundingRate <= 1 * 1e6);\\n        perpFutureMaxFundingRate = _perpFutureMaxFundingRate;\\n        emit SetPerpFutureMaxFundingRate(_perpFutureMaxFundingRate);\\n    }\\n\\n    function setHedgeParams(\\n        uint256 _minSlippageToleranceOfHedge,\\n        uint256 _maxSlippageToleranceOfHedge,\\n        uint256 _hedgeRateOfReturnThreshold\\n    ) external onlyOwner {\\n        require(\\n            _minSlippageToleranceOfHedge >= 0 && _maxSlippageToleranceOfHedge >= 0 && _hedgeRateOfReturnThreshold >= 0\\n        );\\n        require(\\n            _minSlippageToleranceOfHedge < _maxSlippageToleranceOfHedge && _maxSlippageToleranceOfHedge <= 200,\\n            \\\"PMC5\\\"\\n        );\\n\\n        minSlippageToleranceOfHedge = _minSlippageToleranceOfHedge;\\n        maxSlippageToleranceOfHedge = _maxSlippageToleranceOfHedge;\\n        hedgeRateOfReturnThreshold = _hedgeRateOfReturnThreshold;\\n        emit SetHedgeParams(_minSlippageToleranceOfHedge, _maxSlippageToleranceOfHedge, _hedgeRateOfReturnThreshold);\\n    }\\n\\n    function setPoolMarginRiskParam(int256 _poolMarginRiskParam) external onlyOwner {\\n        require(_poolMarginRiskParam >= 0);\\n        poolMarginRiskParam = _poolMarginRiskParam;\\n        emit SetPoolMarginRiskParam(_poolMarginRiskParam);\\n    }\\n\\n    function setTradeFeeRate(int256 _tradeFeeRate, int256 _protocolFeeRate) external onlyOwner {\\n        require(0 <= _protocolFeeRate && _tradeFeeRate <= 30 * 1e4 && _protocolFeeRate < _tradeFeeRate, \\\"PMC5\\\");\\n        tradeFeeRate = _tradeFeeRate;\\n        protocolFeeRate = _protocolFeeRate;\\n        emit SetTradeFeeRate(_tradeFeeRate, _protocolFeeRate);\\n    }\\n\\n    function setSpreadParams(uint256 _safetyPeriod, uint256 _numBlocksPerSpreadDecreasing) external onlyOwner {\\n        require(0 <= _safetyPeriod && _safetyPeriod <= 600, \\\"PMC5\\\");\\n        require(0 < _numBlocksPerSpreadDecreasing && _numBlocksPerSpreadDecreasing <= 600, \\\"PMC5\\\");\\n\\n        spreadInfos[0].setParams(_safetyPeriod, _numBlocksPerSpreadDecreasing);\\n        spreadInfos[1].setParams(_safetyPeriod, _numBlocksPerSpreadDecreasing);\\n        lpTokenSpreadInfo.setParams(_safetyPeriod, _numBlocksPerSpreadDecreasing);\\n        emit SetSpreadParams(_safetyPeriod, _numBlocksPerSpreadDecreasing);\\n    }\\n\\n    /////////////////////////\\n    //  Getter Functions   //\\n    /////////////////////////\\n\\n    /**\\n     * @notice Gets LP token price\\n     * LPTokenPrice = (L + \\u03a3UnrealizedPnL_i - \\u03a3AmountLockedLiquidity_i) / Supply\\n     * @return LPTokenPrice scaled by 1e16\\n     */\\n    function getLPTokenPrice(int256 _deltaLiquidityAmount) public view override returns (uint256) {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        int256 unrealizedPnL = (\\n            getUnrealizedPnL(0, spotPrice, _deltaLiquidityAmount).add(\\n                getUnrealizedPnL(1, spotPrice, _deltaLiquidityAmount)\\n            )\\n        );\\n\\n        int256 hedgePositionValue = nettingInfo.getTotalHedgePositionValue(spotPrice);\\n\\n        return\\n            (\\n                (\\n                    uint256(amountLiquidity.toInt256().add(hedgePositionValue).add(unrealizedPnL))\\n                        .sub(pools[0].amountLockedLiquidity)\\n                        .sub(pools[1].amountLockedLiquidity)\\n                ).mul(1e16)\\n            ).div(totalSupply());\\n    }\\n\\n    /**\\n     * @notice Gets trade price\\n     * @param _productId product id\\n     * @param _tradeAmounts amount of position to trade. positive for pool short and negative for pool long.\\n     */\\n    function getTradePrice(uint256 _productId, int256[2] memory _tradeAmounts)\\n        external\\n        view\\n        override\\n        returns (\\n            int256,\\n            int256,\\n            int256,\\n            int256,\\n            int256\\n        )\\n    {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        return calculateTradePriceReadOnly(_productId, spotPrice, _tradeAmounts, 0);\\n    }\\n\\n    /**\\n     * @notice Gets utilization ratio\\n     * Utilization Ratio = (\\u03a3AmountLockedLiquidity_i) / L\\n     * @return Utilization Ratio scaled by 1e8\\n     */\\n    function getUtilizationRatio() external view returns (uint256) {\\n        uint256 amountLocked;\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            amountLocked = amountLocked.add(pools[i].amountLockedLiquidity);\\n        }\\n\\n        return amountLocked.mul(1e8).div(amountLiquidity);\\n    }\\n\\n    function getTradePriceInfo(int256[2] memory _tradeAmounts) external view override returns (TradePriceInfo memory) {\\n        (int256 spotPrice, ) = getUnderlyingPrice();\\n\\n        int256[2] memory tradePrices;\\n        int256[2] memory fundingRates;\\n        int256[2] memory amountFundingPaidPerPositionGlobals;\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            int256 indexPrice;\\n            (tradePrices[i], indexPrice, fundingRates[i], , ) = calculateTradePriceReadOnly(\\n                i,\\n                spotPrice,\\n                _tradeAmounts,\\n                0\\n            );\\n\\n            // funding payments should be calculated from the current funding rate\\n            int256 currentFundingRate = getCurrentFundingRate(i);\\n\\n            int256 fundingFeePerPosition = calculateFundingFeePerPosition(\\n                i,\\n                indexPrice,\\n                currentFundingRate,\\n                block.timestamp\\n            );\\n\\n            amountFundingPaidPerPositionGlobals[i] = pools[i].amountFundingPaidPerPosition.add(fundingFeePerPosition);\\n        }\\n\\n        return TradePriceInfo(uint128(spotPrice), tradePrices, fundingRates, amountFundingPaidPerPositionGlobals);\\n    }\\n\\n    /////////////////////////\\n    //  Private Functions  //\\n    /////////////////////////\\n\\n    /**\\n     * @notice Executes funding payment\\n     */\\n    function _executeFundingPayment(uint256 _productId, int256 _spotPrice) internal {\\n        if (pools[_productId].lastFundingPaymentTime == 0) {\\n            // Initialize timestamp\\n            pools[_productId].lastFundingPaymentTime = uint128(block.timestamp);\\n            return;\\n        }\\n\\n        if (block.timestamp <= pools[_productId].lastFundingPaymentTime) {\\n            return;\\n        }\\n\\n        (\\n            int256 currentFundingRate,\\n            int256 fundingFeePerPosition,\\n            int256 fundingReceived\\n        ) = calculateResultOfFundingPayment(_productId, _spotPrice, block.timestamp);\\n\\n        pools[_productId].amountFundingPaidPerPosition = pools[_productId].amountFundingPaidPerPosition.add(\\n            fundingFeePerPosition\\n        );\\n\\n        if (fundingReceived != 0) {\\n            amountLiquidity = Math.addDelta(amountLiquidity, fundingReceived);\\n        }\\n\\n        // Update last timestamp of funding payment\\n        pools[_productId].lastFundingPaymentTime = uint128(block.timestamp);\\n\\n        emit FundingPayment(\\n            _productId,\\n            currentFundingRate,\\n            pools[_productId].amountFundingPaidPerPosition,\\n            fundingFeePerPosition,\\n            fundingReceived\\n        );\\n    }\\n\\n    /**\\n     * @notice Calculates funding rate, funding fee per position and funding fee that the pool will receive.\\n     * @param _productId product id\\n     * @param _spotPrice current spot price for index calculation\\n     * @param _currentTimestamp the timestamp to execute funding payment\\n     */\\n    function calculateResultOfFundingPayment(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        uint256 _currentTimestamp\\n    )\\n        internal\\n        view\\n        returns (\\n            int256 currentFundingRate,\\n            int256 fundingFeePerPosition,\\n            int256 fundingReceived\\n        )\\n    {\\n        int256 indexPrice = IndexPricer.calculateIndexPrice(_productId, _spotPrice);\\n\\n        currentFundingRate = getCurrentFundingRate(_productId);\\n\\n        fundingFeePerPosition = calculateFundingFeePerPosition(\\n            _productId,\\n            indexPrice,\\n            currentFundingRate,\\n            _currentTimestamp\\n        );\\n\\n        // Pool receives 'FundingPaidPerPosition * -(Pool Positions)' USDC as funding fee.\\n        fundingReceived = (fundingFeePerPosition.mul(-pools[_productId].positionPerpetuals)).div(1e16);\\n    }\\n\\n    /**\\n     * @notice Calculates amount of funding fee which long position should pay per position.\\n     * FundingPaidPerPosition = IndexPrice * FundingRate * (T-t) / 1 days\\n     * @param _productId product id\\n     * @param _indexPrice index price of the perpetual\\n     * @param _currentFundingRate current funding rate used to calculate funding fee\\n     * @param _currentTimestamp the timestamp to execute funding payment\\n     */\\n    function calculateFundingFeePerPosition(\\n        uint256 _productId,\\n        int256 _indexPrice,\\n        int256 _currentFundingRate,\\n        uint256 _currentTimestamp\\n    ) internal view returns (int256 fundingFeePerPosition) {\\n        fundingFeePerPosition = _indexPrice.mul(_currentFundingRate).div(1e8);\\n\\n        // Normalization by FUNDING_PERIOD\\n        fundingFeePerPosition = (\\n            fundingFeePerPosition.mul(int256(_currentTimestamp.sub(pools[_productId].lastFundingPaymentTime)))\\n        ).div(FUNDING_PERIOD);\\n    }\\n\\n    /**\\n     * @notice Gets current funding rate\\n     * @param _productId product id\\n     */\\n    function getCurrentFundingRate(uint256 _productId) internal view returns (int256) {\\n        return\\n            calculateFundingRate(\\n                _productId,\\n                getSignedMarginAmount(pools[_productId].positionPerpetuals, _productId),\\n                amountLiquidity.toInt256(),\\n                0,\\n                0\\n            );\\n    }\\n\\n    /**\\n     * @notice Calculates signedDeltaMargin and changes of lockedLiquidity and totalLiquidity.\\n     * @return signedDeltaMargin is \\u0394margin: the change of the signed margin.\\n     * @return unlockLiquidityAmount is the change of the absolute amount of margin.\\n     * if return value is negative it represents unrequired.\\n     * @return deltaLiquidity \\u0394liquidity: the change of the total liquidity amount.\\n     */\\n    function calculatePreTrade(\\n        uint256 _productId,\\n        int256 _deltaMargin,\\n        int256 _hedgePositionValue,\\n        MarginChange _marginChangeType\\n    )\\n        internal\\n        view\\n        returns (\\n            int256 signedDeltaMargin,\\n            int256 unlockLiquidityAmount,\\n            int256 deltaLiquidity\\n        )\\n    {\\n        if (_deltaMargin > 0) {\\n            if (_hedgePositionValue >= 0) {\\n                // In case of lock additional margin\\n                require(getAvailableLiquidityAmount() >= uint256(_deltaMargin), \\\"PMC1\\\");\\n                unlockLiquidityAmount = _deltaMargin;\\n            } else {\\n                // unlock all negative hedgePositionValue\\n                (deltaLiquidity, unlockLiquidityAmount) = (\\n                    _hedgePositionValue.sub(pools[_productId].amountLockedLiquidity.toInt256()),\\n                    -pools[_productId].amountLockedLiquidity.toInt256()\\n                );\\n                // lock additional margin\\n                require(getAvailableLiquidityAmount() >= uint256(_deltaMargin.add(_hedgePositionValue)), \\\"PMC1\\\");\\n                unlockLiquidityAmount = unlockLiquidityAmount.add(_deltaMargin.add(_hedgePositionValue));\\n            }\\n        } else if (_deltaMargin < 0) {\\n            // In case of unlock unrequired margin\\n            // _hedgePositionValue should be positive because _deltaMargin=RequiredMargin-_hedgePositionValue<0 => 0<RequiredMargin<_hedgePositionValue\\n            (deltaLiquidity, unlockLiquidityAmount) = calculateUnlockedLiquidity(\\n                pools[_productId].amountLockedLiquidity,\\n                _deltaMargin,\\n                _hedgePositionValue\\n            );\\n        }\\n\\n        // Calculate signedDeltaMargin\\n        signedDeltaMargin = calculateSignedDeltaMargin(\\n            _marginChangeType,\\n            unlockLiquidityAmount,\\n            pools[_productId].amountLockedLiquidity\\n        );\\n    }\\n\\n    /**\\n     * @notice Calculates trade price checked by spread manager\\n     * @return trade price and total protocol fee\\n     */\\n    function calculateSafeTradePrice(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        int256 _tradeAmount\\n    ) internal returns (uint256, uint256) {\\n        int256 deltaMargin;\\n        int256 signedDeltaMargin;\\n        int256 deltaLiquidity;\\n        {\\n            int256 hedgePositionValue;\\n            (deltaMargin, hedgePositionValue) = addMargin(_productId, _spotPrice);\\n            (signedDeltaMargin, deltaMargin, deltaLiquidity) = calculatePreTrade(\\n                _productId,\\n                deltaMargin,\\n                hedgePositionValue,\\n                getMarginChange(pools[_productId].positionPerpetuals, _tradeAmount)\\n            );\\n        }\\n\\n        int256 signedMarginAmount = getSignedMarginAmount(\\n            // Calculate pool position before trade\\n            pools[_productId].positionPerpetuals.add(_tradeAmount),\\n            _productId\\n        );\\n\\n        (int256 tradePrice, int256 protocolFee) = calculateTradePriceAndProtocolFee(\\n            _productId,\\n            _spotPrice,\\n            _tradeAmount,\\n            signedMarginAmount,\\n            signedDeltaMargin,\\n            deltaLiquidity\\n        );\\n\\n        // Update pool liquidity and locked liquidity\\n        {\\n            if (deltaLiquidity != 0) {\\n                amountLiquidity = Math.addDelta(amountLiquidity, deltaLiquidity);\\n            }\\n            pools[_productId].amountLockedLiquidity = Math\\n                .addDelta(pools[_productId].amountLockedLiquidity, deltaMargin)\\n                .toUint128();\\n        }\\n\\n        return (tradePrice.toUint256(), protocolFee.toUint256().mul(Math.abs(_tradeAmount)).div(1e8));\\n    }\\n\\n    function calculateTradePriceAndProtocolFee(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        int256 _tradeAmount,\\n        int256 _signedMarginAmount,\\n        int256 _signedDeltaMargin,\\n        int256 _deltaLiquidity\\n    ) internal returns (int256 tradePrice, int256 protocolFee) {\\n        (tradePrice, , , , protocolFee) = calculateTradePrice(\\n            _productId,\\n            _spotPrice,\\n            _tradeAmount > 0,\\n            _signedMarginAmount,\\n            amountLiquidity.toInt256(),\\n            _signedDeltaMargin,\\n            _deltaLiquidity\\n        );\\n\\n        tradePrice = spreadInfos[_productId].checkPrice(_tradeAmount > 0, tradePrice, arbSys.arbBlockNumber());\\n    }\\n\\n    /**\\n     * @notice Calculates trade price as read-only trade.\\n     * @return tradePrice , indexPrice, fundingRate, tradeFee and protocolFee\\n     */\\n    function calculateTradePriceReadOnly(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        int256[2] memory _tradeAmounts,\\n        int256 _deltaLiquidity\\n    )\\n        internal\\n        view\\n        returns (\\n            int256 tradePrice,\\n            int256 indexPrice,\\n            int256 estFundingRate,\\n            int256 tradeFee,\\n            int256 protocolFee\\n        )\\n    {\\n        int256 signedDeltaMargin;\\n\\n        if (_tradeAmounts[_productId] != 0) {\\n            (int256 deltaMargin, int256 hedgePositionValue, MarginChange marginChangeType) = getRequiredMargin(\\n                _productId,\\n                _spotPrice,\\n                _tradeAmounts\\n            );\\n\\n            int256 deltaLiquidityByTrade;\\n\\n            (signedDeltaMargin, , deltaLiquidityByTrade) = calculatePreTrade(\\n                _productId,\\n                deltaMargin,\\n                hedgePositionValue,\\n                marginChangeType\\n            );\\n\\n            _deltaLiquidity = _deltaLiquidity.add(deltaLiquidityByTrade);\\n        }\\n        {\\n            int256 signedMarginAmount = getSignedMarginAmount(pools[_productId].positionPerpetuals, _productId);\\n\\n            (tradePrice, indexPrice, , tradeFee, protocolFee) = calculateTradePrice(\\n                _productId,\\n                _spotPrice,\\n                _tradeAmounts[_productId] > 0,\\n                signedMarginAmount,\\n                amountLiquidity.toInt256(),\\n                signedDeltaMargin,\\n                _deltaLiquidity\\n            );\\n\\n            // Calculate estimated funding rate\\n            estFundingRate = calculateFundingRate(\\n                _productId,\\n                signedMarginAmount.add(signedDeltaMargin),\\n                amountLiquidity.toInt256().add(_deltaLiquidity),\\n                0,\\n                0\\n            );\\n        }\\n\\n        tradePrice = spreadInfos[_productId].getUpdatedPrice(\\n            _tradeAmounts[_productId] > 0,\\n            tradePrice,\\n            block.timestamp\\n        );\\n\\n        return (tradePrice, indexPrice, estFundingRate, tradeFee, protocolFee);\\n    }\\n\\n    /**\\n     * @notice Adds margin to Netting contract\\n     */\\n    function addMargin(uint256 _productId, int256 _spot)\\n        internal\\n        returns (int256 deltaMargin, int256 hedgePositionValue)\\n    {\\n        (int256 delta0, int256 delta1) = getDeltas(_spot, pools[0].positionPerpetuals, pools[1].positionPerpetuals);\\n        int256 gamma = (IndexPricer.calculateGamma(1).mul(pools[1].positionPerpetuals)) / 1e8;\\n\\n        (deltaMargin, hedgePositionValue) = nettingInfo.addMargin(\\n            _productId,\\n            NettingLib.AddMarginParams(delta0, delta1, gamma, _spot, poolMarginRiskParam)\\n        );\\n    }\\n\\n    /**\\n     * @notice Calculated required or unrequired margin for read-only price calculation.\\n     * @return deltaMargin is the change of the absolute amount of margin.\\n     * @return hedgePositionValue is current value of locked margin.\\n     * if return value is negative it represents unrequired.\\n     */\\n    function getRequiredMargin(\\n        uint256 _productId,\\n        int256 _spot,\\n        int256[2] memory _tradeAmounts\\n    )\\n        internal\\n        view\\n        returns (\\n            int256 deltaMargin,\\n            int256 hedgePositionValue,\\n            MarginChange marginChangeType\\n        )\\n    {\\n        int256 delta0;\\n        int256 delta1;\\n        int256 gamma;\\n\\n        {\\n            int256 tradeAmount0 = pools[0].positionPerpetuals;\\n            int256 tradeAmount1 = pools[1].positionPerpetuals;\\n\\n            tradeAmount0 = tradeAmount0.sub(_tradeAmounts[0]);\\n            tradeAmount1 = tradeAmount1.sub(_tradeAmounts[1]);\\n\\n            if (_productId == 0) {\\n                marginChangeType = getMarginChange(tradeAmount0, _tradeAmounts[0]);\\n            }\\n\\n            if (_productId == 1) {\\n                marginChangeType = getMarginChange(tradeAmount1, _tradeAmounts[1]);\\n            }\\n\\n            (delta0, delta1) = getDeltas(_spot, tradeAmount0, tradeAmount1);\\n            gamma = (IndexPricer.calculateGamma(1).mul(tradeAmount1)) / 1e8;\\n        }\\n\\n        NettingLib.AddMarginParams memory params = NettingLib.AddMarginParams(\\n            delta0,\\n            delta1,\\n            gamma,\\n            _spot,\\n            poolMarginRiskParam\\n        );\\n\\n        int256 totalRequiredMargin = NettingLib.getRequiredMargin(_productId, params);\\n\\n        hedgePositionValue = nettingInfo.getHedgePositionValue(params, _productId);\\n\\n        deltaMargin = totalRequiredMargin.sub(hedgePositionValue);\\n    }\\n\\n    /**\\n     * @notice Gets signed amount of margin used for trade price calculation.\\n     * @param _position current pool position\\n     * @param _productId product id\\n     * @return signedMargin is calculated by following rule.\\n     * If poolPosition is 0 then SignedMargin is 0.\\n     * If poolPosition is long then SignedMargin is negative.\\n     * If poolPosition is short then SignedMargin is positive.\\n     */\\n    function getSignedMarginAmount(int256 _position, uint256 _productId) internal view returns (int256) {\\n        if (_position == 0) {\\n            return 0;\\n        } else if (_position > 0) {\\n            return -pools[_productId].amountLockedLiquidity.toInt256();\\n        } else {\\n            return pools[_productId].amountLockedLiquidity.toInt256();\\n        }\\n    }\\n\\n    /**\\n     * @notice Get signed delta margin. Signed delta margin is the change of the signed margin.\\n     * It is used for trade price calculation.\\n     * For example, if pool position becomes to short 10 from long 10 and deltaMargin hasn't changed.\\n     * Then deltaMargin should be 0 but signedDeltaMargin should be +20.\\n     * @param _deltaMargin amount of change in margin resulting from the trade\\n     * @param _currentMarginAmount amount of locked margin before trade\\n     * @return signedDeltaMargin is calculated by follows.\\n     * Crossing case:\\n     *   If position moves long to short then\\n     *     \\u0394m = currentMarginAmount * 2 + deltaMargin\\n     *   If position moves short to long then\\n     *     \\u0394m = -(currentMarginAmount * 2 + deltaMargin)\\n     * Non Crossing Case:\\n     *   If position moves long to long then\\n     *     \\u0394m = -deltaMargin\\n     *   If position moves short to short then\\n     *     \\u0394m = deltaMargin\\n     */\\n    function calculateSignedDeltaMargin(\\n        MarginChange _marginChangeType,\\n        int256 _deltaMargin,\\n        int256 _currentMarginAmount\\n    ) internal pure returns (int256) {\\n        if (_marginChangeType == MarginChange.LongToShort) {\\n            return _currentMarginAmount.mul(2).add(_deltaMargin);\\n        } else if (_marginChangeType == MarginChange.ShortToLong) {\\n            return -(_currentMarginAmount.mul(2).add(_deltaMargin));\\n        } else if (_marginChangeType == MarginChange.LongToLong) {\\n            return -_deltaMargin;\\n        } else {\\n            // In case of ShortToShort\\n            return _deltaMargin;\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets the type of margin change.\\n     * @param _newPosition positions resulting from trades\\n     * @param _positionTrade delta positions to trade\\n     * @return marginChange the type of margin change\\n     */\\n    function getMarginChange(int256 _newPosition, int256 _positionTrade) internal pure returns (MarginChange) {\\n        int256 position = _newPosition.add(_positionTrade);\\n\\n        if (position > 0 && _newPosition < 0) {\\n            return MarginChange.LongToShort;\\n        } else if (position < 0 && _newPosition > 0) {\\n            return MarginChange.ShortToLong;\\n        } else if (position >= 0 && _newPosition >= 0) {\\n            return MarginChange.LongToLong;\\n        } else {\\n            return MarginChange.ShortToShort;\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates delta liquidity amount and unlock liquidity amount\\n     * unlockLiquidityAmount = \\u0394m * amountLockedLiquidity / hedgePositionValue\\n     * deltaLiquidity = \\u0394m - UnlockAmount\\n     */\\n    function calculateUnlockedLiquidity(\\n        uint256 _amountLockedLiquidity,\\n        int256 _deltaMargin,\\n        int256 _hedgePositionValue\\n    ) internal pure returns (int256 deltaLiquidity, int256 unlockLiquidityAmount) {\\n        unlockLiquidityAmount = _deltaMargin.mul(_amountLockedLiquidity.toInt256()).div(_hedgePositionValue);\\n\\n        return ((unlockLiquidityAmount.sub(_deltaMargin)), unlockLiquidityAmount);\\n    }\\n\\n    /**\\n     * @notice Calculates perpetual's trade price\\n     * TradePrice = IndexPrice * (1 + FundingRate) + TradeFee\\n     * @return TradePrice scaled by 1e8\\n     */\\n    function calculateTradePrice(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        bool _isLong,\\n        int256 _margin,\\n        int256 _totalLiquidityAmount,\\n        int256 _deltaMargin,\\n        int256 _deltaLiquidity\\n    )\\n        internal\\n        view\\n        returns (\\n            int256,\\n            int256 indexPrice,\\n            int256,\\n            int256 tradeFee,\\n            int256 protocolFee\\n        )\\n    {\\n        int256 fundingRate = calculateFundingRate(\\n            _productId,\\n            _margin,\\n            _totalLiquidityAmount,\\n            _deltaMargin,\\n            _deltaLiquidity\\n        );\\n\\n        indexPrice = IndexPricer.calculateIndexPrice(_productId, _spotPrice);\\n\\n        int256 tradePrice = (indexPrice.mul(int256(1e16).add(fundingRate))).div(1e16);\\n\\n        tradeFee = getTradeFee(_productId, _isLong, indexPrice);\\n\\n        tradePrice = tradePrice.add(tradeFee);\\n\\n        protocolFee = getProtocolFee(_productId, indexPrice);\\n\\n        return (tradePrice, indexPrice, fundingRate, Math.abs(tradeFee).toInt256(), protocolFee);\\n    }\\n\\n    /**\\n     * @notice Gets trade fee\\n     * TradeFee = IndxPrice * tradeFeeRate\\n     */\\n    function getTradeFee(\\n        uint256 _productId,\\n        bool _isLong,\\n        int256 _indexPrice\\n    ) internal view returns (int256) {\\n        require(_indexPrice > 0);\\n\\n        if (_isLong) {\\n            return _indexPrice.mul(tradeFeeRate).mul(int256(_productId + 1)) / 1e8;\\n        } else {\\n            return -_indexPrice.mul(tradeFeeRate).mul(int256(_productId + 1)) / 1e8;\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets protocol fee\\n     * ProtocolFee = IndxPrice * protocolFeeRate\\n     */\\n    function getProtocolFee(uint256 _productId, int256 _indexPrice) internal view returns (int256) {\\n        require(_indexPrice > 0);\\n\\n        return _indexPrice.mul(protocolFeeRate).mul(int256(_productId + 1)) / 1e8;\\n    }\\n\\n    function getDeltas(\\n        int256 _spotPrice,\\n        int256 _tradeAmount0,\\n        int256 _tradeAmount1\\n    ) internal pure returns (int256, int256) {\\n        int256 futurePoolDelta = (IndexPricer.calculateDelta(0, _spotPrice).mul(_tradeAmount0)) / 1e8;\\n        int256 sqeethPoolDelta = (IndexPricer.calculateDelta(1, _spotPrice).mul(_tradeAmount1)) / 1e8;\\n        return (futurePoolDelta, sqeethPoolDelta);\\n    }\\n\\n    /**\\n     * @notice Calculates Unrealized PnL\\n     * UnrealizedPnL = (TradePrice - EntryPrice) * Position_i + HedgePositionValue\\n     * TradePrice is calculated as fill price of closing all pool positions.\\n     * @return UnrealizedPnL scaled by 1e8\\n     */\\n    function getUnrealizedPnL(\\n        uint256 _productId,\\n        int256 _spotPrice,\\n        int256 _deltaLiquidityAmount\\n    ) internal view returns (int256) {\\n        int256 positionsValue;\\n        int256[2] memory positionPerpetuals;\\n\\n        positionPerpetuals[0] = pools[0].positionPerpetuals;\\n        positionPerpetuals[1] = pools[1].positionPerpetuals;\\n\\n        if (pools[_productId].positionPerpetuals != 0) {\\n            (int256 tradePrice, , , , ) = calculateTradePriceReadOnly(\\n                _productId,\\n                _spotPrice,\\n                positionPerpetuals,\\n                _deltaLiquidityAmount\\n            );\\n            positionsValue =\\n                pools[_productId].positionPerpetuals.mul(tradePrice.sub(pools[_productId].entryPrice.toInt256())) /\\n                1e8;\\n        }\\n\\n        return positionsValue;\\n    }\\n\\n    /**\\n     * @notice Calculates perpetual's funding rate\\n     * Squared:\\n     *   FundingRate = variance * (1 + squaredPerpFundingMultiplier * m / L)\\n     * Future:\\n     *   FundingRate = BASE_FUNDING_RATE + perpFutureMaxFundingRate * (m / L)\\n     * @param _productId product id\\n     * @param _margin amount of locked margin before trade\\n     * @param _totalLiquidityAmount amount of total liquidity before trade\\n     * @param _deltaMargin amount of change in margin resulting from the trade\\n     * @param _deltaLiquidity difference of liquidity\\n     * @return FundingRate scaled by 1e16 (1e16 = 100%)\\n     */\\n    function calculateFundingRate(\\n        uint256 _productId,\\n        int256 _margin,\\n        int256 _totalLiquidityAmount,\\n        int256 _deltaMargin,\\n        int256 _deltaLiquidity\\n    ) internal view returns (int256) {\\n        if (_productId == 0) {\\n            int256 fundingRate = perpFutureMaxFundingRate\\n                .mul(\\n                    PoolMath.calculateFundingRateFormula(_margin, _deltaMargin, _totalLiquidityAmount, _deltaLiquidity)\\n                )\\n                .div(1e8);\\n            return poolSnapshot.futureBaseFundingRate.add(fundingRate);\\n        } else if (_productId == 1) {\\n            if (_totalLiquidityAmount == 0) {\\n                return poolSnapshot.ethVariance.mul(1e8);\\n            } else {\\n                int256 addition = squaredPerpFundingMultiplier\\n                    .mul(\\n                        PoolMath.calculateFundingRateFormula(\\n                            _margin,\\n                            _deltaMargin,\\n                            _totalLiquidityAmount,\\n                            _deltaLiquidity\\n                        )\\n                    )\\n                    .div(1e8);\\n                return poolSnapshot.ethVariance.mul(int256(1e16).add(addition)).div(1e8);\\n            }\\n        }\\n        return 0;\\n    }\\n\\n    /**\\n     * @notice Calculates the slippage tolerance of USDC amount for a hedge\\n     */\\n    function calculateSlippageToleranceForHedging(int256 _spotPrice) internal view returns (uint256 slippageTolerance) {\\n        uint256 rateOfReturn = Math.abs(_spotPrice.sub(lastHedgeSpotPrice).mul(1e8).div(lastHedgeSpotPrice));\\n\\n        slippageTolerance = minSlippageToleranceOfHedge.add(\\n            (maxSlippageToleranceOfHedge - minSlippageToleranceOfHedge).mul(rateOfReturn).div(\\n                hedgeRateOfReturnThreshold\\n            )\\n        );\\n\\n        if (slippageTolerance < minSlippageToleranceOfHedge) slippageTolerance = minSlippageToleranceOfHedge;\\n        if (slippageTolerance > maxSlippageToleranceOfHedge) slippageTolerance = maxSlippageToleranceOfHedge;\\n    }\\n\\n    /**\\n     * @notice Gets available amount of liquidity\\n     * available amount = amountLiquidity - (\\u03a3amountLocked_i)\\n     */\\n    function getAvailableLiquidityAmount() internal view returns (uint256) {\\n        uint256 amountLocked;\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            amountLocked = amountLocked.add(pools[i].amountLockedLiquidity);\\n\\n            if (nettingInfo.amountsUsdc[i] < 0) {\\n                amountLocked = Math.addDelta(amountLocked, -nettingInfo.amountsUsdc[i]);\\n            }\\n        }\\n\\n        return amountLiquidity.sub(amountLocked);\\n    }\\n\\n    /**\\n     * @notice get underlying price scaled by 1e8\\n     */\\n    function getUnderlyingPrice() internal view returns (int256, uint256) {\\n        (, int256 answer, , uint256 roundTimestamp, ) = priceFeed.latestRoundData();\\n\\n        require(answer > 0, \\\"PMC3\\\");\\n\\n        return (answer, roundTimestamp);\\n    }\\n}\\n\",\"keccak256\":\"0x855b6cffbd092f5a82a560d5feee7942ca502099c9b2ab848a09023faeb75a82\",\"license\":\"agpl-3.0\"},\"src/interfaces/IPerpetualMarketCore.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"../lib/NettingLib.sol\\\";\\n\\ninterface IPerpetualMarketCore {\\n    struct TradePriceInfo {\\n        uint128 spotPrice;\\n        int256[2] tradePrices;\\n        int256[2] fundingRates;\\n        int256[2] amountsFundingPaidPerPosition;\\n    }\\n\\n    function initialize(\\n        address _depositor,\\n        uint256 _depositAmount,\\n        int256 _initialFundingRate\\n    ) external returns (uint256 mintAmount);\\n\\n    function deposit(address _depositor, uint256 _depositAmount) external returns (uint256 mintAmount);\\n\\n    function withdraw(address _withdrawer, uint256 _withdrawnAmount) external returns (uint256 burnAmount);\\n\\n    function addLiquidity(uint256 _amount) external;\\n\\n    function updatePoolPositions(int256[2] memory _tradeAmounts)\\n        external\\n        returns (\\n            uint256[2] memory tradePrice,\\n            int256[2] memory,\\n            uint256 protocolFee\\n        );\\n\\n    function completeHedgingProcedure(NettingLib.CompleteParams memory _completeParams) external;\\n\\n    function updatePoolSnapshot() external;\\n\\n    function executeFundingPayment() external;\\n\\n    function getTradePriceInfo(int256[2] memory _tradeAmounts) external view returns (TradePriceInfo memory);\\n\\n    function getTradePrice(uint256 _productId, int256[2] memory _tradeAmounts)\\n        external\\n        view\\n        returns (\\n            int256,\\n            int256,\\n            int256,\\n            int256,\\n            int256\\n        );\\n\\n    function rebalance() external;\\n\\n    function getTokenAmountForHedging() external view returns (NettingLib.CompleteParams memory completeParams);\\n\\n    function getLPTokenPrice(int256 _deltaLiquidityAmount) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x2544ccffc110ad49bbc7ab45491d032c5063ba68130eafa237c392c149eaf3a3\",\"license\":\"agpl-3.0\"},\"src/lib/EntryPriceMath.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"./Math.sol\\\";\\n\\n/**\\n * @title EntryPriceMath\\n * @notice Library contract which has functions to calculate new entry price and profit\\n * from previous entry price and trade price for implementing margin wallet.\\n */\\nlibrary EntryPriceMath {\\n    using SafeCast for uint256;\\n    using SafeMath for uint256;\\n    using SignedSafeMath for int256;\\n\\n    /**\\n     * @notice Calculates new entry price and return profit if position is closed\\n     *\\n     * Calculation Patterns\\n     *  |Position|PositionTrade|NewPosition|Pattern|\\n     *  |       +|            +|          +|      A|\\n     *  |       +|            -|          +|      B|\\n     *  |       +|            -|          -|      C|\\n     *  |       -|            -|          -|      A|\\n     *  |       -|            +|          -|      B|\\n     *  |       -|            +|          +|      C|\\n     *\\n     * Calculations\\n     *  Pattern A (open positions)\\n     *   NewEntryPrice = (EntryPrice * |Position| + TradePrce * |PositionTrade|) / (Position + PositionTrade)\\n     *\\n     *  Pattern B (close positions)\\n     *   NewEntryPrice = EntryPrice\\n     *   ProfitValue = -PositionTrade * (TradePrice - EntryPrice)\\n     *\\n     *  Pattern C (close all positions & open new)\\n     *   NewEntryPrice = TradePrice\\n     *   ProfitValue = Position * (TradePrice - EntryPrice)\\n     *\\n     * @param _entryPrice previous entry price\\n     * @param _position current position\\n     * @param _tradePrice trade price\\n     * @param _positionTrade position to trade\\n     * @return newEntryPrice new entry price\\n     * @return profitValue notional profit value when positions are closed\\n     */\\n    function updateEntryPrice(\\n        int256 _entryPrice,\\n        int256 _position,\\n        int256 _tradePrice,\\n        int256 _positionTrade\\n    ) internal pure returns (int256 newEntryPrice, int256 profitValue) {\\n        int256 newPosition = _position.add(_positionTrade);\\n        if (_position == 0 || (_position > 0 && _positionTrade > 0) || (_position < 0 && _positionTrade < 0)) {\\n            newEntryPrice = (\\n                _entryPrice.mul(int256(Math.abs(_position))).add(_tradePrice.mul(int256(Math.abs(_positionTrade))))\\n            ).div(int256(Math.abs(_position.add(_positionTrade))));\\n        } else if (\\n            (_position > 0 && _positionTrade < 0 && newPosition > 0) ||\\n            (_position < 0 && _positionTrade > 0 && newPosition < 0)\\n        ) {\\n            newEntryPrice = _entryPrice;\\n            profitValue = (-_positionTrade).mul(_tradePrice.sub(_entryPrice)) / 1e8;\\n        } else {\\n            if (newPosition != 0) {\\n                newEntryPrice = _tradePrice;\\n            }\\n\\n            profitValue = _position.mul(_tradePrice.sub(_entryPrice)) / 1e8;\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x76b69923c0d21ff5a04335743b0b4f64ff36a90df6154f030914231abf47c858\",\"license\":\"agpl-3.0\"},\"src/lib/IndexPricer.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\n\\n/**\\n * @title IndexPricer\\n * @notice Library contract that has functions to calculate Index price and Greeks of perpetual\\n */\\nlibrary IndexPricer {\\n    using SignedSafeMath for int256;\\n\\n    /// @dev Scaling factor for squared index price.\\n    int256 public constant SCALING_FACTOR = 1e4;\\n\\n    /**\\n     * @notice Calculates index price of perpetuals\\n     * Future: ETH\\n     * Squeeth: ETH^2 / 10000\\n     * @return calculated index price scaled by 1e8\\n     */\\n    function calculateIndexPrice(uint256 _productId, int256 _spot) internal pure returns (int256) {\\n        if (_productId == 0) {\\n            return _spot;\\n        } else if (_productId == 1) {\\n            return (_spot.mul(_spot)) / (1e8 * SCALING_FACTOR);\\n        } else {\\n            revert(\\\"NP\\\");\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates delta of perpetuals\\n     * Future: 1\\n     * Squeeth: 2 * ETH / 10000\\n     * @return calculated delta scaled by 1e8\\n     */\\n    function calculateDelta(uint256 _productId, int256 _spot) internal pure returns (int256) {\\n        if (_productId == 0) {\\n            return 1e8;\\n        } else if (_productId == 1) {\\n            return _spot.mul(2) / SCALING_FACTOR;\\n        } else {\\n            revert(\\\"NP\\\");\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates gamma of perpetuals\\n     * Future: 0\\n     * Squeeth: 2 / 10000\\n     * @return calculated gamma scaled by 1e8\\n     */\\n    function calculateGamma(uint256 _productId) internal pure returns (int256) {\\n        if (_productId == 0) {\\n            return 0;\\n        } else if (_productId == 1) {\\n            return 2 * SCALING_FACTOR;\\n        } else {\\n            revert(\\\"NP\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x862c04bb7b0dafb54cdf5e6e0c91a89f0269b7ddb42b7993371c39884ae45097\",\"license\":\"agpl-3.0\"},\"src/lib/Math.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n/**\\n * Error codes\\n * M0: y is too small\\n * M1: y is too large\\n * M2: possible overflow\\n * M3: input should be positive number\\n * M4: cannot handle exponents greater than 100\\n */\\nlibrary Math {\\n    using SafeMath for uint256;\\n    using SignedSafeMath for int256;\\n\\n    /// @dev Min exp\\n    int256 private constant MIN_EXP = -63 * 1e8;\\n    /// @dev Max exp\\n    uint256 private constant MAX_EXP = 100 * 1e8;\\n    /// @dev ln(2) scaled by 1e8\\n    uint256 private constant LN_2_E8 = 69314718;\\n\\n    /**\\n     * @notice Return the addition of unsigned integer and sigined integer.\\n     * when y is negative reverting on negative result and when y is positive reverting on overflow.\\n     */\\n    function addDelta(uint256 x, int256 y) internal pure returns (uint256 z) {\\n        if (y < 0) {\\n            require((z = x - uint256(-y)) < x, \\\"M0\\\");\\n        } else {\\n            require((z = x + uint256(y)) >= x, \\\"M1\\\");\\n        }\\n    }\\n\\n    function abs(int256 x) internal pure returns (uint256) {\\n        return uint256(x >= 0 ? x : -x);\\n    }\\n\\n    function min(int256 a, int256 b) internal pure returns (int256) {\\n        return a > b ? b : a;\\n    }\\n\\n    function mulDiv(\\n        int256 _x,\\n        int256 _y,\\n        int256 _d,\\n        bool _roundUp\\n    ) internal pure returns (int256) {\\n        int256 tailing;\\n        if (_roundUp) {\\n            int256 remainer = (_x * _y) % _d;\\n            if (remainer > 0) {\\n                tailing = 1;\\n            } else if (remainer < 0) {\\n                tailing = -1;\\n            }\\n        }\\n\\n        int256 result = (_x * _y) / _d + tailing;\\n\\n        return result;\\n    }\\n\\n    /**\\n     * @notice Returns scaled number.\\n     * Reverts if the scaler is greater than 50.\\n     */\\n    function scale(\\n        uint256 _a,\\n        uint256 _from,\\n        uint256 _to\\n    ) internal pure returns (uint256) {\\n        if (_from > _to) {\\n            require(_from - _to < 70, \\\"M2\\\");\\n            // (_from - _to) is safe because _from > _to.\\n            // 10**(_from - _to) is safe because it's less than 10**70.\\n            return _a.div(10**(_from - _to));\\n        } else if (_from < _to) {\\n            require(_to - _from < 70, \\\"M2\\\");\\n            // (_to - _from) is safe because _to > _from.\\n            // 10**(_to - _from) is safe because it's less than 10**70.\\n            return _a.mul(10**(_to - _from));\\n        } else {\\n            return _a;\\n        }\\n    }\\n\\n    /**\\n     * @dev Calculates an approximate value of the logarithm of input value by Halley's method.\\n     */\\n    function log(uint256 x) internal pure returns (int256) {\\n        int256 res;\\n        int256 next;\\n\\n        for (uint256 i = 0; i < 8; i++) {\\n            int256 e = int256(exp(res));\\n            next = res.add((int256(x).sub(e).mul(2)).mul(1e8).div(int256(x).add(e)));\\n            if (next == res) {\\n                break;\\n            }\\n            res = next;\\n        }\\n\\n        return res;\\n    }\\n\\n    /**\\n     * @dev Returns the exponent of the value using Taylor expansion with support for negative numbers.\\n     */\\n    function exp(int256 x) internal pure returns (uint256) {\\n        if (0 <= x) {\\n            return exp(uint256(x));\\n        } else if (x < MIN_EXP) {\\n            // return 0 because `exp(-63) < 1e-27`\\n            return 0;\\n        } else {\\n            return uint256(1e8).mul(1e8).div(exp(uint256(-x)));\\n        }\\n    }\\n\\n    /**\\n     * @dev Calculates the exponent of the value using Taylor expansion.\\n     */\\n    function exp(uint256 x) internal pure returns (uint256) {\\n        if (x == 0) {\\n            return 1e8;\\n        }\\n        require(x <= MAX_EXP, \\\"M4\\\");\\n\\n        uint256 k = floor(x.mul(1e8).div(LN_2_E8)) / 1e8;\\n        uint256 p = 2**k;\\n        uint256 r = x.sub(k.mul(LN_2_E8));\\n\\n        uint256 multiplier = 1e8;\\n\\n        uint256 lastMultiplier;\\n        for (uint256 i = 16; i > 0; i--) {\\n            multiplier = multiplier.mul(r / i).div(1e8).add(1e8);\\n            if (multiplier == lastMultiplier) {\\n                break;\\n            }\\n            lastMultiplier = multiplier;\\n        }\\n\\n        return p.mul(multiplier);\\n    }\\n\\n    /**\\n     * @dev Returns the floor of a 1e8\\n     */\\n    function floor(uint256 x) internal pure returns (uint256) {\\n        return x - (x % 1e8);\\n    }\\n}\\n\",\"keccak256\":\"0xf737bf7a070dc7bb0b6f3179c81d70938421a3cc39ddec72a4ba9fc97b60ab7a\",\"license\":\"agpl-3.0\"},\"src/lib/NettingLib.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"./Math.sol\\\";\\n\\n/**\\n * @title NettingLib\\n *\\n * HedgePositionValue = ETH * S + AmountUSDC\\n *\\n * Normally, Amount Locked is equal to HedgePositionValue.\\n * AMM adjusts the HedgePositionValue to be equal to the RequiredMargin\\n * by adding or decreasing AmountUSDC.\\n *\\n *  --------------------------------------------------\\n * |              Total Liquidity Amount              |\\n * |     Amount Locked       |\\n * |    ETH     | AmountUSDC |\\n *  --------------------------------------------------\\n *\\n * If RequiredMargin becomes smaller than ETH value that AMM has, AmountUSDC becomes negative.\\n *\\n *  --------------------------------------------------\\n * |              Total Liquidity Amount              |\\n * |      Amount Locked(10)       |\\n * |            ETH(15)                          |\\n *                                |AmountUSDC(-5)|\\n *  --------------------------------------------------\\n *\\n * After hedge completed, AmountUSDC becomes positive.\\n *\\n *  --------------------------------------------------\\n * |              Total Liquidity Amount              |\\n * |      Amount Locked(10)       |\\n * |      ETH(6)    |\\n *                  |AmountUSDC(4)|\\n *  --------------------------------------------------\\n *\\n * Error codes\\n * N0: Unknown product id\\n * N1: Total delta must be greater than 0\\n * N2: No enough USDC\\n */\\nlibrary NettingLib {\\n    using SafeCast for int256;\\n    using SafeCast for uint128;\\n    using SafeCast for uint256;\\n    using SafeMath for uint256;\\n    using SafeMath for uint128;\\n    using SafeMath for int256;\\n    using SignedSafeMath for int256;\\n    using SignedSafeMath for int128;\\n\\n    struct AddMarginParams {\\n        int256 delta0;\\n        int256 delta1;\\n        int256 gamma1;\\n        int256 spotPrice;\\n        int256 poolMarginRiskParam;\\n    }\\n\\n    struct CompleteParams {\\n        uint256 amountUsdc;\\n        uint256 amountUnderlying;\\n        uint256 futureWeight;\\n        bool isLong;\\n    }\\n\\n    struct Info {\\n        int256[2] amountsUsdc;\\n        uint256 amountUnderlying;\\n    }\\n\\n    /**\\n     * @notice Adds required margin for delta hedging\\n     */\\n    function addMargin(\\n        Info storage _info,\\n        uint256 _productId,\\n        AddMarginParams memory _params\\n    ) internal returns (int256 requiredMargin, int256 hedgePositionValue) {\\n        int256 totalRequiredMargin = getRequiredMargin(_productId, _params);\\n\\n        hedgePositionValue = getHedgePositionValue(_info, _params, _productId);\\n\\n        requiredMargin = totalRequiredMargin.sub(hedgePositionValue);\\n\\n        _info.amountsUsdc[_productId] = _info.amountsUsdc[_productId].add(requiredMargin);\\n    }\\n\\n    function getRequiredTokenAmountsForHedge(\\n        uint256 _amountUnderlying,\\n        int256[2] memory _deltas,\\n        int256 _spotPrice\\n    ) internal pure returns (CompleteParams memory completeParams) {\\n        int256 totalUnderlyingPosition = _amountUnderlying.toInt256();\\n\\n        // 1. Calculate required amount of underlying token\\n        int256 requiredUnderlyingAmount;\\n        {\\n            // required amount is -(net delta)\\n            requiredUnderlyingAmount = -_deltas[0].add(_deltas[1]).add(totalUnderlyingPosition);\\n\\n            if (_deltas[0].add(_deltas[1]) > 0) {\\n                // if pool delta is positive\\n                requiredUnderlyingAmount = -totalUnderlyingPosition;\\n            }\\n\\n            completeParams.isLong = requiredUnderlyingAmount > 0;\\n        }\\n\\n        // 2. Calculate USDC and ETH amounts.\\n        completeParams.amountUnderlying = Math.abs(requiredUnderlyingAmount);\\n        completeParams.amountUsdc = (Math.abs(requiredUnderlyingAmount).mul(uint256(_spotPrice))) / 1e8;\\n\\n        completeParams.futureWeight = calculateWeight(0, _deltas[0], _deltas[1]);\\n\\n        return completeParams;\\n    }\\n\\n    /**\\n     * @notice Completes delta hedging procedure\\n     * Calculate holding amount of Underlying and USDC after a hedge.\\n     */\\n    function complete(Info storage _info, CompleteParams memory _params) internal {\\n        uint256 amountRequired0 = _params.amountUsdc.mul(_params.futureWeight).div(1e16);\\n        uint256 amountRequired1 = _params.amountUsdc.sub(amountRequired0);\\n\\n        require(_params.amountUnderlying > 0, \\\"N1\\\");\\n\\n        if (_params.isLong) {\\n            _info.amountUnderlying = _info.amountUnderlying.add(_params.amountUnderlying);\\n\\n            _info.amountsUsdc[0] = _info.amountsUsdc[0].sub(amountRequired0.toInt256());\\n            _info.amountsUsdc[1] = _info.amountsUsdc[1].sub(amountRequired1.toInt256());\\n        } else {\\n            _info.amountUnderlying = _info.amountUnderlying.sub(_params.amountUnderlying);\\n\\n            _info.amountsUsdc[0] = _info.amountsUsdc[0].add(amountRequired0.toInt256());\\n            _info.amountsUsdc[1] = _info.amountsUsdc[1].add(amountRequired1.toInt256());\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets required margin\\n     * @param _productId Id of product to get required margin\\n     * @param _params parameters to calculate required margin\\n     * @return RequiredMargin scaled by 1e8\\n     */\\n    function getRequiredMargin(uint256 _productId, AddMarginParams memory _params) internal pure returns (int256) {\\n        int256 weightedDelta = calculateWeightedDelta(_productId, _params.delta0, _params.delta1);\\n        int256 deltaFromGamma = 0;\\n\\n        if (_productId == 1) {\\n            deltaFromGamma = _params.poolMarginRiskParam.mul(_params.spotPrice).mul(_params.gamma1).div(1e12);\\n        }\\n\\n        int256 requiredMargin = (\\n            _params.spotPrice.mul(Math.abs(weightedDelta).add(Math.abs(deltaFromGamma)).toInt256())\\n        ).div(1e8);\\n\\n        return ((1e4 + _params.poolMarginRiskParam).mul(requiredMargin)).div(1e4);\\n    }\\n\\n    /**\\n     * @notice Gets notional value of hedge positions\\n     * HedgePositionValue_i = AmountsUsdc_i+(|delta_i| / (\\u03a3|delta_i|))*AmountUnderlying*S\\n     * @return HedgePositionValue scaled by 1e8\\n     */\\n    function getHedgePositionValue(\\n        Info memory _info,\\n        AddMarginParams memory _params,\\n        uint256 _productId\\n    ) internal pure returns (int256) {\\n        int256 totalHedgeNotional = _params.spotPrice.mul(_info.amountUnderlying.toInt256()).div(1e8);\\n\\n        int256 productHedgeNotional = totalHedgeNotional\\n            .mul(calculateWeight(0, _params.delta0, _params.delta1).toInt256())\\n            .div(1e16);\\n\\n        if (_productId == 1) {\\n            productHedgeNotional = totalHedgeNotional.sub(productHedgeNotional);\\n        }\\n\\n        int256 hedgePositionValue = _info.amountsUsdc[_productId].add(productHedgeNotional);\\n\\n        return hedgePositionValue;\\n    }\\n\\n    /**\\n     * @notice Gets notional value of hedge positions\\n     * HedgePositionValue_i = AmountsUsdc_0+AmountsUsdc_1+AmountUnderlying*S\\n     * @return HedgePositionValue scaled by 1e8\\n     */\\n    function getTotalHedgePositionValue(Info memory _info, int256 _spotPrice) internal pure returns (int256) {\\n        int256 hedgeNotional = _spotPrice.mul(_info.amountUnderlying.toInt256()).div(1e8);\\n\\n        return (_info.amountsUsdc[0].add(_info.amountsUsdc[1])).add(hedgeNotional);\\n    }\\n\\n    /**\\n     * @notice Calculates weighted delta\\n     * WeightedDelta = |delta_i| * (\\u03a3delta_i) / (\\u03a3|delta_i|)\\n     * @return weighted delta scaled by 1e8\\n     */\\n    function calculateWeightedDelta(\\n        uint256 _productId,\\n        int256 _delta0,\\n        int256 _delta1\\n    ) internal pure returns (int256) {\\n        int256 netDelta = _delta0.add(_delta1);\\n\\n        return netDelta.mul(calculateWeight(_productId, _delta0, _delta1).toInt256()).div(1e16);\\n    }\\n\\n    /**\\n     * @notice Calculates delta weighted value\\n     * WeightedDelta = |delta_i| / (\\u03a3|delta_i|)\\n     * @return weighted delta scaled by 1e16\\n     */\\n    function calculateWeight(\\n        uint256 _productId,\\n        int256 _delta0,\\n        int256 _delta1\\n    ) internal pure returns (uint256) {\\n        uint256 totalDelta = (Math.abs(_delta0).add(Math.abs(_delta1)));\\n\\n        require(totalDelta >= 0, \\\"N1\\\");\\n\\n        if (totalDelta == 0) {\\n            return 0;\\n        }\\n\\n        if (_productId == 0) {\\n            return (Math.abs(_delta0).mul(1e16)).div(totalDelta);\\n        } else if (_productId == 1) {\\n            return (Math.abs(_delta1).mul(1e16)).div(totalDelta);\\n        } else {\\n            revert(\\\"N0\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x70cdf7f78fd57b080557956bb3c7bcf7da407c8c35528d488e1714047d42cc53\",\"license\":\"agpl-3.0\"},\"src/lib/PoolMath.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"./Math.sol\\\";\\n\\n/**\\n * @notice AMM related math library\\n */\\nlibrary PoolMath {\\n    using SignedSafeMath for int256;\\n    using SafeCast for int256;\\n\\n    int256 private constant K = 3;\\n\\n    /**\\n     * @notice Calculate multiple integral of k*(m/L)+(1-k)(m/L)^3.\\n     * @param _m required margin\\n     * @param _deltaMargin difference of required margin\\n     * @param _l total amount of liquidity\\n     * @param _deltaL difference of liquidity\\n     * @return returns result of above formula\\n     */\\n    function calculateFundingRateFormula(\\n        int256 _m,\\n        int256 _deltaMargin,\\n        int256 _l,\\n        int256 _deltaL\\n    ) internal pure returns (int256) {\\n        require(_l > 0, \\\"l must be positive\\\");\\n\\n        return\\n            K\\n                .mul(calculateMarginDivLiquidity(_m, _deltaMargin, _l, _deltaL))\\n                .add((10 - K).mul(calculateMarginDivLiquidity3(_m, _deltaMargin, _l, _deltaL)))\\n                .div(10);\\n    }\\n\\n    /**\\n     * @notice Calculate multiple integral of (m/L)^3.\\n     * The formula is `(_m^3 + (3/2)*_m^2 * _deltaMargin + _m * _deltaMargin^2 + _deltaMargin^3 / 4) * (_l + _deltaL / 2) / (_l^2 * (_l + _deltaL)^2)`.\\n     * @param _m required margin\\n     * @param _deltaMargin difference of required margin\\n     * @param _l total amount of liquidity\\n     * @param _deltaL difference of liquidity\\n     * @return returns result of above formula\\n     */\\n    function calculateMarginDivLiquidity3(\\n        int256 _m,\\n        int256 _deltaMargin,\\n        int256 _l,\\n        int256 _deltaL\\n    ) internal pure returns (int256) {\\n        int256 result = 0;\\n\\n        result = (_m.mul(_m).mul(_m));\\n\\n        result = result.add(_m.mul(_m).mul(_deltaMargin).mul(3).div(2));\\n\\n        result = result.add(_m.mul(_deltaMargin).mul(_deltaMargin));\\n\\n        result = result.add(_deltaMargin.mul(_deltaMargin).mul(_deltaMargin).div(4));\\n\\n        result = result.mul(1e8).div(_l).div(_l);\\n\\n        return result.mul(_l.add(_deltaL.div(2))).mul(1e8).div(_l.add(_deltaL)).div(_l.add(_deltaL));\\n    }\\n\\n    /**\\n     * @notice calculate multiple integral of m/L\\n     * the formula is ((_m + _deltaMargin / 2) / _deltaL) * (log(_l + _deltaL) - log(_l))\\n     * @param _m required margin\\n     * @param _deltaMargin difference of required margin\\n     * @param _l total amount of liquidity\\n     * @param _deltaL difference of liquidity\\n     * @return returns result of above formula\\n     */\\n    function calculateMarginDivLiquidity(\\n        int256 _m,\\n        int256 _deltaMargin,\\n        int256 _l,\\n        int256 _deltaL\\n    ) internal pure returns (int256) {\\n        if (_deltaL == 0) {\\n            return (_m.add(_deltaMargin / 2).mul(1e16)).div(_l);\\n        } else {\\n            return\\n                (_m.add(_deltaMargin / 2)).mul(Math.log(_l.add(_deltaL).mul(1e8).div(_l).toUint256())).mul(1e8).div(\\n                    _deltaL\\n                );\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x861e72009d5b73fb38827608a21cc046986ff810881c9ffce537d370006d1eb7\",\"license\":\"agpl-3.0\"},\"src/lib/SpreadLib.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\n\\n/**\\n * @title SpreadLib\\n * @notice Spread Library has functions to controls spread for short-term volatility risk management\\n */\\nlibrary SpreadLib {\\n    using SafeCast for int256;\\n    using SafeCast for uint128;\\n    using SafeCast for uint256;\\n    using SafeMath for uint256;\\n    using SignedSafeMath for int128;\\n\\n    /// @dev block period for ETH - USD\\n    uint256 private constant SAFETY_BLOCK_PERIOD = 5;\\n\\n    /// @dev number of blocks per spread decreasing\\n    uint256 private constant NUM_BLOCKS_PER_SPREAD_DECREASING = 3;\\n\\n    struct Info {\\n        uint128 blockLastLongTransaction;\\n        int128 minLongTradePrice;\\n        uint128 blockLastShortTransaction;\\n        int128 maxShortTradePrice;\\n        uint256 safetyBlockPeriod;\\n        uint256 numBlocksPerSpreadDecreasing;\\n    }\\n\\n    function init(Info storage _info) internal {\\n        _info.minLongTradePrice = type(int128).max;\\n        _info.maxShortTradePrice = 0;\\n        _info.safetyBlockPeriod = SAFETY_BLOCK_PERIOD;\\n        _info.numBlocksPerSpreadDecreasing = NUM_BLOCKS_PER_SPREAD_DECREASING;\\n    }\\n\\n    function setParams(\\n        Info storage _info,\\n        uint256 _safetyBlockPeriod,\\n        uint256 _numBlocksPerSpreadDecreasing\\n    ) internal {\\n        _info.safetyBlockPeriod = _safetyBlockPeriod;\\n        _info.numBlocksPerSpreadDecreasing = _numBlocksPerSpreadDecreasing;\\n    }\\n\\n    /**\\n     * @notice Checks and updates price to guarantee that\\n     * max(bit) \\u2264 min(ask) from some point t to t-Safety Period.\\n     * @param _isLong trade is long or short\\n     * @param _price trade price\\n     * @return adjustedPrice adjusted price\\n     */\\n    function checkPrice(\\n        Info storage _info,\\n        bool _isLong,\\n        int256 _price,\\n        uint256 _blocknumber\\n    ) internal returns (int256 adjustedPrice) {\\n        Info memory cache = Info(\\n            _info.blockLastLongTransaction,\\n            _info.minLongTradePrice,\\n            _info.blockLastShortTransaction,\\n            _info.maxShortTradePrice,\\n            _info.safetyBlockPeriod,\\n            _info.numBlocksPerSpreadDecreasing\\n        );\\n        // MockArbSys mockArbSys = new MockArbSys();\\n        adjustedPrice = getUpdatedPrice(cache, _isLong, _price, _blocknumber);\\n\\n        _info.blockLastLongTransaction = cache.blockLastLongTransaction;\\n        _info.minLongTradePrice = cache.minLongTradePrice;\\n        _info.blockLastShortTransaction = cache.blockLastShortTransaction;\\n        _info.maxShortTradePrice = cache.maxShortTradePrice;\\n    }\\n\\n    function getUpdatedPrice(\\n        Info memory _info,\\n        bool _isLong,\\n        int256 _price,\\n        uint256 _blocknumber\\n    ) internal pure returns (int256 adjustedPrice) {\\n        adjustedPrice = _price;\\n\\n        if (_info.safetyBlockPeriod == 0) {\\n            return _price;\\n        }\\n\\n        if (_isLong) {\\n            // if long\\n            if (_info.blockLastShortTransaction >= _blocknumber - _info.safetyBlockPeriod) {\\n                // Within safety period\\n                if (adjustedPrice < _info.maxShortTradePrice) {\\n                    int256 spreadClosing = ((_blocknumber - _info.blockLastShortTransaction) /\\n                        _info.numBlocksPerSpreadDecreasing).toInt256();\\n                    if (adjustedPrice <= (_info.maxShortTradePrice.mul(1e4 - spreadClosing)) / 1e4) {\\n                        _info.maxShortTradePrice = ((_info.maxShortTradePrice.mul(1e4 - spreadClosing)) / 1e4)\\n                            .toInt128();\\n                    }\\n                    adjustedPrice = _info.maxShortTradePrice;\\n                }\\n            }\\n\\n            // Update min ask\\n            if (\\n                _info.minLongTradePrice > adjustedPrice ||\\n                _info.blockLastLongTransaction + _info.safetyBlockPeriod < _blocknumber\\n            ) {\\n                _info.minLongTradePrice = adjustedPrice.toInt128();\\n            }\\n            _info.blockLastLongTransaction = uint128(_blocknumber);\\n        } else {\\n            // if short\\n            if (_info.blockLastLongTransaction >= _blocknumber - _info.safetyBlockPeriod) {\\n                // Within safety period\\n                if (adjustedPrice > _info.minLongTradePrice) {\\n                    int256 spreadClosing = ((_blocknumber - _info.blockLastLongTransaction) /\\n                        _info.numBlocksPerSpreadDecreasing).toInt256();\\n                    if (adjustedPrice >= (_info.minLongTradePrice.mul(1e4 + spreadClosing)) / 1e4) {\\n                        _info.minLongTradePrice = ((_info.minLongTradePrice.mul(1e4 + spreadClosing)) / 1e4).toInt128();\\n                    }\\n                    adjustedPrice = _info.minLongTradePrice;\\n                }\\n            }\\n\\n            // Update max bit\\n            if (\\n                _info.maxShortTradePrice < adjustedPrice ||\\n                _info.blockLastShortTransaction + _info.safetyBlockPeriod < _blocknumber\\n            ) {\\n                _info.maxShortTradePrice = adjustedPrice.toInt128();\\n            }\\n            _info.blockLastShortTransaction = uint128(_blocknumber);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x1b8a4b4e611c26753432415a7dcd9abcecd6f99492aa733e7fbce415efbc240c\",\"license\":\"agpl-3.0\"}},\"version\":1}",
  "bytecode": "0x60806040523480156200001157600080fd5b50604051620053343803806200533483398101604081905262000034916200038c565b8282600062000042620001d9565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508151620000a190600490602085019062000228565b508051620000b790600590602084019062000228565b50506006805460ff1916601217905550620000d36008620001dd565b601b80546001600160a01b038087166001600160a01b031992831617909255601c805492841692909116919091179055600080526011602090815262000144907f4ad3b33220dddc71b994a52d72c06b10862965f7d926534c05c00fb7e819e7b79062001b3b620001f3821b17901c565b60016000526011602090815262000186907f17bc176d2408558f6e4111feebc3cab4e16b63e967be91cde721f4c8a488b5529062001b3b620001f3821b17901c565b6200019d6012620001f360201b62001b3b1760201c565b50506320c85580600755505062035b6060085560286009556050600a55622625a0600b55610fa0600c5561c350600d55612710600e5562000419565b3390565b6006805460ff191660ff92909216919091179055565b8054600160801b600160ff1b036001600160801b03918216178255600182018054909116905560056002820155600390810155565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620002605760008555620002ab565b82601f106200027b57805160ff1916838001178555620002ab565b82800160010185558215620002ab579182015b82811115620002ab5782518255916020019190600101906200028e565b50620002b9929150620002bd565b5090565b5b80821115620002b95760008155600101620002be565b80516001600160a01b0381168114620002ec57600080fd5b919050565b600082601f83011262000302578081fd5b81516001600160401b03808211156200031757fe5b6040516020601f8401601f19168201810183811183821017156200033757fe5b60405283825285840181018710156200034e578485fd5b8492505b8383101562000371578583018101518284018201529182019162000352565b838311156200038257848185840101525b5095945050505050565b60008060008060808587031215620003a2578384fd5b620003ad85620002d4565b60208601519094506001600160401b0380821115620003ca578485fd5b620003d888838901620002f1565b94506040870151915080821115620003ee578384fd5b50620003fd87828801620002f1565b9250506200040e60608601620002d4565b905092959194509250565b614f0b80620004296000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80637d7c2a1c1161013b578063ac4afa38116100b8578063dd62ed3e1161007c578063dd62ed3e146104f5578063e7dc45d314610508578063f2fde38b1461051b578063f3fef3a31461052e578063f844f2a61461054157610248565b8063ac4afa3814610485578063b02582dc146104a9578063b206ab84146104bc578063bfe51951146104cf578063d0209f96146104e257610248565b806389633081116100ff578063896330811461043a5780638da5cb5b1461044257806395d89b4114610457578063a457c2d71461045f578063a9059cbb1461047257610248565b80637d7c2a1c146103f55780637d8c2659146103fd5780637fc3846714610405578063854ad1b71461041d57806387c3a09a1461043257610248565b806333a37ffb116101c9578063545ed65a1161018d578063545ed65a146103ac5780635cda497d146103b457806370a08231146103c7578063715018a6146103da57806373f3489e146103e257610248565b806333a37ffb1461033a578063395093511461035e5780633d33bcd51461037157806347e7ef241461038657806351c6590a1461039957610248565b80631c2f4e97116102105780631c2f4e97146102c857806323a216c1146102e857806323b872dd146102f05780632e06396414610303578063313ce5671461032557610248565b806306fdde031461024d578063095ea7b31461026b578063128c113f1461028b57806318160ddd146102a0578063192679ed146102b5575b600080fd5b610255610554565b6040516102629190614a34565b60405180910390f35b61027e61027936600461475b565b6105ea565b60405161026291906149a5565b61029e61029936600461480a565b610608565b005b6102a861065c565b60405161026291906149fa565b61029e6102c33660046147d1565b610662565b6102db6102d63660046147b6565b610721565b6040516102629190614b6d565b6102a861081d565b61027e6102fe366004614720565b61087b565b6103166103113660046147b6565b610903565b6040516102629392919061495f565b61032d610afa565b6040516102629190614c00565b61034d61034836600461488b565b610b03565b604051610262959493929190614a11565b61027e61036c36600461475b565b610b38565b610379610b86565b6040516102629190614b4a565b6102a861039436600461475b565b610bd6565b61029e6103a73660046147d1565b610d00565b6102a8610d3d565b61029e6103c23660046148ae565b610d43565b6102a86103d53660046146d4565b610e21565b61029e610e3c565b6102a86103f03660046147d1565b610ee8565b61029e610ff8565b61029e6110e2565b61040d611137565b60405161026294939291906149b0565b610425611161565b6040516102629190614b1d565b61029e611247565b6102a86112aa565b61044a6112b0565b604051610262919061494b565b6102556112bf565b61027e61046d36600461475b565b611320565b61027e61048036600461475b565b611388565b6104986104933660046147d1565b61139c565b604051610262959493929190614bb7565b61029e6104b73660046147d1565b6113dd565b61029e6104ca3660046147e9565b611492565b61029e6104dd3660046147d1565b611577565b61029e6104f03660046147e9565b61161c565b6102a86105033660046146ee565b611774565b6102a8610516366004614784565b61179f565b61029e6105293660046146d4565b611894565b6102a861053c36600461475b565b611996565b61029e61054f3660046146d4565b611a8d565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156105e05780601f106105b5576101008083540402835291602001916105e0565b820191906000526020600020905b8154815290600101906020018083116105c357829003601f168201915b5050505050905090565b60006105fe6105f7611b79565b8484611b7d565b5060015b92915050565b601e546001600160a01b0316331461063b5760405162461bcd60e51b815260040161063290614ac3565b60405180910390fd5b6000610645611c69565b50601d8190559050610658601883611d25565b5050565b60035490565b61066a611b79565b6001600160a01b031661067b6112b0565b6001600160a01b0316146106c4576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b600081121580156106d85750620f42408113155b6106e157600080fd5b60088190556040517f0e5502f89db0c53034cbc3f53df6d411d72c6c9b9e711b952d4cc6a30d8ac73d906107169083906149fa565b60405180910390a150565b61072961458a565b6000610733611c69565b50905061073e6145cc565b6107466145cc565b61074e6145cc565b60005b60028110156107ec57600061076982878a6000611e4b565b90505087856002811061077857fe5b6020020187866002811061078857fe5b602002019190915291909152905060006107a183611fd7565b905060006107b18484844261200f565b6000858152601060205260409020600201549091506107d09082612066565b8585600281106107dc57fe5b6020020152505050600101610751565b50604080516080810182526001600160801b039095168552602085019390935291830152606082015290505b919050565b60008060005b60028110156108595760008181526010602052604090205461084f9083906001600160801b03166120cb565b9150600101610823565b50600f546108759061086f836305f5e100612125565b9061217e565b91505090565b60006108888484846121e5565b6108f884610894611b79565b6108f385604051806060016040528060288152602001614d8c602891396001600160a01b038a166000908152600260205260408120906108d2611b79565b6001600160a01b031681526020810191909152604001600020549190612342565b611b7d565b5060015b9392505050565b61090b6145cc565b6109136145cc565b601e546000906001600160a01b031633146109405760405162461bcd60e51b815260040161063290614ac3565b6000600f54116109625760405162461bcd60e51b815260040161063290614aa5565b835160008080526010602052600080516020614d2a8339815191525490916109a29161099d91600160801b909104600f90810b900b906123d9565b61243e565b600080805260106020908152600080516020614d2a83398151915280546001600160801b03908116600160801b600f96870b92909216820217909155908801516001909252600080516020614c3283398151915254610a0d9361099d9392909104810b900b906123d9565b60016000526010602052600080516020614c328339815191528054600f9290920b6001600160801b03908116600160801b029216919091179055845115610a8857600080610a628188815b60200201516124a3565b9188529188529092509050610a7784836120cb565b9350610a838382612066565b925050505b602085015115610ad157600080610aa160018881610a58565b602089810193909352918901929092529092509050610ac084836120cb565b9350610acc8382612066565b925050505b610aef600f54610aea610ae385612561565b84906123d9565b6125a5565b600f55509193909250565b60065460ff1690565b600080600080600080610b14611c69565b509050610b248882896000611e4b565b939c929b5090995097509095509350505050565b60006105fe610b45611b79565b846108f38560026000610b56611b79565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906120cb565b610b8e6145ea565b604080516080810180835290916018918391820190839060029082845b815481526020019060010190808311610bab5750505050508152602001600282015481525050905090565b601e546000906001600160a01b03163314610c035760405162461bcd60e51b815260040161063290614ac3565b6000610c0d61065c565b11610c1757600080fd5b6000610c256103f084612561565b9050610cc5610cc0600183601c60009054906101000a90046001600160a01b03166001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7e57600080fd5b505afa158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614873565b6012929190612633565b61270c565b9050610cdc8161086f85662386f26fc10000612125565b600f54909250610cec90846120cb565b600f55610cf98483612763565b5092915050565b601e546001600160a01b03163314610d2a5760405162461bcd60e51b815260040161063290614ac3565b600f54610d3790826120cb565b600f5550565b601d5481565b610d4b611b79565b6001600160a01b0316610d5c6112b0565b6001600160a01b031614610da5576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b8183108015610db5575060c88211155b610dd15760405162461bcd60e51b815260040161063290614ae1565b6009839055600a829055600b8190556040517f40eadc083dad26c82ca6e52052119f861019dc8b168294cc37f793801b6494a090610e1490859085908590614bea565b60405180910390a1505050565b6001600160a01b031660009081526001602052604090205490565b610e44611b79565b6001600160a01b0316610e556112b0565b6001600160a01b031614610e9e576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600080610ef3611c69565b5090506000610f19610f0760018487612855565b610f1360008588612855565b90612066565b6040805160808101808352929350600092610f7692869291601891839190820190839060029082845b815481526020019060010190808311610f42575050505050815260200160028201548152505061293d90919063ffffffff16565b9050610fef610f8361065c565b6010602052600080516020614c328339815191525460008052600080516020614d2a83398151915254600f5461086f92662386f26fc1000092610fe9926001600160801b0392831692610fe392169082908b90610f13908c908290612561565b9061298a565b90612125565b95945050505050565b601e546001600160a01b031633146110225760405162461bcd60e51b815260040161063290614ac3565b600061102c611c69565b50905060005b600281101561065857600080600061104a84866129e7565b909350905061105c8484836002612ae0565b9094509250508115905061107a57611076600f54826125a5565b600f555b81156110d8576000838152601060205260409020546110ab906110a6906001600160801b0316846125a5565b612c26565b600084815260106020526040902080546001600160801b0319166001600160801b03929092169190911790555b5050600101611032565b601e546001600160a01b0316331461110c5760405162461bcd60e51b815260040161063290614ac3565b6000611116611c69565b50905060005b60028110156106585761112f8183612c6a565b60010161111c565b601654601754600f82810b92600160801b90819004820b929182900b91046001600160801b031684565b61116961460a565b6000611173611c69565b506010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152549293509182916111ca918591600160801b90819004600f90810b810b9291909104810b900b612daf565b915091506111d66145cc565b82815260208101829052601a546111ee908286612dfe565b945060006111fb85612ea4565b90508560600151156112295761122261271061086f61121a82856120cb565b895190612125565b865261123f565b61123c61271061086f61121a828561298a565b86525b505050505090565b601e546001600160a01b031633146112715760405162461bcd60e51b815260040161063290614ac3565b60175461a8c06001600160801b03600160801b90920482160116421015611297576112a8565b6112a042612f27565b6112a86130ac565b565b600f5481565b6000546001600160a01b031690565b60058054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156105e05780601f106105b5576101008083540402835291602001916105e0565b60006105fe61132d611b79565b846108f385604051806060016040528060258152602001614eb16025913960026000611357611b79565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612342565b60006105fe611395611b79565b84846121e5565b60106020526000908152604090208054600182015460028301546003909301546001600160801b0380841694600160801b909404600f0b9392811692911685565b6113e5611b79565b6001600160a01b03166113f66112b0565b6001600160a01b03161461143f576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b60008112158015611454575063773594008113155b61145d57600080fd5b60078190556040517ffd74ba77488a6a7a45711e7c3469f918238eb90178880837da4a029a93ccf375906107169083906149fa565b61149a611b79565b6001600160a01b03166114ab6112b0565b6001600160a01b0316146114f4576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b806000131580156115085750620493e08213155b801561151357508181125b61152f5760405162461bcd60e51b815260040161063290614ae1565b600d829055600e8190556040517fbacb10fce6db592e49a2f13ebfa4af23c68a1ddc3962bc0818478a518f3fa95f9061156b9084908490614a03565b60405180910390a15050565b61157f611b79565b6001600160a01b03166115906112b0565b6001600160a01b0316146115d9576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b60008112156115e757600080fd5b600c8190556040517f8e6edd6f6b5a50f0d6a8f356374101e297ba1ac391a14aaa3248ba40d7665e73906107169083906149fa565b611624611b79565b6001600160a01b03166116356112b0565b6001600160a01b03161461167e576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b6102588211156116a05760405162461bcd60e51b815260040161063290614ae1565b8060001080156116b257506102588111155b6116ce5760405162461bcd60e51b815260040161063290614ae1565b6000805260116020526117027f4ad3b33220dddc71b994a52d72c06b10862965f7d926534c05c00fb7e819e7b783836130be565b600160005260116020526117377f17bc176d2408558f6e4111feebc3cab4e16b63e967be91cde721f4c8a488b55283836130be565b611743601283836130be565b7ff2450f3986de0a389b21b7df0371586ea26c539d4a18d0b39542308db22a48c2828260405161156b929190614a03565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b601e546000906001600160a01b031633146117cc5760405162461bcd60e51b815260040161063290614ac3565b6117d461065c565b156117de57600080fd5b508160006117ea611c69565b5090506117f68361243e565b60168054600f9290920b6001600160801b03908116600160801b0292169190911790556118228161243e565b60178054600f9290920b6001600160801b03166001600160801b031990921691909117905561185042612c26565b601780546001600160801b03928316600160801b029216919091179055601d819055600f5461187f90856120cb565b600f5561188c8583612763565b509392505050565b61189c611b79565b6001600160a01b03166118ad6112b0565b6001600160a01b0316146118f6576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b6001600160a01b03811661193b5760405162461bcd60e51b8152600401808060200182810382526026815260200180614c746026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b601e546000906001600160a01b031633146119c35760405162461bcd60e51b815260040161063290614ac3565b816119cc6130ce565b10156119ea5760405162461bcd60e51b815260040161063290614aff565b6000611a006119f884612561565b600003610ee8565b9050611a59610cc0600083601c60009054906101000a90046001600160a01b03166001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7e57600080fd5b9050611a708161086f85662386f26fc10000612125565b600f54909250611a80908461298a565b600f55610cf9848361314d565b611a95611b79565b6001600160a01b0316611aa66112b0565b6001600160a01b031614611aef576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b601e546001600160a01b0316158015611b1057506001600160a01b03811615155b611b1957600080fd5b601e80546001600160a01b0319166001600160a01b0392909216919091179055565b80546f7fffffffffffffffffffffffffffffff60801b6001600160801b03918216178255600182018054909116905560056002820155600390810155565b3390565b6001600160a01b038316611bc25760405162461bcd60e51b8152600401808060200182810382526024815260200180614e416024913960400191505060405180910390fd5b6001600160a01b038216611c075760405162461bcd60e51b8152600401808060200182810382526022815260200180614c9a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600080600080601b60009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015611cbd57600080fd5b505afa158015611cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf591906148d9565b5093505092505060008213611d1c5760405162461bcd60e51b815260040161063290614a87565b90925090509091565b6000611d4d662386f26fc1000061086f8460400151856000015161212590919063ffffffff16565b8251909150600090611d5f908361298a565b90506000836020015111611d9f576040805162461bcd60e51b81526020600482015260026024820152614e3160f01b604482015290519081900360640190fd5b826060015115611df95760208301516002850154611dbc916120cb565b6002850155611dd9611dcd83612561565b8560005b0154906123d9565b8455611def611de782612561565b856001611dd1565b8460010155611e45565b60208301516002850154611e0c9161298a565b6002850155611e29611e1d83612561565b8560005b015490612066565b8455611e3f611e3782612561565b856001611e21565b84600101555b50505050565b600080600080600080878a60028110611e6057fe5b602002015115611ea7576000806000611e7a8d8d8d613249565b9250925092506000611e8e8e858585612ae0565b919650909150611ea090508b82612066565b9a50505050505b60008a815260106020526040812054611ece90600160801b9004600f90810b900b8c6133d0565b9050611efc8b8b60008c8f60028110611ee357fe5b60200201511384611ef5600f54612561565b878e61343b565b939a50919850909550909350611f2f90508b611f188385612066565b611f278b610f13600f54612561565b6000806134d4565b945050611fc96000898c60028110611f4357fe5b6020908102919091015160008e815260118352604090819020815160c08101835281546001600160801b038082168352600160801b91829004600f90810b810b810b97840197909752600184015490811694830194909452909204840b840b90930b60608201526002830154608082015260039092015460a083015290911288426135b3565b955050945094509450945094565b60008181526010602052604081205461060290839061200490600160801b9004600f90810b900b826133d0565b611f27600f54612561565b60006120296305f5e10061202386866137e8565b90613891565b600086815260106020526040902060030154909150610fef9062015180906120239061205f9086906001600160801b031661298a565b84906137e8565b600082820181831280159061207b5750838112155b80612090575060008312801561209057508381125b6108fc5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d096021913960400191505060405180910390fd5b6000828201838110156108fc576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008261213457506000610602565b8282028284828161214157fe5b04146108fc5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d6b6021913960400191505060405180910390fd5b60008082116121d4576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816121dd57fe5b049392505050565b6001600160a01b03831661222a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e1c6025913960400191505060405180910390fd5b6001600160a01b03821661226f5760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0f6023913960400191505060405180910390fd5b61227a838383613949565b6122b781604051806060016040528060268152602001614cbc602691396001600160a01b0386166000908152600160205260409020549190612342565b6001600160a01b0380851660009081526001602052604080822093909355908416815220546122e690826120cb565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156123d15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561239657818101518382015260200161237e565b50505050905090810190601f1680156123c35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183038183128015906123ee5750838113155b80612403575060008312801561240357508381135b6108fc5760405162461bcd60e51b8152600401808060200182810382526024815260200180614e8d6024913960400191505060405180910390fd5b60006f7fffffffffffffffffffffffffffffff19821215801561246457506001607f1b82125b61249f5760405162461bcd60e51b8152600401808060200182810382526027815260200180614ce26027913960400191505060405180910390fd5b5090565b60008060008060006124b3611c69565b5090506124c187828861394e565b6000898152601060205260408120600181015490549398509195509161250d916001600160801b03169061250390600160801b9004600f90810b900b8a612066565b888a600003613a91565b9350905061251d6110a68261270c565b60008981526010602052604090206001810180546001600160801b03939093166001600160801b031990931692909217909155600201549450505092959194509250565b6000600160ff1b821061249f5760405162461bcd60e51b8152600401808060200182810382526028815260200180614e656028913960400191505060405180910390fd5b6000808212156125f55782826000038403915081106125f0576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b610602565b5080820182811015610602576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b6040805160c08101825285546001600160801b038082168352600160801b91829004600f90810b810b602085015260018901549182169484019490945204820b90910b606082015260028501546080820152600385015460a082015260009061269e818686866135b3565b815187546020840151600f90810b6001600160801b03908116600160801b9081029482166001600160801b0319948516178216949094178b5560408601516001909b01805460609097015190920b811690930299831694909116939093171696909617905550929392505050565b60008082121561249f576040805162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f736974697665604482015290519081900360640190fd5b6001600160a01b0382166127be576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6127ca60008383613949565b6003546127d790826120cb565b6003556001600160a01b0382166000908152600160205260409020546127fd90826120cb565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000806128606145cc565b600080516020614d2a83398151915254600160801b90819004600f90810b810b8352600080516020614c3283398151915254829004810b810b60208481019190915260008981526010909152604090205491909104810b900b156129345760006128cc87878488611e4b565b5050506000898152601060205260409020600101549192506305f5e10091612928915061290590610ae3906001600160801b0316612561565b60008a815260106020526040902054600160801b9004600f90810b900b906137e8565b8161292f57fe5b059250505b50949350505050565b60008061295f6305f5e1006120236129588760200151612561565b86906137e8565b84516020810151919250612982918391610f13919060005b602002015190612066565b949350505050565b6000828211156129e1576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152549091829182918291612a3e918791600160801b91829004600f90810b810b92909104810b900b612daf565b600160008181526010602052600080516020614c328339815191525493955091935090916305f5e10091612a8a91600160801b9004600f90810b900b90612a8490613bb7565b906137e8565b81612a9157fe5b059050612ad2876040518060a00160405280868152602001858152602001848152602001898152602001600c548152506018613c0a9092919063ffffffff16565b909890975095505050505050565b600080600080861315612bc45760008512612b245785612afe6130ce565b1015612b1c5760405162461bcd60e51b815260040161063290614aa5565b859150612bbf565b600087815260106020526040902054612b5090612b49906001600160801b0316612561565b86906123d9565b600088815260106020526040902054612b71906001600160801b0316612561565b60000392509050612b828686612066565b612b8a6130ce565b1015612ba85760405162461bcd60e51b815260040161063290614aa5565b612bbc612bb58787612066565b8390612066565b91505b612bf5565b6000861215612bf557600087815260106020526040902054612bf0906001600160801b03168787613ca0565b925090505b600087815260106020526040902054612c1a90859084906001600160801b0316613cd0565b92509450945094915050565b6000600160801b821061249f5760405162461bcd60e51b8152600401808060200182810382526027815260200180614ce26027913960400191505060405180910390fd5b6000828152601060205260409020600301546001600160801b0316612cb857600082815260106020526040902060030180546001600160801b031916426001600160801b0316179055610658565b6000828152601060205260409020600301546001600160801b03164211612cde57610658565b6000806000612cee858542613d4f565b6000888152601060205260409020600201549295509093509150612d129083612066565b6000868152601060205260409020600201558015612d3a57612d36600f54826125a5565b600f555b600085815260106020526040908190206003810180546001600160801b031916426001600160801b03161790556002015490517f3e5170eaa3b2dec8bb1a3e32834aed10d5bbdb77abda3b065447543099eaebfa91612da0918891879187908790614a11565b60405180910390a15050505050565b60008060006305f5e100612dc886612a8460008a613dc0565b81612dcf57fe5b05905060006305f5e100612de886612a8460018b613dc0565b81612def57fe5b92989205965090945050505050565b612e0661460a565b6000612e1185612561565b90506000612e2c82610f138760016020020151886000612977565b602086015160009182039250612e43908783612977565b1315612e50578160000390505b600081136060840152612e6281613df8565b60208401526305f5e100612e7985610fe984613df8565b81612e8057fe5b04835284516020860151612e9691600091613e0b565b604084015250509392505050565b600080612ed2612ecd601d546120236305f5e100612a84601d54896123d990919063ffffffff16565b613df8565b9050612eff612ef6600b5461086f84600954600a540361212590919063ffffffff16565b600954906120cb565b9150600954821015612f115760095491505b600a54821115612f2157600a5491505b50919050565b6000612f31611c69565b50601754909150600090612f5890600f90810b900b6120236305f5e100612a8486846123d9565b90506000612f6e6305f5e10061202384806137e8565b601754909150612fa090612f9390600160801b90046001600160801b03168603612561565b61202383620151806137e8565b9050612fe76305f5e100612fda612fba625b8d80856137e8565b601654610f139063059a538090600160801b9004600f90810b900b6137e8565b81612fe157fe5b0561243e565b60168054600f9290920b6001600160801b03908116600160801b0292169190911790556130138361243e565b60178054600f9290920b6001600160801b03166001600160801b031990921691909117905561304184612c26565b601780546001600160801b03908116600160801b93909116830217908190556016546040517fc0286f283c0343297f024da33b37cbae636c6f78d8b29803dd94a72c09d44b1a9361309e939204600f90810b92900b9088906149dc565b60405180910390a150505050565b601680546001600160801b0319169055565b6002830191909155600390910155565b60008060005b600281101561313f576000818152601060205260409020546131009083906001600160801b03166120cb565b915060006018826002811061311157fe5b0154121561313757613134826018836002811061312a57fe5b01546000036125a5565b91505b6001016130d4565b50600f54610875908261298a565b6001600160a01b0382166131925760405162461bcd60e51b8152600401808060200182810382526021815260200180614dfb6021913960400191505060405180910390fd5b61319e82600083613949565b6131db81604051806060016040528060228152602001614c52602291396001600160a01b0385166000908152600160205260409020549190612342565b6001600160a01b038316600090815260016020526040902055600354613201908261298a565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152548351919283928392839283928392600160801b92839004600f90810b810b93909104810b900b906132a79083906123d9565b91506132bb896001602002015182906123d9565b90508a6132d7576132d4828a60005b6020020151613eb2565b95505b8a600114156132ef576132ec818a60016132ca565b95505b6132fa8a8383612daf565b90955093506305f5e10061331282612a846001613bb7565b8161331957fe5b059250505060006040518060a001604052808581526020018481526020018381526020018a8152602001600c54815250905060006133578b83613f2a565b60408051608081018083529293506133b49285928f9291601891839190820190839060029082845b81548152602001906001019080831161337f5750505050508152602001600282015481525050613fd99092919063ffffffff16565b96506133c081886123d9565b9750505050505093509350939050565b6000826133df57506000610602565b600083131561341357600082815260106020526040902054613409906001600160801b0316612561565b6000039050610602565b600082815260106020526040902054613434906001600160801b0316612561565b9050610602565b6000806000806000806134518d8b8b8b8b6134d4565b905061345d8d8d614068565b94506000613480662386f26fc100006120236134798286612066565b89906137e8565b905061348d8e8d8861408f565b93506134998185612066565b90506134a58e876140fe565b92508086836134bb6134b688613df8565b612561565b9650965096509650505097509750975097509792505050565b60008561351c5760006134fd6305f5e1006120236134f489888a8961413c565b600854906137e8565b60165490915061351490600f90810b900b82612066565b915050610fef565b85600114156135a757836135505760165461354990600160801b9004600f90810b900b6305f5e1006137e8565b9050610fef565b60006135726305f5e10061202361356989888a8961413c565b600754906137e8565b90506135146305f5e100612023613590662386f26fc1000085612066565b601654600160801b9004600f90810b900b906137e8565b50600095945050505050565b608084015182906135c5575081612982565b83156136d8578460800151820385604001516001600160801b031610613688578460600151600f0b81121561368857600061361b8660a0015187604001516001600160801b031685038161361557fe5b04612561565b905061271061363e82612710038860600151600f0b6137e890919063ffffffff16565b8161364557fe5b05821361367d57613670612710612fda83612710038960600151600f0b6137e890919063ffffffff16565b600f90810b900b60608701525b50506060840151600f0b5b808560200151600f0b13806136ac5750608085015185516001600160801b03160182115b156136c7576136ba8161243e565b600f90810b900b60208601525b6001600160801b0382168552612982565b8460800151820385600001516001600160801b03161061378f578460200151600f0b81131561378f5760006137228660a0015187600001516001600160801b031685038161361557fe5b905061271061374582612710018860200151600f0b6137e890919063ffffffff16565b8161374c57fe5b05821261378457613777612710612fda83612710018960200151600f0b6137e890919063ffffffff16565b600f90810b900b60208701525b50506020840151600f0b5b808560600151600f0b12806137b6575081856080015186604001516001600160801b031601105b156137d1576137c48161243e565b600f90810b900b60608601525b6001600160801b0382166040860152949350505050565b6000826137f757506000610602565b8260001914801561380b5750600160ff1b82145b156138475760405162461bcd60e51b8152600401808060200182810382526027815260200180614dd46027913960400191505060405180910390fd5b8282028284828161385457fe5b05146108fc5760405162461bcd60e51b8152600401808060200182810382526027815260200180614dd46027913960400191505060405180910390fd5b6000816138e5576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b816000191480156138f95750600160ff1b83145b156139355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d4a6021913960400191505060405180910390fd5b600082848161394057fe5b05949350505050565b505050565b60008060008060008061396189896129e7565b60008b815260106020526040902054919550915061399c908a908690849061399790600160801b9004600f90810b900b8c613eb2565b612ae0565b60008c81526010602052604081205492975092955093509091506139d8906139d290600160801b9004600f90810b900b89612066565b8a6133d0565b90506000806139eb8b8b8b8689896141bd565b9150915083600014613a0757613a03600f54856125a5565b600f555b60008b815260106020526040902054613a2d906110a6906001600160801b0316886125a5565b60008c815260106020526040902080546001600160801b0319166001600160801b0392909216919091179055613a628261270c565b613a7f6305f5e10061086f613a768d613df8565b610fe98661270c565b97509750505050505050935093915050565b60008080613a9f8685612066565b9050851580613ab95750600086138015613ab95750600084135b80613acf5750600086128015613acf5750600084125b15613b0d57613b06613ae4612ecd8887612066565b612023613af361347988613df8565b610f13613aff8b613df8565b8c906137e8565b9250613bad565b600086138015613b1d5750600084125b8015613b295750600081135b80613b4b5750600086128015613b3f5750600084135b8015613b4b5750600081125b15613b7f578692506305f5e100613b70613b6587866123d9565b6000879003906137e8565b81613b7757fe5b059150613bad565b8015613b89578492505b6305f5e100613ba2613b9b878a6123d9565b88906137e8565b81613ba957fe5b0591505b5094509492505050565b600081613bc657506000610818565b8160011415613bd85750614e20610818565b6040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b6000806000613c198585613f2a565b6040805160808101808352929350613c6992909189918391820190839060029082845b815481526020019060010190808311613c3c57505050505081526020016002820154815250508587613fd9565b9150613c7581836123d9565b9250613c8783878760028110611e2157fe5b868660028110613c9357fe5b0155509094909350915050565b600080613cba83612023613cb388612561565b87906137e8565b9050613cc681856123d9565b9150935093915050565b60006003846003811115613ce057fe5b1415613cfc57613cf583610f138460026137e8565b90506108fc565b6001846003811115613d0a57fe5b1415613d2957613d1f83610f138460026137e8565b60000390506108fc565b6002846003811115613d3757fe5b1415613d48578260000390506108fc565b50816108fc565b600080600080613d5f8787614068565b9050613d6a87611fd7565b9350613d788782868861200f565b600088815260106020526040812054919450613db491662386f26fc1000091612023918791600160801b909104600f90810b909103900b6137e8565b91505093509350939050565b600082613dd257506305f5e100610602565b8260011415613bd857612710613de98360026137e8565b81613df057fe5b059050610602565b60008082121561249f5781600003610602565b600080613e29613e1a84613df8565b613e2386613df8565b906120cb565b905080613e3a5760009150506108fc565b84613e5f57613e578161086f662386f26fc10000610fe988613df8565b9150506108fc565b8460011415613e8057613e578161086f662386f26fc10000610fe987613df8565b6040805162461bcd60e51b815260206004820152600260248201526104e360f41b604482015290519081900360640190fd5b600080613ebf8484612066565b9050600081138015613ed15750600084125b15613ee0576003915050610602565b600081128015613ef05750600084135b15613eff576001915050610602565b60008112158015613f11575060008412155b15613f20576002915050610602565b6000915050610602565b600080613f408484600001518560200151614290565b905060008460011415613f7c57613f7964e8d4a510006120238660400151612a84886060015189608001516137e890919063ffffffff16565b90505b6000613fac6305f5e100612023613fa16134b6613f9887613df8565b613e2389613df8565b6060890151906137e8565b9050613fcf612710612023838860800151612710016137e890919063ffffffff16565b9695505050505050565b600080613fff6305f5e100612023613ff48860200151612561565b6060880151906137e8565b9050600061402f662386f26fc100006120236140286134b660008a600001518b60200151613e0b565b85906137e8565b905083600114156140475761404482826123d9565b90505b600061405d828860000151876002811061297757fe5b979650505050505050565b600082614076575080610602565b8260011415613bd85764e8d4a51000613de983806137e8565b600080821361409d57600080fd5b82156140d3576305f5e1006140c485600101612a84600d54866137e890919063ffffffff16565b816140cb57fe5b0590506108fc565b6305f5e1006140f485600101612a84600d54866137e890919063ffffffff16565b600003816140cb57fe5b600080821361410c57600080fd5b6305f5e10061412d84600101612a84600e54866137e890919063ffffffff16565b8161413457fe5b059392505050565b6000808313614187576040805162461bcd60e51b81526020600482015260126024820152716c206d75737420626520706f73697469766560701b604482015290519081900360640190fd5b610fef600a6120236141a661419e898989896142bb565b6007906137e8565b610f136141b58a8a8a8a61436b565b6003906137e8565b6000806141dc888860008913886141d5600f54612561565b898961343b565b601c546040805163a3b1b31d60e01b815290519698509196506142839560008d1395508894506001600160a01b03909116925063a3b1b31d91600480820192602092909190829003018186803b15801561423557600080fd5b505afa158015614249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061426d9190614873565b60008c8152601160205260409020929190612633565b9150965096945050505050565b60008061429d8484612066565b9050610fef662386f26fc1000061202361205f6134b6898989613e0b565b6000806142cc86612a8481806137e8565b90506142ee6142e760026120236003612a848a818d806137e8565b8290612066565b90506143016142e786612a8489826137e8565b90506143196142e7600461202388612a8481806137e8565b905061432f846120238181856305f5e1006137e8565b9050613fcf61433e8585612066565b61202361434b8787612066565b6120236305f5e100612a84613b9b6143648b6002613891565b8c90612066565b6000816143955761438e83612023662386f26fc10000612a848960028a05612066565b9050612982565b61438e826120236305f5e100612a846143bd6143b8610cc08a868686838b612066565b6143ca565b612a848b60028c05612066565b60008080805b60088110156144305760006143e484614439565b905061441261440b6143f68884612066565b6120236305f5e100612a846002818d896123d9565b8590612066565b9250838314156144225750614430565b5090915081906001016143d0565b50909392505050565b6000816000136144535761444c82614486565b9050610818565b640177825eff1982121561446957506000610818565b61444c61447883600003614486565b61086f6305f5e10080612125565b60008161449857506305f5e100610818565b6402540be4008211156144d7576040805162461bcd60e51b8152602060048201526002602482015261134d60f21b604482015290519081900360640190fd5b60006305f5e1006144f86144f3630421a89e61086f8785612125565b61457e565b816144ff57fe5b049050600281900a600061452161451a84630421a89e612125565b869061298a565b90506305f5e100600060105b8015614573576145586305f5e100613e236305f5e10061086f85898161454f57fe5b89919004612125565b92508183141561456757614573565b8291506000190161452d565b5061405d8483612125565b6305f5e1008106900390565b604051806080016040528060006001600160801b031681526020016145ad6145cc565b81526020016145ba6145cc565b81526020016145c76145cc565b905290565b60405180604001604052806002906020820280368337509192915050565b60405180604001604052806145fd6145cc565b8152602001600081525090565b60405180608001604052806000815260200160008152602001600081526020016000151581525090565b80356001600160a01b038116811461081857600080fd5b600082601f83011261465b578081fd5b6040516040810181811067ffffffffffffffff8211171561467857fe5b806040525080838560408601111561468e578384fd5b835b60028110156146af578135835260209283019290910190600101614690565b509195945050505050565b805169ffffffffffffffffffff8116811461081857600080fd5b6000602082840312156146e5578081fd5b6108fc82614634565b60008060408385031215614700578081fd5b61470983614634565b915061471760208401614634565b90509250929050565b600080600060608486031215614734578081fd5b61473d84614634565b925061474b60208501614634565b9150604084013590509250925092565b6000806040838503121561476d578182fd5b61477683614634565b946020939093013593505050565b600080600060608486031215614798578283fd5b6147a184614634565b95602085013595506040909401359392505050565b6000604082840312156147c7578081fd5b6108fc838361464b565b6000602082840312156147e2578081fd5b5035919050565b600080604083850312156147fb578182fd5b50508035926020909101359150565b60006080828403121561481b578081fd5b6040516080810181811067ffffffffffffffff8211171561483857fe5b806040525082358152602083013560208201526040830135604082015260608301358015158114614867578283fd5b60608201529392505050565b600060208284031215614884578081fd5b5051919050565b6000806060838503121561489d578182fd5b82359150614717846020850161464b565b6000806000606084860312156148c2578081fd5b505081359360208301359350604090920135919050565b600080600080600060a086880312156148f0578283fd5b6148f9866146ba565b945060208601519350604086015192506060860151915061491c608087016146ba565b90509295509295909350565b8060005b6002811015611e4557815184526020938401939091019060010161492c565b6001600160a01b0391909116815260200190565b60a08101818560005b6002811015614987578151835260209283019290910190600101614968565b5050506149976040830185614928565b826080830152949350505050565b901515815260200190565b600f94850b815292840b6020840152920b60408201526001600160801b03909116606082015260800190565b600f93840b81529190920b6020820152604081019190915260600190565b90815260200190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b6000602080835283518082850152825b81811015614a6057858101830151858201604001528201614a44565b81811115614a715783604083870101525b50601f01601f1916929092016040019392505050565b602080825260049082015263504d433360e01b604082015260600190565b602080825260049082015263504d433160e01b604082015260600190565b6020808252600490820152632826a19960e11b604082015260600190565b602080825260049082015263504d433560e01b604082015260600190565b6020808252600490820152630504d43360e41b604082015260600190565b81518152602080830151908201526040808301519082015260609182015115159181019190915260800190565b6000606082019050614b5d828451614928565b6020830151604083015292915050565b81516001600160801b0316815260208083015160e0830191614b9190840182614928565b506040830151614ba46060840182614928565b506060830151610cf960a0840182614928565b6001600160801b039586168152600f9490940b602085015291841660408401526060830152909116608082015260a00190565b9283526020830191909152604082015260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573738c6065603763fec3f5742441d3833f3f43b982453612d76adb39a885e3006b5f45524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f776e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb015369676e6564536166654d6174683a206469766973696f6e206f766572666c6f77536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f7745524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ac6894026d05d6f527ccf41fee0fe8cde301a3c735fc5a80cf0a6c912de968a064736f6c63430007060033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102485760003560e01c80637d7c2a1c1161013b578063ac4afa38116100b8578063dd62ed3e1161007c578063dd62ed3e146104f5578063e7dc45d314610508578063f2fde38b1461051b578063f3fef3a31461052e578063f844f2a61461054157610248565b8063ac4afa3814610485578063b02582dc146104a9578063b206ab84146104bc578063bfe51951146104cf578063d0209f96146104e257610248565b806389633081116100ff578063896330811461043a5780638da5cb5b1461044257806395d89b4114610457578063a457c2d71461045f578063a9059cbb1461047257610248565b80637d7c2a1c146103f55780637d8c2659146103fd5780637fc3846714610405578063854ad1b71461041d57806387c3a09a1461043257610248565b806333a37ffb116101c9578063545ed65a1161018d578063545ed65a146103ac5780635cda497d146103b457806370a08231146103c7578063715018a6146103da57806373f3489e146103e257610248565b806333a37ffb1461033a578063395093511461035e5780633d33bcd51461037157806347e7ef241461038657806351c6590a1461039957610248565b80631c2f4e97116102105780631c2f4e97146102c857806323a216c1146102e857806323b872dd146102f05780632e06396414610303578063313ce5671461032557610248565b806306fdde031461024d578063095ea7b31461026b578063128c113f1461028b57806318160ddd146102a0578063192679ed146102b5575b600080fd5b610255610554565b6040516102629190614a34565b60405180910390f35b61027e61027936600461475b565b6105ea565b60405161026291906149a5565b61029e61029936600461480a565b610608565b005b6102a861065c565b60405161026291906149fa565b61029e6102c33660046147d1565b610662565b6102db6102d63660046147b6565b610721565b6040516102629190614b6d565b6102a861081d565b61027e6102fe366004614720565b61087b565b6103166103113660046147b6565b610903565b6040516102629392919061495f565b61032d610afa565b6040516102629190614c00565b61034d61034836600461488b565b610b03565b604051610262959493929190614a11565b61027e61036c36600461475b565b610b38565b610379610b86565b6040516102629190614b4a565b6102a861039436600461475b565b610bd6565b61029e6103a73660046147d1565b610d00565b6102a8610d3d565b61029e6103c23660046148ae565b610d43565b6102a86103d53660046146d4565b610e21565b61029e610e3c565b6102a86103f03660046147d1565b610ee8565b61029e610ff8565b61029e6110e2565b61040d611137565b60405161026294939291906149b0565b610425611161565b6040516102629190614b1d565b61029e611247565b6102a86112aa565b61044a6112b0565b604051610262919061494b565b6102556112bf565b61027e61046d36600461475b565b611320565b61027e61048036600461475b565b611388565b6104986104933660046147d1565b61139c565b604051610262959493929190614bb7565b61029e6104b73660046147d1565b6113dd565b61029e6104ca3660046147e9565b611492565b61029e6104dd3660046147d1565b611577565b61029e6104f03660046147e9565b61161c565b6102a86105033660046146ee565b611774565b6102a8610516366004614784565b61179f565b61029e6105293660046146d4565b611894565b6102a861053c36600461475b565b611996565b61029e61054f3660046146d4565b611a8d565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156105e05780601f106105b5576101008083540402835291602001916105e0565b820191906000526020600020905b8154815290600101906020018083116105c357829003601f168201915b5050505050905090565b60006105fe6105f7611b79565b8484611b7d565b5060015b92915050565b601e546001600160a01b0316331461063b5760405162461bcd60e51b815260040161063290614ac3565b60405180910390fd5b6000610645611c69565b50601d8190559050610658601883611d25565b5050565b60035490565b61066a611b79565b6001600160a01b031661067b6112b0565b6001600160a01b0316146106c4576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b600081121580156106d85750620f42408113155b6106e157600080fd5b60088190556040517f0e5502f89db0c53034cbc3f53df6d411d72c6c9b9e711b952d4cc6a30d8ac73d906107169083906149fa565b60405180910390a150565b61072961458a565b6000610733611c69565b50905061073e6145cc565b6107466145cc565b61074e6145cc565b60005b60028110156107ec57600061076982878a6000611e4b565b90505087856002811061077857fe5b6020020187866002811061078857fe5b602002019190915291909152905060006107a183611fd7565b905060006107b18484844261200f565b6000858152601060205260409020600201549091506107d09082612066565b8585600281106107dc57fe5b6020020152505050600101610751565b50604080516080810182526001600160801b039095168552602085019390935291830152606082015290505b919050565b60008060005b60028110156108595760008181526010602052604090205461084f9083906001600160801b03166120cb565b9150600101610823565b50600f546108759061086f836305f5e100612125565b9061217e565b91505090565b60006108888484846121e5565b6108f884610894611b79565b6108f385604051806060016040528060288152602001614d8c602891396001600160a01b038a166000908152600260205260408120906108d2611b79565b6001600160a01b031681526020810191909152604001600020549190612342565b611b7d565b5060015b9392505050565b61090b6145cc565b6109136145cc565b601e546000906001600160a01b031633146109405760405162461bcd60e51b815260040161063290614ac3565b6000600f54116109625760405162461bcd60e51b815260040161063290614aa5565b835160008080526010602052600080516020614d2a8339815191525490916109a29161099d91600160801b909104600f90810b900b906123d9565b61243e565b600080805260106020908152600080516020614d2a83398151915280546001600160801b03908116600160801b600f96870b92909216820217909155908801516001909252600080516020614c3283398151915254610a0d9361099d9392909104810b900b906123d9565b60016000526010602052600080516020614c328339815191528054600f9290920b6001600160801b03908116600160801b029216919091179055845115610a8857600080610a628188815b60200201516124a3565b9188529188529092509050610a7784836120cb565b9350610a838382612066565b925050505b602085015115610ad157600080610aa160018881610a58565b602089810193909352918901929092529092509050610ac084836120cb565b9350610acc8382612066565b925050505b610aef600f54610aea610ae385612561565b84906123d9565b6125a5565b600f55509193909250565b60065460ff1690565b600080600080600080610b14611c69565b509050610b248882896000611e4b565b939c929b5090995097509095509350505050565b60006105fe610b45611b79565b846108f38560026000610b56611b79565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906120cb565b610b8e6145ea565b604080516080810180835290916018918391820190839060029082845b815481526020019060010190808311610bab5750505050508152602001600282015481525050905090565b601e546000906001600160a01b03163314610c035760405162461bcd60e51b815260040161063290614ac3565b6000610c0d61065c565b11610c1757600080fd5b6000610c256103f084612561565b9050610cc5610cc0600183601c60009054906101000a90046001600160a01b03166001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7e57600080fd5b505afa158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614873565b6012929190612633565b61270c565b9050610cdc8161086f85662386f26fc10000612125565b600f54909250610cec90846120cb565b600f55610cf98483612763565b5092915050565b601e546001600160a01b03163314610d2a5760405162461bcd60e51b815260040161063290614ac3565b600f54610d3790826120cb565b600f5550565b601d5481565b610d4b611b79565b6001600160a01b0316610d5c6112b0565b6001600160a01b031614610da5576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b8183108015610db5575060c88211155b610dd15760405162461bcd60e51b815260040161063290614ae1565b6009839055600a829055600b8190556040517f40eadc083dad26c82ca6e52052119f861019dc8b168294cc37f793801b6494a090610e1490859085908590614bea565b60405180910390a1505050565b6001600160a01b031660009081526001602052604090205490565b610e44611b79565b6001600160a01b0316610e556112b0565b6001600160a01b031614610e9e576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600080610ef3611c69565b5090506000610f19610f0760018487612855565b610f1360008588612855565b90612066565b6040805160808101808352929350600092610f7692869291601891839190820190839060029082845b815481526020019060010190808311610f42575050505050815260200160028201548152505061293d90919063ffffffff16565b9050610fef610f8361065c565b6010602052600080516020614c328339815191525460008052600080516020614d2a83398151915254600f5461086f92662386f26fc1000092610fe9926001600160801b0392831692610fe392169082908b90610f13908c908290612561565b9061298a565b90612125565b95945050505050565b601e546001600160a01b031633146110225760405162461bcd60e51b815260040161063290614ac3565b600061102c611c69565b50905060005b600281101561065857600080600061104a84866129e7565b909350905061105c8484836002612ae0565b9094509250508115905061107a57611076600f54826125a5565b600f555b81156110d8576000838152601060205260409020546110ab906110a6906001600160801b0316846125a5565b612c26565b600084815260106020526040902080546001600160801b0319166001600160801b03929092169190911790555b5050600101611032565b601e546001600160a01b0316331461110c5760405162461bcd60e51b815260040161063290614ac3565b6000611116611c69565b50905060005b60028110156106585761112f8183612c6a565b60010161111c565b601654601754600f82810b92600160801b90819004820b929182900b91046001600160801b031684565b61116961460a565b6000611173611c69565b506010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152549293509182916111ca918591600160801b90819004600f90810b810b9291909104810b900b612daf565b915091506111d66145cc565b82815260208101829052601a546111ee908286612dfe565b945060006111fb85612ea4565b90508560600151156112295761122261271061086f61121a82856120cb565b895190612125565b865261123f565b61123c61271061086f61121a828561298a565b86525b505050505090565b601e546001600160a01b031633146112715760405162461bcd60e51b815260040161063290614ac3565b60175461a8c06001600160801b03600160801b90920482160116421015611297576112a8565b6112a042612f27565b6112a86130ac565b565b600f5481565b6000546001600160a01b031690565b60058054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156105e05780601f106105b5576101008083540402835291602001916105e0565b60006105fe61132d611b79565b846108f385604051806060016040528060258152602001614eb16025913960026000611357611b79565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612342565b60006105fe611395611b79565b84846121e5565b60106020526000908152604090208054600182015460028301546003909301546001600160801b0380841694600160801b909404600f0b9392811692911685565b6113e5611b79565b6001600160a01b03166113f66112b0565b6001600160a01b03161461143f576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b60008112158015611454575063773594008113155b61145d57600080fd5b60078190556040517ffd74ba77488a6a7a45711e7c3469f918238eb90178880837da4a029a93ccf375906107169083906149fa565b61149a611b79565b6001600160a01b03166114ab6112b0565b6001600160a01b0316146114f4576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b806000131580156115085750620493e08213155b801561151357508181125b61152f5760405162461bcd60e51b815260040161063290614ae1565b600d829055600e8190556040517fbacb10fce6db592e49a2f13ebfa4af23c68a1ddc3962bc0818478a518f3fa95f9061156b9084908490614a03565b60405180910390a15050565b61157f611b79565b6001600160a01b03166115906112b0565b6001600160a01b0316146115d9576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b60008112156115e757600080fd5b600c8190556040517f8e6edd6f6b5a50f0d6a8f356374101e297ba1ac391a14aaa3248ba40d7665e73906107169083906149fa565b611624611b79565b6001600160a01b03166116356112b0565b6001600160a01b03161461167e576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b6102588211156116a05760405162461bcd60e51b815260040161063290614ae1565b8060001080156116b257506102588111155b6116ce5760405162461bcd60e51b815260040161063290614ae1565b6000805260116020526117027f4ad3b33220dddc71b994a52d72c06b10862965f7d926534c05c00fb7e819e7b783836130be565b600160005260116020526117377f17bc176d2408558f6e4111feebc3cab4e16b63e967be91cde721f4c8a488b55283836130be565b611743601283836130be565b7ff2450f3986de0a389b21b7df0371586ea26c539d4a18d0b39542308db22a48c2828260405161156b929190614a03565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b601e546000906001600160a01b031633146117cc5760405162461bcd60e51b815260040161063290614ac3565b6117d461065c565b156117de57600080fd5b508160006117ea611c69565b5090506117f68361243e565b60168054600f9290920b6001600160801b03908116600160801b0292169190911790556118228161243e565b60178054600f9290920b6001600160801b03166001600160801b031990921691909117905561185042612c26565b601780546001600160801b03928316600160801b029216919091179055601d819055600f5461187f90856120cb565b600f5561188c8583612763565b509392505050565b61189c611b79565b6001600160a01b03166118ad6112b0565b6001600160a01b0316146118f6576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b6001600160a01b03811661193b5760405162461bcd60e51b8152600401808060200182810382526026815260200180614c746026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b601e546000906001600160a01b031633146119c35760405162461bcd60e51b815260040161063290614ac3565b816119cc6130ce565b10156119ea5760405162461bcd60e51b815260040161063290614aff565b6000611a006119f884612561565b600003610ee8565b9050611a59610cc0600083601c60009054906101000a90046001600160a01b03166001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7e57600080fd5b9050611a708161086f85662386f26fc10000612125565b600f54909250611a80908461298a565b600f55610cf9848361314d565b611a95611b79565b6001600160a01b0316611aa66112b0565b6001600160a01b031614611aef576040805162461bcd60e51b81526020600482018190526024820152600080516020614db4833981519152604482015290519081900360640190fd5b601e546001600160a01b0316158015611b1057506001600160a01b03811615155b611b1957600080fd5b601e80546001600160a01b0319166001600160a01b0392909216919091179055565b80546f7fffffffffffffffffffffffffffffff60801b6001600160801b03918216178255600182018054909116905560056002820155600390810155565b3390565b6001600160a01b038316611bc25760405162461bcd60e51b8152600401808060200182810382526024815260200180614e416024913960400191505060405180910390fd5b6001600160a01b038216611c075760405162461bcd60e51b8152600401808060200182810382526022815260200180614c9a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600080600080601b60009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015611cbd57600080fd5b505afa158015611cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf591906148d9565b5093505092505060008213611d1c5760405162461bcd60e51b815260040161063290614a87565b90925090509091565b6000611d4d662386f26fc1000061086f8460400151856000015161212590919063ffffffff16565b8251909150600090611d5f908361298a565b90506000836020015111611d9f576040805162461bcd60e51b81526020600482015260026024820152614e3160f01b604482015290519081900360640190fd5b826060015115611df95760208301516002850154611dbc916120cb565b6002850155611dd9611dcd83612561565b8560005b0154906123d9565b8455611def611de782612561565b856001611dd1565b8460010155611e45565b60208301516002850154611e0c9161298a565b6002850155611e29611e1d83612561565b8560005b015490612066565b8455611e3f611e3782612561565b856001611e21565b84600101555b50505050565b600080600080600080878a60028110611e6057fe5b602002015115611ea7576000806000611e7a8d8d8d613249565b9250925092506000611e8e8e858585612ae0565b919650909150611ea090508b82612066565b9a50505050505b60008a815260106020526040812054611ece90600160801b9004600f90810b900b8c6133d0565b9050611efc8b8b60008c8f60028110611ee357fe5b60200201511384611ef5600f54612561565b878e61343b565b939a50919850909550909350611f2f90508b611f188385612066565b611f278b610f13600f54612561565b6000806134d4565b945050611fc96000898c60028110611f4357fe5b6020908102919091015160008e815260118352604090819020815160c08101835281546001600160801b038082168352600160801b91829004600f90810b810b810b97840197909752600184015490811694830194909452909204840b840b90930b60608201526002830154608082015260039092015460a083015290911288426135b3565b955050945094509450945094565b60008181526010602052604081205461060290839061200490600160801b9004600f90810b900b826133d0565b611f27600f54612561565b60006120296305f5e10061202386866137e8565b90613891565b600086815260106020526040902060030154909150610fef9062015180906120239061205f9086906001600160801b031661298a565b84906137e8565b600082820181831280159061207b5750838112155b80612090575060008312801561209057508381125b6108fc5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d096021913960400191505060405180910390fd5b6000828201838110156108fc576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008261213457506000610602565b8282028284828161214157fe5b04146108fc5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d6b6021913960400191505060405180910390fd5b60008082116121d4576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816121dd57fe5b049392505050565b6001600160a01b03831661222a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e1c6025913960400191505060405180910390fd5b6001600160a01b03821661226f5760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0f6023913960400191505060405180910390fd5b61227a838383613949565b6122b781604051806060016040528060268152602001614cbc602691396001600160a01b0386166000908152600160205260409020549190612342565b6001600160a01b0380851660009081526001602052604080822093909355908416815220546122e690826120cb565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156123d15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561239657818101518382015260200161237e565b50505050905090810190601f1680156123c35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183038183128015906123ee5750838113155b80612403575060008312801561240357508381135b6108fc5760405162461bcd60e51b8152600401808060200182810382526024815260200180614e8d6024913960400191505060405180910390fd5b60006f7fffffffffffffffffffffffffffffff19821215801561246457506001607f1b82125b61249f5760405162461bcd60e51b8152600401808060200182810382526027815260200180614ce26027913960400191505060405180910390fd5b5090565b60008060008060006124b3611c69565b5090506124c187828861394e565b6000898152601060205260408120600181015490549398509195509161250d916001600160801b03169061250390600160801b9004600f90810b900b8a612066565b888a600003613a91565b9350905061251d6110a68261270c565b60008981526010602052604090206001810180546001600160801b03939093166001600160801b031990931692909217909155600201549450505092959194509250565b6000600160ff1b821061249f5760405162461bcd60e51b8152600401808060200182810382526028815260200180614e656028913960400191505060405180910390fd5b6000808212156125f55782826000038403915081106125f0576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b610602565b5080820182811015610602576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b6040805160c08101825285546001600160801b038082168352600160801b91829004600f90810b810b602085015260018901549182169484019490945204820b90910b606082015260028501546080820152600385015460a082015260009061269e818686866135b3565b815187546020840151600f90810b6001600160801b03908116600160801b9081029482166001600160801b0319948516178216949094178b5560408601516001909b01805460609097015190920b811690930299831694909116939093171696909617905550929392505050565b60008082121561249f576040805162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f736974697665604482015290519081900360640190fd5b6001600160a01b0382166127be576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6127ca60008383613949565b6003546127d790826120cb565b6003556001600160a01b0382166000908152600160205260409020546127fd90826120cb565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000806128606145cc565b600080516020614d2a83398151915254600160801b90819004600f90810b810b8352600080516020614c3283398151915254829004810b810b60208481019190915260008981526010909152604090205491909104810b900b156129345760006128cc87878488611e4b565b5050506000898152601060205260409020600101549192506305f5e10091612928915061290590610ae3906001600160801b0316612561565b60008a815260106020526040902054600160801b9004600f90810b900b906137e8565b8161292f57fe5b059250505b50949350505050565b60008061295f6305f5e1006120236129588760200151612561565b86906137e8565b84516020810151919250612982918391610f13919060005b602002015190612066565b949350505050565b6000828211156129e1576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152549091829182918291612a3e918791600160801b91829004600f90810b810b92909104810b900b612daf565b600160008181526010602052600080516020614c328339815191525493955091935090916305f5e10091612a8a91600160801b9004600f90810b900b90612a8490613bb7565b906137e8565b81612a9157fe5b059050612ad2876040518060a00160405280868152602001858152602001848152602001898152602001600c548152506018613c0a9092919063ffffffff16565b909890975095505050505050565b600080600080861315612bc45760008512612b245785612afe6130ce565b1015612b1c5760405162461bcd60e51b815260040161063290614aa5565b859150612bbf565b600087815260106020526040902054612b5090612b49906001600160801b0316612561565b86906123d9565b600088815260106020526040902054612b71906001600160801b0316612561565b60000392509050612b828686612066565b612b8a6130ce565b1015612ba85760405162461bcd60e51b815260040161063290614aa5565b612bbc612bb58787612066565b8390612066565b91505b612bf5565b6000861215612bf557600087815260106020526040902054612bf0906001600160801b03168787613ca0565b925090505b600087815260106020526040902054612c1a90859084906001600160801b0316613cd0565b92509450945094915050565b6000600160801b821061249f5760405162461bcd60e51b8152600401808060200182810382526027815260200180614ce26027913960400191505060405180910390fd5b6000828152601060205260409020600301546001600160801b0316612cb857600082815260106020526040902060030180546001600160801b031916426001600160801b0316179055610658565b6000828152601060205260409020600301546001600160801b03164211612cde57610658565b6000806000612cee858542613d4f565b6000888152601060205260409020600201549295509093509150612d129083612066565b6000868152601060205260409020600201558015612d3a57612d36600f54826125a5565b600f555b600085815260106020526040908190206003810180546001600160801b031916426001600160801b03161790556002015490517f3e5170eaa3b2dec8bb1a3e32834aed10d5bbdb77abda3b065447543099eaebfa91612da0918891879187908790614a11565b60405180910390a15050505050565b60008060006305f5e100612dc886612a8460008a613dc0565b81612dcf57fe5b05905060006305f5e100612de886612a8460018b613dc0565b81612def57fe5b92989205965090945050505050565b612e0661460a565b6000612e1185612561565b90506000612e2c82610f138760016020020151886000612977565b602086015160009182039250612e43908783612977565b1315612e50578160000390505b600081136060840152612e6281613df8565b60208401526305f5e100612e7985610fe984613df8565b81612e8057fe5b04835284516020860151612e9691600091613e0b565b604084015250509392505050565b600080612ed2612ecd601d546120236305f5e100612a84601d54896123d990919063ffffffff16565b613df8565b9050612eff612ef6600b5461086f84600954600a540361212590919063ffffffff16565b600954906120cb565b9150600954821015612f115760095491505b600a54821115612f2157600a5491505b50919050565b6000612f31611c69565b50601754909150600090612f5890600f90810b900b6120236305f5e100612a8486846123d9565b90506000612f6e6305f5e10061202384806137e8565b601754909150612fa090612f9390600160801b90046001600160801b03168603612561565b61202383620151806137e8565b9050612fe76305f5e100612fda612fba625b8d80856137e8565b601654610f139063059a538090600160801b9004600f90810b900b6137e8565b81612fe157fe5b0561243e565b60168054600f9290920b6001600160801b03908116600160801b0292169190911790556130138361243e565b60178054600f9290920b6001600160801b03166001600160801b031990921691909117905561304184612c26565b601780546001600160801b03908116600160801b93909116830217908190556016546040517fc0286f283c0343297f024da33b37cbae636c6f78d8b29803dd94a72c09d44b1a9361309e939204600f90810b92900b9088906149dc565b60405180910390a150505050565b601680546001600160801b0319169055565b6002830191909155600390910155565b60008060005b600281101561313f576000818152601060205260409020546131009083906001600160801b03166120cb565b915060006018826002811061311157fe5b0154121561313757613134826018836002811061312a57fe5b01546000036125a5565b91505b6001016130d4565b50600f54610875908261298a565b6001600160a01b0382166131925760405162461bcd60e51b8152600401808060200182810382526021815260200180614dfb6021913960400191505060405180910390fd5b61319e82600083613949565b6131db81604051806060016040528060228152602001614c52602291396001600160a01b0385166000908152600160205260409020549190612342565b6001600160a01b038316600090815260016020526040902055600354613201908261298a565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6010602052600080516020614d2a8339815191525460016000908152600080516020614c32833981519152548351919283928392839283928392600160801b92839004600f90810b810b93909104810b900b906132a79083906123d9565b91506132bb896001602002015182906123d9565b90508a6132d7576132d4828a60005b6020020151613eb2565b95505b8a600114156132ef576132ec818a60016132ca565b95505b6132fa8a8383612daf565b90955093506305f5e10061331282612a846001613bb7565b8161331957fe5b059250505060006040518060a001604052808581526020018481526020018381526020018a8152602001600c54815250905060006133578b83613f2a565b60408051608081018083529293506133b49285928f9291601891839190820190839060029082845b81548152602001906001019080831161337f5750505050508152602001600282015481525050613fd99092919063ffffffff16565b96506133c081886123d9565b9750505050505093509350939050565b6000826133df57506000610602565b600083131561341357600082815260106020526040902054613409906001600160801b0316612561565b6000039050610602565b600082815260106020526040902054613434906001600160801b0316612561565b9050610602565b6000806000806000806134518d8b8b8b8b6134d4565b905061345d8d8d614068565b94506000613480662386f26fc100006120236134798286612066565b89906137e8565b905061348d8e8d8861408f565b93506134998185612066565b90506134a58e876140fe565b92508086836134bb6134b688613df8565b612561565b9650965096509650505097509750975097509792505050565b60008561351c5760006134fd6305f5e1006120236134f489888a8961413c565b600854906137e8565b60165490915061351490600f90810b900b82612066565b915050610fef565b85600114156135a757836135505760165461354990600160801b9004600f90810b900b6305f5e1006137e8565b9050610fef565b60006135726305f5e10061202361356989888a8961413c565b600754906137e8565b90506135146305f5e100612023613590662386f26fc1000085612066565b601654600160801b9004600f90810b900b906137e8565b50600095945050505050565b608084015182906135c5575081612982565b83156136d8578460800151820385604001516001600160801b031610613688578460600151600f0b81121561368857600061361b8660a0015187604001516001600160801b031685038161361557fe5b04612561565b905061271061363e82612710038860600151600f0b6137e890919063ffffffff16565b8161364557fe5b05821361367d57613670612710612fda83612710038960600151600f0b6137e890919063ffffffff16565b600f90810b900b60608701525b50506060840151600f0b5b808560200151600f0b13806136ac5750608085015185516001600160801b03160182115b156136c7576136ba8161243e565b600f90810b900b60208601525b6001600160801b0382168552612982565b8460800151820385600001516001600160801b03161061378f578460200151600f0b81131561378f5760006137228660a0015187600001516001600160801b031685038161361557fe5b905061271061374582612710018860200151600f0b6137e890919063ffffffff16565b8161374c57fe5b05821261378457613777612710612fda83612710018960200151600f0b6137e890919063ffffffff16565b600f90810b900b60208701525b50506020840151600f0b5b808560600151600f0b12806137b6575081856080015186604001516001600160801b031601105b156137d1576137c48161243e565b600f90810b900b60608601525b6001600160801b0382166040860152949350505050565b6000826137f757506000610602565b8260001914801561380b5750600160ff1b82145b156138475760405162461bcd60e51b8152600401808060200182810382526027815260200180614dd46027913960400191505060405180910390fd5b8282028284828161385457fe5b05146108fc5760405162461bcd60e51b8152600401808060200182810382526027815260200180614dd46027913960400191505060405180910390fd5b6000816138e5576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b816000191480156138f95750600160ff1b83145b156139355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d4a6021913960400191505060405180910390fd5b600082848161394057fe5b05949350505050565b505050565b60008060008060008061396189896129e7565b60008b815260106020526040902054919550915061399c908a908690849061399790600160801b9004600f90810b900b8c613eb2565b612ae0565b60008c81526010602052604081205492975092955093509091506139d8906139d290600160801b9004600f90810b900b89612066565b8a6133d0565b90506000806139eb8b8b8b8689896141bd565b9150915083600014613a0757613a03600f54856125a5565b600f555b60008b815260106020526040902054613a2d906110a6906001600160801b0316886125a5565b60008c815260106020526040902080546001600160801b0319166001600160801b0392909216919091179055613a628261270c565b613a7f6305f5e10061086f613a768d613df8565b610fe98661270c565b97509750505050505050935093915050565b60008080613a9f8685612066565b9050851580613ab95750600086138015613ab95750600084135b80613acf5750600086128015613acf5750600084125b15613b0d57613b06613ae4612ecd8887612066565b612023613af361347988613df8565b610f13613aff8b613df8565b8c906137e8565b9250613bad565b600086138015613b1d5750600084125b8015613b295750600081135b80613b4b5750600086128015613b3f5750600084135b8015613b4b5750600081125b15613b7f578692506305f5e100613b70613b6587866123d9565b6000879003906137e8565b81613b7757fe5b059150613bad565b8015613b89578492505b6305f5e100613ba2613b9b878a6123d9565b88906137e8565b81613ba957fe5b0591505b5094509492505050565b600081613bc657506000610818565b8160011415613bd85750614e20610818565b6040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b6000806000613c198585613f2a565b6040805160808101808352929350613c6992909189918391820190839060029082845b815481526020019060010190808311613c3c57505050505081526020016002820154815250508587613fd9565b9150613c7581836123d9565b9250613c8783878760028110611e2157fe5b868660028110613c9357fe5b0155509094909350915050565b600080613cba83612023613cb388612561565b87906137e8565b9050613cc681856123d9565b9150935093915050565b60006003846003811115613ce057fe5b1415613cfc57613cf583610f138460026137e8565b90506108fc565b6001846003811115613d0a57fe5b1415613d2957613d1f83610f138460026137e8565b60000390506108fc565b6002846003811115613d3757fe5b1415613d48578260000390506108fc565b50816108fc565b600080600080613d5f8787614068565b9050613d6a87611fd7565b9350613d788782868861200f565b600088815260106020526040812054919450613db491662386f26fc1000091612023918791600160801b909104600f90810b909103900b6137e8565b91505093509350939050565b600082613dd257506305f5e100610602565b8260011415613bd857612710613de98360026137e8565b81613df057fe5b059050610602565b60008082121561249f5781600003610602565b600080613e29613e1a84613df8565b613e2386613df8565b906120cb565b905080613e3a5760009150506108fc565b84613e5f57613e578161086f662386f26fc10000610fe988613df8565b9150506108fc565b8460011415613e8057613e578161086f662386f26fc10000610fe987613df8565b6040805162461bcd60e51b815260206004820152600260248201526104e360f41b604482015290519081900360640190fd5b600080613ebf8484612066565b9050600081138015613ed15750600084125b15613ee0576003915050610602565b600081128015613ef05750600084135b15613eff576001915050610602565b60008112158015613f11575060008412155b15613f20576002915050610602565b6000915050610602565b600080613f408484600001518560200151614290565b905060008460011415613f7c57613f7964e8d4a510006120238660400151612a84886060015189608001516137e890919063ffffffff16565b90505b6000613fac6305f5e100612023613fa16134b6613f9887613df8565b613e2389613df8565b6060890151906137e8565b9050613fcf612710612023838860800151612710016137e890919063ffffffff16565b9695505050505050565b600080613fff6305f5e100612023613ff48860200151612561565b6060880151906137e8565b9050600061402f662386f26fc100006120236140286134b660008a600001518b60200151613e0b565b85906137e8565b905083600114156140475761404482826123d9565b90505b600061405d828860000151876002811061297757fe5b979650505050505050565b600082614076575080610602565b8260011415613bd85764e8d4a51000613de983806137e8565b600080821361409d57600080fd5b82156140d3576305f5e1006140c485600101612a84600d54866137e890919063ffffffff16565b816140cb57fe5b0590506108fc565b6305f5e1006140f485600101612a84600d54866137e890919063ffffffff16565b600003816140cb57fe5b600080821361410c57600080fd5b6305f5e10061412d84600101612a84600e54866137e890919063ffffffff16565b8161413457fe5b059392505050565b6000808313614187576040805162461bcd60e51b81526020600482015260126024820152716c206d75737420626520706f73697469766560701b604482015290519081900360640190fd5b610fef600a6120236141a661419e898989896142bb565b6007906137e8565b610f136141b58a8a8a8a61436b565b6003906137e8565b6000806141dc888860008913886141d5600f54612561565b898961343b565b601c546040805163a3b1b31d60e01b815290519698509196506142839560008d1395508894506001600160a01b03909116925063a3b1b31d91600480820192602092909190829003018186803b15801561423557600080fd5b505afa158015614249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061426d9190614873565b60008c8152601160205260409020929190612633565b9150965096945050505050565b60008061429d8484612066565b9050610fef662386f26fc1000061202361205f6134b6898989613e0b565b6000806142cc86612a8481806137e8565b90506142ee6142e760026120236003612a848a818d806137e8565b8290612066565b90506143016142e786612a8489826137e8565b90506143196142e7600461202388612a8481806137e8565b905061432f846120238181856305f5e1006137e8565b9050613fcf61433e8585612066565b61202361434b8787612066565b6120236305f5e100612a84613b9b6143648b6002613891565b8c90612066565b6000816143955761438e83612023662386f26fc10000612a848960028a05612066565b9050612982565b61438e826120236305f5e100612a846143bd6143b8610cc08a868686838b612066565b6143ca565b612a848b60028c05612066565b60008080805b60088110156144305760006143e484614439565b905061441261440b6143f68884612066565b6120236305f5e100612a846002818d896123d9565b8590612066565b9250838314156144225750614430565b5090915081906001016143d0565b50909392505050565b6000816000136144535761444c82614486565b9050610818565b640177825eff1982121561446957506000610818565b61444c61447883600003614486565b61086f6305f5e10080612125565b60008161449857506305f5e100610818565b6402540be4008211156144d7576040805162461bcd60e51b8152602060048201526002602482015261134d60f21b604482015290519081900360640190fd5b60006305f5e1006144f86144f3630421a89e61086f8785612125565b61457e565b816144ff57fe5b049050600281900a600061452161451a84630421a89e612125565b869061298a565b90506305f5e100600060105b8015614573576145586305f5e100613e236305f5e10061086f85898161454f57fe5b89919004612125565b92508183141561456757614573565b8291506000190161452d565b5061405d8483612125565b6305f5e1008106900390565b604051806080016040528060006001600160801b031681526020016145ad6145cc565b81526020016145ba6145cc565b81526020016145c76145cc565b905290565b60405180604001604052806002906020820280368337509192915050565b60405180604001604052806145fd6145cc565b8152602001600081525090565b60405180608001604052806000815260200160008152602001600081526020016000151581525090565b80356001600160a01b038116811461081857600080fd5b600082601f83011261465b578081fd5b6040516040810181811067ffffffffffffffff8211171561467857fe5b806040525080838560408601111561468e578384fd5b835b60028110156146af578135835260209283019290910190600101614690565b509195945050505050565b805169ffffffffffffffffffff8116811461081857600080fd5b6000602082840312156146e5578081fd5b6108fc82614634565b60008060408385031215614700578081fd5b61470983614634565b915061471760208401614634565b90509250929050565b600080600060608486031215614734578081fd5b61473d84614634565b925061474b60208501614634565b9150604084013590509250925092565b6000806040838503121561476d578182fd5b61477683614634565b946020939093013593505050565b600080600060608486031215614798578283fd5b6147a184614634565b95602085013595506040909401359392505050565b6000604082840312156147c7578081fd5b6108fc838361464b565b6000602082840312156147e2578081fd5b5035919050565b600080604083850312156147fb578182fd5b50508035926020909101359150565b60006080828403121561481b578081fd5b6040516080810181811067ffffffffffffffff8211171561483857fe5b806040525082358152602083013560208201526040830135604082015260608301358015158114614867578283fd5b60608201529392505050565b600060208284031215614884578081fd5b5051919050565b6000806060838503121561489d578182fd5b82359150614717846020850161464b565b6000806000606084860312156148c2578081fd5b505081359360208301359350604090920135919050565b600080600080600060a086880312156148f0578283fd5b6148f9866146ba565b945060208601519350604086015192506060860151915061491c608087016146ba565b90509295509295909350565b8060005b6002811015611e4557815184526020938401939091019060010161492c565b6001600160a01b0391909116815260200190565b60a08101818560005b6002811015614987578151835260209283019290910190600101614968565b5050506149976040830185614928565b826080830152949350505050565b901515815260200190565b600f94850b815292840b6020840152920b60408201526001600160801b03909116606082015260800190565b600f93840b81529190920b6020820152604081019190915260600190565b90815260200190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b6000602080835283518082850152825b81811015614a6057858101830151858201604001528201614a44565b81811115614a715783604083870101525b50601f01601f1916929092016040019392505050565b602080825260049082015263504d433360e01b604082015260600190565b602080825260049082015263504d433160e01b604082015260600190565b6020808252600490820152632826a19960e11b604082015260600190565b602080825260049082015263504d433560e01b604082015260600190565b6020808252600490820152630504d43360e41b604082015260600190565b81518152602080830151908201526040808301519082015260609182015115159181019190915260800190565b6000606082019050614b5d828451614928565b6020830151604083015292915050565b81516001600160801b0316815260208083015160e0830191614b9190840182614928565b506040830151614ba46060840182614928565b506060830151610cf960a0840182614928565b6001600160801b039586168152600f9490940b602085015291841660408401526060830152909116608082015260a00190565b9283526020830191909152604082015260600190565b60ff9190911681526020019056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573738c6065603763fec3f5742441d3833f3f43b982453612d76adb39a885e3006b5f45524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636553616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f776e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb015369676e6564536166654d6174683a206469766973696f6e206f766572666c6f77536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f7745524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220ac6894026d05d6f527ccf41fee0fe8cde301a3c735fc5a80cf0a6c912de968a064736f6c63430007060033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "allowance(address,address)": {
        "details": "See {IERC20-allowance}."
      },
      "approve(address,uint256)": {
        "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address."
      },
      "balanceOf(address)": {
        "details": "See {IERC20-balanceOf}."
      },
      "decimals()": {
        "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}."
      },
      "decreaseAllowance(address,uint256)": {
        "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`."
      },
      "getLPTokenPrice(int256)": {
        "returns": {
          "_0": "LPTokenPrice scaled by 1e16"
        }
      },
      "getTradePrice(uint256,int256[2])": {
        "params": {
          "_productId": "product id",
          "_tradeAmounts": "amount of position to trade. positive for pool short and negative for pool long."
        }
      },
      "getUtilizationRatio()": {
        "returns": {
          "_0": "Utilization Ratio scaled by 1e8"
        }
      },
      "increaseAllowance(address,uint256)": {
        "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address."
      },
      "name()": {
        "details": "Returns the name of the token."
      },
      "owner()": {
        "details": "Returns the address of the current owner."
      },
      "renounceOwnership()": {
        "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."
      },
      "symbol()": {
        "details": "Returns the symbol of the token, usually a shorter version of the name."
      },
      "totalSupply()": {
        "details": "See {IERC20-totalSupply}."
      },
      "transfer(address,uint256)": {
        "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`."
      },
      "transferFrom(address,address,uint256)": {
        "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`."
      },
      "transferOwnership(address)": {
        "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
      },
      "updatePoolPositions(int256[2])": {
        "params": {
          "_tradeAmounts": "amount of positions to trade. positive for pool short and negative for pool long."
        }
      }
    },
    "title": "PerpetualMarketCore",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "completeHedgingProcedure((uint256,uint256,uint256,bool))": {
        "notice": "Update netting info to complete heging procedure"
      },
      "deposit(address,uint256)": {
        "notice": "Provides liquidity"
      },
      "getLPTokenPrice(int256)": {
        "notice": "Gets LP token price LPTokenPrice = (L + ΣUnrealizedPnL_i - ΣAmountLockedLiquidity_i) / Supply"
      },
      "getTokenAmountForHedging()": {
        "notice": "Gets USDC and underlying amount to make the pool delta neutral"
      },
      "getTradePrice(uint256,int256[2])": {
        "notice": "Gets trade price"
      },
      "getUtilizationRatio()": {
        "notice": "Gets utilization ratio Utilization Ratio = (ΣAmountLockedLiquidity_i) / L"
      },
      "initialize(address,uint256,int256)": {
        "notice": "Initialize pool with initial liquidity and funding rate"
      },
      "rebalance()": {
        "notice": "Locks liquidity if more collateral required and unlocks liquidity if there is unrequied collateral."
      },
      "updatePoolPositions(int256[2])": {
        "notice": "Adds or removes pool positions"
      },
      "updatePoolSnapshot()": {
        "notice": "Updates pool snapshot Calculates ETH variance and base funding rate for future pool."
      },
      "withdraw(address,uint256)": {
        "notice": "xxWithdraws liquidity"
      }
    },
    "notice": "Perpetual Market Core Contract manages perpetual pool positions and calculates amount of collaterals. Error Code PMC0: No available liquidity PMC1: No available liquidity PMC2: caller must be PerpetualMarket contract PMC3: underlying price must not be 0 PMC4: pool delta must be negative PMC5: invalid params",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 53,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_owner",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 841,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_balances",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 847,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_allowances",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 849,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_totalSupply",
        "offset": 0,
        "slot": "3",
        "type": "t_uint256"
      },
      {
        "astId": 851,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_name",
        "offset": 0,
        "slot": "4",
        "type": "t_string_storage"
      },
      {
        "astId": 853,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_symbol",
        "offset": 0,
        "slot": "5",
        "type": "t_string_storage"
      },
      {
        "astId": 855,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "_decimals",
        "offset": 0,
        "slot": "6",
        "type": "t_uint8"
      },
      {
        "astId": 8920,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "squaredPerpFundingMultiplier",
        "offset": 0,
        "slot": "7",
        "type": "t_int256"
      },
      {
        "astId": 8922,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "perpFutureMaxFundingRate",
        "offset": 0,
        "slot": "8",
        "type": "t_int256"
      },
      {
        "astId": 8924,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "minSlippageToleranceOfHedge",
        "offset": 0,
        "slot": "9",
        "type": "t_uint256"
      },
      {
        "astId": 8926,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "maxSlippageToleranceOfHedge",
        "offset": 0,
        "slot": "10",
        "type": "t_uint256"
      },
      {
        "astId": 8928,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "hedgeRateOfReturnThreshold",
        "offset": 0,
        "slot": "11",
        "type": "t_uint256"
      },
      {
        "astId": 8930,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "poolMarginRiskParam",
        "offset": 0,
        "slot": "12",
        "type": "t_int256"
      },
      {
        "astId": 8932,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "tradeFeeRate",
        "offset": 0,
        "slot": "13",
        "type": "t_int256"
      },
      {
        "astId": 8934,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "protocolFeeRate",
        "offset": 0,
        "slot": "14",
        "type": "t_int256"
      },
      {
        "astId": 8961,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "amountLiquidity",
        "offset": 0,
        "slot": "15",
        "type": "t_uint256"
      },
      {
        "astId": 8965,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "pools",
        "offset": 0,
        "slot": "16",
        "type": "t_mapping(t_uint256,t_struct(Pool)8945_storage)"
      },
      {
        "astId": 8969,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "spreadInfos",
        "offset": 0,
        "slot": "17",
        "type": "t_mapping(t_uint256,t_struct(Info)14816_storage)"
      },
      {
        "astId": 8971,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "lpTokenSpreadInfo",
        "offset": 0,
        "slot": "18",
        "type": "t_struct(Info)14816_storage"
      },
      {
        "astId": 8973,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "poolSnapshot",
        "offset": 0,
        "slot": "22",
        "type": "t_struct(PoolSnapshot)8954_storage"
      },
      {
        "astId": 8975,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "nettingInfo",
        "offset": 0,
        "slot": "24",
        "type": "t_struct(Info)13935_storage"
      },
      {
        "astId": 8977,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "priceFeed",
        "offset": 0,
        "slot": "27",
        "type": "t_contract(AggregatorV3Interface)45"
      },
      {
        "astId": 8979,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "arbSys",
        "offset": 0,
        "slot": "28",
        "type": "t_contract(ArbSys)6456"
      },
      {
        "astId": 8981,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "lastHedgeSpotPrice",
        "offset": 0,
        "slot": "29",
        "type": "t_int256"
      },
      {
        "astId": 8983,
        "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
        "label": "perpetualMarket",
        "offset": 0,
        "slot": "30",
        "type": "t_address"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_int256)2_storage": {
        "base": "t_int256",
        "encoding": "inplace",
        "label": "int256[2]",
        "numberOfBytes": "64"
      },
      "t_contract(AggregatorV3Interface)45": {
        "encoding": "inplace",
        "label": "contract AggregatorV3Interface",
        "numberOfBytes": "20"
      },
      "t_contract(ArbSys)6456": {
        "encoding": "inplace",
        "label": "contract ArbSys",
        "numberOfBytes": "20"
      },
      "t_int128": {
        "encoding": "inplace",
        "label": "int128",
        "numberOfBytes": "16"
      },
      "t_int256": {
        "encoding": "inplace",
        "label": "int256",
        "numberOfBytes": "32"
      },
      "t_mapping(t_address,t_mapping(t_address,t_uint256))": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => mapping(address => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_uint256)"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_uint256,t_struct(Info)14816_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => struct SpreadLib.Info)",
        "numberOfBytes": "32",
        "value": "t_struct(Info)14816_storage"
      },
      "t_mapping(t_uint256,t_struct(Pool)8945_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => struct PerpetualMarketCore.Pool)",
        "numberOfBytes": "32",
        "value": "t_struct(Pool)8945_storage"
      },
      "t_string_storage": {
        "encoding": "bytes",
        "label": "string",
        "numberOfBytes": "32"
      },
      "t_struct(Info)13935_storage": {
        "encoding": "inplace",
        "label": "struct NettingLib.Info",
        "members": [
          {
            "astId": 13932,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "amountsUsdc",
            "offset": 0,
            "slot": "0",
            "type": "t_array(t_int256)2_storage"
          },
          {
            "astId": 13934,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "amountUnderlying",
            "offset": 0,
            "slot": "2",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "96"
      },
      "t_struct(Info)14816_storage": {
        "encoding": "inplace",
        "label": "struct SpreadLib.Info",
        "members": [
          {
            "astId": 14805,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "blockLastLongTransaction",
            "offset": 0,
            "slot": "0",
            "type": "t_uint128"
          },
          {
            "astId": 14807,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "minLongTradePrice",
            "offset": 16,
            "slot": "0",
            "type": "t_int128"
          },
          {
            "astId": 14809,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "blockLastShortTransaction",
            "offset": 0,
            "slot": "1",
            "type": "t_uint128"
          },
          {
            "astId": 14811,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "maxShortTradePrice",
            "offset": 16,
            "slot": "1",
            "type": "t_int128"
          },
          {
            "astId": 14813,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "safetyBlockPeriod",
            "offset": 0,
            "slot": "2",
            "type": "t_uint256"
          },
          {
            "astId": 14815,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "numBlocksPerSpreadDecreasing",
            "offset": 0,
            "slot": "3",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "128"
      },
      "t_struct(Pool)8945_storage": {
        "encoding": "inplace",
        "label": "struct PerpetualMarketCore.Pool",
        "members": [
          {
            "astId": 8936,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "amountLockedLiquidity",
            "offset": 0,
            "slot": "0",
            "type": "t_uint128"
          },
          {
            "astId": 8938,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "positionPerpetuals",
            "offset": 16,
            "slot": "0",
            "type": "t_int128"
          },
          {
            "astId": 8940,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "entryPrice",
            "offset": 0,
            "slot": "1",
            "type": "t_uint128"
          },
          {
            "astId": 8942,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "amountFundingPaidPerPosition",
            "offset": 0,
            "slot": "2",
            "type": "t_int256"
          },
          {
            "astId": 8944,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "lastFundingPaymentTime",
            "offset": 0,
            "slot": "3",
            "type": "t_uint128"
          }
        ],
        "numberOfBytes": "128"
      },
      "t_struct(PoolSnapshot)8954_storage": {
        "encoding": "inplace",
        "label": "struct PerpetualMarketCore.PoolSnapshot",
        "members": [
          {
            "astId": 8947,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "futureBaseFundingRate",
            "offset": 0,
            "slot": "0",
            "type": "t_int128"
          },
          {
            "astId": 8949,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "ethVariance",
            "offset": 16,
            "slot": "0",
            "type": "t_int128"
          },
          {
            "astId": 8951,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "ethPrice",
            "offset": 0,
            "slot": "1",
            "type": "t_int128"
          },
          {
            "astId": 8953,
            "contract": "src/PerpetualMarketCore.sol:PerpetualMarketCore",
            "label": "lastSnapshotTime",
            "offset": 16,
            "slot": "1",
            "type": "t_uint128"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint128": {
        "encoding": "inplace",
        "label": "uint128",
        "numberOfBytes": "16"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      },
      "t_uint8": {
        "encoding": "inplace",
        "label": "uint8",
        "numberOfBytes": "1"
      }
    }
  }
}