{
  "address": "0xAdBAeE9665C101413EbFF07e20520bdB67C71AB6",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_perpetualMarketCoreAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_quoteAsset",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_underlyingAsset",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_feeRecepient",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_vaultNFT",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "issued",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "Deposited",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "trader",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "vaultId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "DepositedToVault",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "hedger",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "isBuyingUnderlying",
          "type": "bool"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "usdcAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "underlyingAmount",
          "type": "uint256"
        }
      ],
      "name": "Hedged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "liquidator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "vaultId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "reward",
          "type": "uint256"
        }
      ],
      "name": "Liquidated",
      "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": [],
      "name": "Paused",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "trader",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "vaultId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "subVaultIndex",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "productId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "tradeAmount",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "tradePrice",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "fundingFeePerPosition",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "int256",
          "name": "deltaUsdcPosition",
          "type": "int256"
        },
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "metadata",
          "type": "bytes"
        }
      ],
      "name": "PositionUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "feeRecepient",
          "type": "address"
        }
      ],
      "name": "SetFeeRecepient",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [],
      "name": "UnPaused",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "burned",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "Withdrawn",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "trader",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "vaultId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "WithdrawnFromVault",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        },
        {
          "internalType": "int256",
          "name": "_marginToAdd",
          "type": "int256"
        }
      ],
      "name": "addMargin",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_depositAmount",
          "type": "uint256"
        }
      ],
      "name": "deposit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bool",
          "name": "_withRebalance",
          "type": "bool"
        },
        {
          "internalType": "uint256",
          "name": "_amountUsdc",
          "type": "uint256"
        }
      ],
      "name": "execHedge",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "amountUnderlying",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "feeRecepient",
      "outputs": [
        {
          "internalType": "contract IFeePool",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "int256",
          "name": "_deltaLiquidityAmount",
          "type": "int256"
        }
      ],
      "name": "getLPTokenPrice",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        },
        {
          "internalType": "int128[2]",
          "name": "_tradeAmounts",
          "type": "int128[2]"
        }
      ],
      "name": "getMinCollateralToAddPosition",
      "outputs": [
        {
          "internalType": "int256",
          "name": "minCollateral",
          "type": "int256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        }
      ],
      "name": "getPositionValueAndMinCollateral",
      "outputs": [
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        },
        {
          "internalType": "int256",
          "name": "",
          "type": "int256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getTokenAmountForHedging",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_productId",
          "type": "uint256"
        },
        {
          "internalType": "int256[2]",
          "name": "_tradeAmounts",
          "type": "int256[2]"
        }
      ],
      "name": "getTradePrice",
      "outputs": [
        {
          "components": [
            {
              "internalType": "int256",
              "name": "tradePrice",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "indexPrice",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "fundingRate",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "tradeFee",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "protocolFee",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "fundingFee",
              "type": "int256"
            },
            {
              "internalType": "uint256",
              "name": "totalValue",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "totalFee",
              "type": "uint256"
            }
          ],
          "internalType": "struct IPerpetualMarket.TradeInfo",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        }
      ],
      "name": "getTraderVault",
      "outputs": [
        {
          "components": [
            {
              "internalType": "int128",
              "name": "positionUsdc",
              "type": "int128"
            },
            {
              "components": [
                {
                  "internalType": "int128[2]",
                  "name": "positionPerpetuals",
                  "type": "int128[2]"
                },
                {
                  "internalType": "uint128[2]",
                  "name": "entryPrices",
                  "type": "uint128[2]"
                },
                {
                  "internalType": "int256[2]",
                  "name": "entryFundingFee",
                  "type": "int256[2]"
                }
              ],
              "internalType": "struct TraderVaultLib.SubVault[]",
              "name": "subVaults",
              "type": "tuple[]"
            }
          ],
          "internalType": "struct TraderVaultLib.TraderVault",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        }
      ],
      "name": "getVaultStatus",
      "outputs": [
        {
          "components": [
            {
              "internalType": "int256",
              "name": "positionValue",
              "type": "int256"
            },
            {
              "internalType": "int256",
              "name": "minCollateral",
              "type": "int256"
            },
            {
              "internalType": "int256[2][]",
              "name": "positionValues",
              "type": "int256[2][]"
            },
            {
              "internalType": "int256[2][]",
              "name": "fundingPaid",
              "type": "int256[2][]"
            },
            {
              "components": [
                {
                  "internalType": "int128",
                  "name": "positionUsdc",
                  "type": "int128"
                },
                {
                  "components": [
                    {
                      "internalType": "int128[2]",
                      "name": "positionPerpetuals",
                      "type": "int128[2]"
                    },
                    {
                      "internalType": "uint128[2]",
                      "name": "entryPrices",
                      "type": "uint128[2]"
                    },
                    {
                      "internalType": "int256[2]",
                      "name": "entryFundingFee",
                      "type": "int256[2]"
                    }
                  ],
                  "internalType": "struct TraderVaultLib.SubVault[]",
                  "name": "subVaults",
                  "type": "tuple[]"
                }
              ],
              "internalType": "struct TraderVaultLib.TraderVault",
              "name": "rawVaultData",
              "type": "tuple"
            }
          ],
          "internalType": "struct IPerpetualMarket.VaultStatus",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "hedger",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_depositAmount",
          "type": "uint256"
        },
        {
          "internalType": "int256",
          "name": "_initialFundingRate",
          "type": "int256"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "isSystemPaused",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_vaultId",
          "type": "uint256"
        }
      ],
      "name": "liquidateByPool",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "maxPositionsInVault",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "pause",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "quoteAsset",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_feeRecepient",
          "type": "address"
        }
      ],
      "name": "setFeeRecepient",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_hedger",
          "type": "address"
        }
      ],
      "name": "setHedger",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_maxFutureAmount",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_maxSquaredAmount",
          "type": "uint256"
        }
      ],
      "name": "setMaxAmount",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "vaultId",
              "type": "uint256"
            },
            {
              "components": [
                {
                  "internalType": "uint256",
                  "name": "productId",
                  "type": "uint256"
                },
                {
                  "internalType": "uint256",
                  "name": "subVaultIndex",
                  "type": "uint256"
                },
                {
                  "internalType": "int128",
                  "name": "tradeAmount",
                  "type": "int128"
                },
                {
                  "internalType": "uint256",
                  "name": "limitPrice",
                  "type": "uint256"
                },
                {
                  "internalType": "bytes",
                  "name": "metadata",
                  "type": "bytes"
                }
              ],
              "internalType": "struct IPerpetualMarket.TradeParams[]",
              "name": "trades",
              "type": "tuple[]"
            },
            {
              "internalType": "int256",
              "name": "marginAmount",
              "type": "int256"
            },
            {
              "internalType": "uint256",
              "name": "deadline",
              "type": "uint256"
            }
          ],
          "internalType": "struct IPerpetualMarket.MultiTradeParams",
          "name": "_tradeParams",
          "type": "tuple"
        }
      ],
      "name": "trade",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "unPause",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "underlyingAsset",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint128",
          "name": "_withdrawnAmount",
          "type": "uint128"
        }
      ],
      "name": "withdraw",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0xbff1d41f32474389ce96bddc52644122dfe97197873406ace945d82bb4e7acf6",
  "receipt": {
    "to": null,
    "from": "0x4f071924D66BBC71A5254217893CC7D49938B1c4",
    "contractAddress": "0xAdBAeE9665C101413EbFF07e20520bdB67C71AB6",
    "transactionIndex": 0,
    "gasUsed": "77973078",
    "logsBloom": "0x00000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000100000000000000000400000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000020000000000000000000200000000000000000000000000000000000000000000000",
    "blockHash": "0x6c40b428a7854bcb0e8e779d9493deec7ba21bed14436db70432c8734ca346db",
    "transactionHash": "0xbff1d41f32474389ce96bddc52644122dfe97197873406ace945d82bb4e7acf6",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 14570828,
        "transactionHash": "0xbff1d41f32474389ce96bddc52644122dfe97197873406ace945d82bb4e7acf6",
        "address": "0xAdBAeE9665C101413EbFF07e20520bdB67C71AB6",
        "topics": [
          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x0000000000000000000000004f071924d66bbc71a5254217893cc7d49938b1c4"
        ],
        "data": "0x",
        "logIndex": 0,
        "blockHash": "0x6c40b428a7854bcb0e8e779d9493deec7ba21bed14436db70432c8734ca346db"
      }
    ],
    "blockNumber": 14570828,
    "cumulativeGasUsed": "36634718",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x8B98991EEd7C25280BE5532C3b23a095654868c0",
    "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8",
    "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
    "0xE17B52958aa4a3cEa4202B9893A0C7ae5bDaCEa5",
    "0x175FB4B866070Ab10F20057050Eb84491ff7Fd0c"
  ],
  "solcInputHash": "4053827aa146c622da7f45f0acacb57f",
  "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_perpetualMarketCoreAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_quoteAsset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_underlyingAsset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_feeRecepient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_vaultNFT\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"issued\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"trader\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DepositedToVault\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"hedger\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isBuyingUnderlying\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"usdcAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"underlyingAmount\",\"type\":\"uint256\"}],\"name\":\"Hedged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"Liquidated\",\"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\":[],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"trader\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subVaultIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"productId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"tradeAmount\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tradePrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fundingFeePerPosition\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"deltaUsdcPosition\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"PositionUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"feeRecepient\",\"type\":\"address\"}],\"name\":\"SetFeeRecepient\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"UnPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"burned\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"trader\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawnFromVault\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"_marginToAdd\",\"type\":\"int256\"}],\"name\":\"addMargin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_withRebalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"_amountUsdc\",\"type\":\"uint256\"}],\"name\":\"execHedge\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountUnderlying\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeRecepient\",\"outputs\":[{\"internalType\":\"contract IFeePool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_deltaLiquidityAmount\",\"type\":\"int256\"}],\"name\":\"getLPTokenPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"},{\"internalType\":\"int128[2]\",\"name\":\"_tradeAmounts\",\"type\":\"int128[2]\"}],\"name\":\"getMinCollateralToAddPosition\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"minCollateral\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"}],\"name\":\"getPositionValueAndMinCollateral\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenAmountForHedging\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_productId\",\"type\":\"uint256\"},{\"internalType\":\"int256[2]\",\"name\":\"_tradeAmounts\",\"type\":\"int256[2]\"}],\"name\":\"getTradePrice\",\"outputs\":[{\"components\":[{\"internalType\":\"int256\",\"name\":\"tradePrice\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"indexPrice\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"fundingRate\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"tradeFee\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"protocolFee\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"fundingFee\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"totalValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalFee\",\"type\":\"uint256\"}],\"internalType\":\"struct IPerpetualMarket.TradeInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"}],\"name\":\"getTraderVault\",\"outputs\":[{\"components\":[{\"internalType\":\"int128\",\"name\":\"positionUsdc\",\"type\":\"int128\"},{\"components\":[{\"internalType\":\"int128[2]\",\"name\":\"positionPerpetuals\",\"type\":\"int128[2]\"},{\"internalType\":\"uint128[2]\",\"name\":\"entryPrices\",\"type\":\"uint128[2]\"},{\"internalType\":\"int256[2]\",\"name\":\"entryFundingFee\",\"type\":\"int256[2]\"}],\"internalType\":\"struct TraderVaultLib.SubVault[]\",\"name\":\"subVaults\",\"type\":\"tuple[]\"}],\"internalType\":\"struct TraderVaultLib.TraderVault\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"}],\"name\":\"getVaultStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"int256\",\"name\":\"positionValue\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"minCollateral\",\"type\":\"int256\"},{\"internalType\":\"int256[2][]\",\"name\":\"positionValues\",\"type\":\"int256[2][]\"},{\"internalType\":\"int256[2][]\",\"name\":\"fundingPaid\",\"type\":\"int256[2][]\"},{\"components\":[{\"internalType\":\"int128\",\"name\":\"positionUsdc\",\"type\":\"int128\"},{\"components\":[{\"internalType\":\"int128[2]\",\"name\":\"positionPerpetuals\",\"type\":\"int128[2]\"},{\"internalType\":\"uint128[2]\",\"name\":\"entryPrices\",\"type\":\"uint128[2]\"},{\"internalType\":\"int256[2]\",\"name\":\"entryFundingFee\",\"type\":\"int256[2]\"}],\"internalType\":\"struct TraderVaultLib.SubVault[]\",\"name\":\"subVaults\",\"type\":\"tuple[]\"}],\"internalType\":\"struct TraderVaultLib.TraderVault\",\"name\":\"rawVaultData\",\"type\":\"tuple\"}],\"internalType\":\"struct IPerpetualMarket.VaultStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hedger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"int256\",\"name\":\"_initialFundingRate\",\"type\":\"int256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isSystemPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultId\",\"type\":\"uint256\"}],\"name\":\"liquidateByPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"maxPositionsInVault\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quoteAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_feeRecepient\",\"type\":\"address\"}],\"name\":\"setFeeRecepient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_hedger\",\"type\":\"address\"}],\"name\":\"setHedger\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxFutureAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSquaredAmount\",\"type\":\"uint256\"}],\"name\":\"setMaxAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"vaultId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"productId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"subVaultIndex\",\"type\":\"uint256\"},{\"internalType\":\"int128\",\"name\":\"tradeAmount\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"limitPrice\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"internalType\":\"struct IPerpetualMarket.TradeParams[]\",\"name\":\"trades\",\"type\":\"tuple[]\"},{\"internalType\":\"int256\",\"name\":\"marginAmount\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IPerpetualMarket.MultiTradeParams\",\"name\":\"_tradeParams\",\"type\":\"tuple\"}],\"name\":\"trade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"underlyingAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint128\",\"name\":\"_withdrawnAmount\",\"type\":\"uint128\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addMargin(uint256,int256)\":{\"params\":{\"_marginToAdd\":\"amount of margin to add\",\"_vaultId\":\"id of the vault\"}},\"getLPTokenPrice(int256)\":{\"params\":{\"_deltaLiquidityAmount\":\"difference of liquidity If LPs want LP token price of deposit, _deltaLiquidityAmount is positive number of amount to deposit. On the other hand, if LPs want LP token price of withdrawal, _deltaLiquidityAmount is negative number of amount to withdraw.\"},\"returns\":{\"_0\":\"LP token price scaled by 1e6\"}},\"getMinCollateralToAddPosition(uint256,int128[2])\":{\"params\":{\"_tradeAmounts\":\"amounts to trade\",\"_vaultId\":\"The id of target vault\"},\"returns\":{\"minCollateral\":\"scaled by 1e6\"}},\"getPositionValueAndMinCollateral(uint256)\":{\"params\":{\"_vaultId\":\"The id of target vault\"}},\"getTokenAmountForHedging()\":{\"returns\":{\"_0\":\"Amount of USDC and underlying reqired for hedging\"}},\"getTradePrice(uint256,int256[2])\":{\"params\":{\"_productId\":\"product id\",\"_tradeAmounts\":\"amount of position to trade. positive to get long price and negative to get short price.\"},\"returns\":{\"_0\":\"trade info\"}},\"getVaultStatus(uint256)\":{\"params\":{\"_vaultId\":\"The id of target vault\"},\"returns\":{\"_0\":\"vault status\"}},\"initialize(uint256,int256)\":{\"params\":{\"_depositAmount\":\"deposit amount\",\"_initialFundingRate\":\"initial funding rate\"}},\"liquidateByPool(uint256)\":{\"params\":{\"_vaultId\":\"The id of target vault\"}},\"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.\"},\"setFeeRecepient(address)\":{\"params\":{\"_feeRecepient\":\"The address of new fee recepient\"}},\"setHedger(address)\":{\"params\":{\"_hedger\":\"bot address\"}},\"setMaxAmount(uint256,uint256)\":{\"params\":{\"_maxFutureAmount\":\"max future amount\",\"_maxSquaredAmount\":\"max squared amount\"}},\"trade((uint256,(uint256,uint256,int128,uint256,bytes)[],int256,uint256))\":{\"params\":{\"_tradeParams\":\"trade parameters\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"LIQUIDATION_FEE\":{\"details\":\"liquidation fee is 10%\"},\"hedger\":{\"details\":\"hedger address\"},\"isSystemPaused\":{\"details\":\"is system paused\"},\"maxPositionsInVault\":{\"details\":\"maximum positions in a vault\"}},\"title\":\"Perpetual Market\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addMargin(uint256,int256)\":{\"notice\":\"Add margin to the vault\"},\"constructor\":{\"notice\":\"Constructor of Perpetual Market contract\"},\"deposit(uint256)\":{\"notice\":\"Provides liquidity to the pool and mints LP tokens\"},\"execHedge(bool,uint256)\":{\"notice\":\"Executes hedging\"},\"getLPTokenPrice(int256)\":{\"notice\":\"Gets current LP token price\"},\"getMinCollateralToAddPosition(uint256,int128[2])\":{\"notice\":\"Gets value of min collateral to add positions\"},\"getPositionValueAndMinCollateral(uint256)\":{\"notice\":\"Gets position value and min collateral\"},\"getTokenAmountForHedging()\":{\"notice\":\"Gets token amount for hedging\"},\"getTradePrice(uint256,int256[2])\":{\"notice\":\"Gets trade price\"},\"getVaultStatus(uint256)\":{\"notice\":\"Gets position value of a vault\"},\"initialize(uint256,int256)\":{\"notice\":\"Initializes Perpetual Pool\"},\"liquidateByPool(uint256)\":{\"notice\":\"Liquidates a vault by Pool Anyone can liquidate a vault whose PositionValue is less than MinCollateral. The caller gets a portion of the margin as reward.\"},\"pause()\":{\"notice\":\"pause the contract\"},\"setFeeRecepient(address)\":{\"notice\":\"Sets new fee recepient\"},\"setHedger(address)\":{\"notice\":\"set bot address\"},\"setMaxAmount(uint256,uint256)\":{\"notice\":\"Sets max amounts that a vault can hold\"},\"trade((uint256,(uint256,uint256,int128,uint256,bytes)[],int256,uint256))\":{\"notice\":\"Opens new positions or closes hold position of the perpetual contracts and manage margin in the vault at the same time.\"},\"unPause()\":{\"notice\":\"unpause the contract\"},\"withdraw(uint128)\":{\"notice\":\"Withdraws liquidity from the pool and burn LP tokens\"}},\"notice\":\"Perpetual Market Contract is entry point of traders and liquidity providers. It manages traders' vault storage and holds funds from traders and liquidity providers. Error Codes PM0: tx exceed deadline PM1: limit price PM2: caller is not vault owner PM3: vault not found PM4: caller is not hedger PM5: vault limit PM6: Paused PM7: Not paused PM8: USDC amount is too large PM9: USDC amount is too small\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/PerpetualMarket.sol\":\"PerpetualMarket\"},\"evmVersion\":\"istanbul\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x0000000000000031363535313831393733373438\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd2f30fad5b24c4120f96dbac83aacdb7993ee610a9092bc23c44463da292bf8d\",\"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/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    using SafeMath for uint256;\\n    using Address for address;\\n\\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        // solhint-disable-next-line max-line-length\\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xc77dd6233a82c7c6e3dc49da8f3456baa00ecd3ea4dfa9222002a9aebf155dcd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../../introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n    /**\\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n     */\\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n    /**\\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n     */\\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Returns the number of tokens in ``owner``'s account.\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @dev Returns the owner of the `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n    /**\\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must exist and be owned by `from`.\\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Transfers `tokenId` token from `from` to `to`.\\n     *\\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `to` cannot be the zero address.\\n     * - `tokenId` token must be owned by `from`.\\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n     * The approval is cleared when the token is transferred.\\n     *\\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n     *\\n     * Requirements:\\n     *\\n     * - The caller must own the token or be an approved operator.\\n     * - `tokenId` must exist.\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address to, uint256 tokenId) external;\\n\\n    /**\\n     * @dev Returns the account approved for `tokenId` token.\\n     *\\n     * Requirements:\\n     *\\n     * - `tokenId` must exist.\\n     */\\n    function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n    /**\\n     * @dev Approve or remove `operator` as an operator for the caller.\\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n     *\\n     * Requirements:\\n     *\\n     * - The `operator` cannot be the caller.\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function setApprovalForAll(address operator, bool _approved) external;\\n\\n    /**\\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n     *\\n     * See {setApprovalForAll}\\n     */\\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n    /**\\n      * @dev Safely transfers `tokenId` token from `from` to `to`.\\n      *\\n      * Requirements:\\n      *\\n      * - `from` cannot be the zero address.\\n      * - `to` cannot be the zero address.\\n      * - `tokenId` token must exist and be owned by `from`.\\n      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n      *\\n      * Emits a {Transfer} event.\\n      */\\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0xb11597841d47f7a773bca63ca323c76f804cb5d944788de0327db5526319dc82\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xf89f005a3d98f7768cdee2583707db0ac725cf567d455751af32ee68132f3db3\",\"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\"},\"src/PerpetualMarket.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"./interfaces/IFeePool.sol\\\";\\nimport \\\"./interfaces/IPerpetualMarketCore.sol\\\";\\nimport \\\"./interfaces/IPerpetualMarket.sol\\\";\\nimport \\\"./base/BaseLiquidityPool.sol\\\";\\nimport \\\"./lib/TraderVaultLib.sol\\\";\\nimport \\\"./interfaces/IVaultNFT.sol\\\";\\n\\n/**\\n * @title Perpetual Market\\n * @notice Perpetual Market Contract is entry point of traders and liquidity providers.\\n * It manages traders' vault storage and holds funds from traders and liquidity providers.\\n *\\n * Error Codes\\n * PM0: tx exceed deadline\\n * PM1: limit price\\n * PM2: caller is not vault owner\\n * PM3: vault not found\\n * PM4: caller is not hedger\\n * PM5: vault limit\\n * PM6: Paused\\n * PM7: Not paused\\n * PM8: USDC amount is too large\\n * PM9: USDC amount is too small\\n */\\ncontract PerpetualMarket is IPerpetualMarket, BaseLiquidityPool, Ownable {\\n    using SafeERC20 for IERC20;\\n    using SafeCast for uint256;\\n    using SafeCast for int256;\\n    using SafeMath for uint256;\\n    using SignedSafeMath for int256;\\n    using SignedSafeMath for int128;\\n    using TraderVaultLib for TraderVaultLib.TraderVault;\\n\\n    uint256 private constant MAX_PRODUCT_ID = 2;\\n\\n    /// @dev liquidation fee is 10%\\n    int256 private constant LIQUIDATION_FEE = 1000;\\n\\n    IPerpetualMarketCore private immutable perpetualMarketCore;\\n\\n    /// @dev hedger address\\n    address public hedger;\\n\\n    // Fee recepient address\\n    IFeePool public feeRecepient;\\n\\n    /// @dev maximum positions in a vault\\n    uint256[2] public maxPositionsInVault;\\n\\n    address private vaultNFT;\\n\\n    // trader's vaults storage\\n    mapping(uint256 => TraderVaultLib.TraderVault) private traderVaults;\\n\\n    /// @dev is system paused\\n    bool public isSystemPaused;\\n\\n    event Deposited(address indexed account, uint256 issued, uint256 amount);\\n\\n    event Withdrawn(address indexed account, uint256 burned, uint256 amount);\\n\\n    event PositionUpdated(\\n        address indexed trader,\\n        uint256 vaultId,\\n        uint256 subVaultIndex,\\n        uint256 productId,\\n        int256 tradeAmount,\\n        uint256 tradePrice,\\n        int256 fundingFeePerPosition,\\n        int256 deltaUsdcPosition,\\n        bytes metadata\\n    );\\n    event DepositedToVault(address indexed trader, uint256 vaultId, uint256 amount);\\n    event WithdrawnFromVault(address indexed trader, uint256 vaultId, uint256 amount);\\n    event Liquidated(address liquidator, uint256 indexed vaultId, uint256 reward);\\n\\n    event Hedged(address hedger, bool isBuyingUnderlying, uint256 usdcAmount, uint256 underlyingAmount);\\n\\n    event SetFeeRecepient(address feeRecepient);\\n    event Paused();\\n    event UnPaused();\\n\\n    modifier onlyHedger() {\\n        require(msg.sender == hedger, \\\"PM4\\\");\\n        _;\\n    }\\n\\n    modifier notPaused() {\\n        require(!isSystemPaused, \\\"PM6\\\");\\n        _;\\n    }\\n\\n    modifier isPaused() {\\n        require(isSystemPaused, \\\"PM7\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice Constructor of Perpetual Market contract\\n     */\\n    constructor(\\n        address _perpetualMarketCoreAddress,\\n        address _quoteAsset,\\n        address _underlyingAsset,\\n        address _feeRecepient,\\n        address _vaultNFT\\n    ) BaseLiquidityPool(_quoteAsset, _underlyingAsset) {\\n        require(_feeRecepient != address(0));\\n\\n        hedger = msg.sender;\\n\\n        perpetualMarketCore = IPerpetualMarketCore(_perpetualMarketCoreAddress);\\n        feeRecepient = IFeePool(_feeRecepient);\\n        vaultNFT = _vaultNFT;\\n\\n        maxPositionsInVault[0] = 1000000 * 1e8;\\n        maxPositionsInVault[1] = 1000000 * 1e8;\\n    }\\n\\n    /**\\n     * @notice Initializes Perpetual Pool\\n     * @param _depositAmount deposit amount\\n     * @param _initialFundingRate initial funding rate\\n     */\\n    function initialize(uint256 _depositAmount, int256 _initialFundingRate) external override notPaused {\\n        require(_depositAmount > 0 && _initialFundingRate > 0);\\n\\n        uint256 lpTokenAmount = perpetualMarketCore.initialize(msg.sender, _depositAmount * 1e2, _initialFundingRate);\\n\\n        IERC20(quoteAsset).safeTransferFrom(msg.sender, address(this), _depositAmount);\\n\\n        emit Deposited(msg.sender, lpTokenAmount, _depositAmount);\\n    }\\n\\n    /**\\n     * @notice Provides liquidity to the pool and mints LP tokens\\n     */\\n    function deposit(uint256 _depositAmount) external override notPaused {\\n        require(_depositAmount > 0);\\n\\n        // Funding payment should be proceeded before deposit\\n        perpetualMarketCore.executeFundingPayment();\\n\\n        uint256 lpTokenAmount = perpetualMarketCore.deposit(msg.sender, _depositAmount * 1e2);\\n\\n        IERC20(quoteAsset).safeTransferFrom(msg.sender, address(this), _depositAmount);\\n\\n        emit Deposited(msg.sender, lpTokenAmount, _depositAmount);\\n    }\\n\\n    /**\\n     * @notice Withdraws liquidity from the pool and burn LP tokens\\n     */\\n    function withdraw(uint128 _withdrawnAmount) external override notPaused {\\n        require(_withdrawnAmount > 0);\\n\\n        // Funding payment should be proceeded before withdrawal\\n        perpetualMarketCore.executeFundingPayment();\\n\\n        uint256 lpTokenAmount = perpetualMarketCore.withdraw(msg.sender, _withdrawnAmount * 1e2);\\n\\n        // Send liquidity to msg.sender\\n        sendLiquidity(msg.sender, _withdrawnAmount);\\n\\n        emit Withdrawn(msg.sender, lpTokenAmount, _withdrawnAmount);\\n    }\\n\\n    /**\\n     * @notice Opens new positions or closes hold position of the perpetual contracts\\n     * and manage margin in the vault at the same time.\\n     * @param _tradeParams trade parameters\\n     */\\n    function trade(MultiTradeParams memory _tradeParams) external override notPaused {\\n        // check the transaction not exceed deadline\\n        require(_tradeParams.deadline == 0 || _tradeParams.deadline >= block.number, \\\"PM0\\\");\\n\\n        if (_tradeParams.vaultId == 0) {\\n            // open new vault\\n            _tradeParams.vaultId = IVaultNFT(vaultNFT).mintNFT(msg.sender);\\n        } else {\\n            // check caller is vault owner\\n            require(IVaultNFT(vaultNFT).ownerOf(_tradeParams.vaultId) == msg.sender, \\\"PM2\\\");\\n        }\\n\\n        // funding payment should bee proceeded before trade\\n        perpetualMarketCore.executeFundingPayment();\\n\\n        uint256 totalProtocolFee;\\n\\n        {\\n            uint256[2] memory tradePrices;\\n            int256[2] memory fundingPaidPerPositions;\\n\\n            (tradePrices, fundingPaidPerPositions, totalProtocolFee) = updatePoolPosition(\\n                traderVaults[_tradeParams.vaultId],\\n                getTradeAmounts(_tradeParams.trades),\\n                getLimitPrices(_tradeParams.trades)\\n            );\\n\\n            for (uint256 i = 0; i < _tradeParams.trades.length; i++) {\\n                updateSubVault(\\n                    traderVaults[_tradeParams.vaultId],\\n                    _tradeParams.trades[i].productId,\\n                    _tradeParams.vaultId,\\n                    _tradeParams.trades[i].subVaultIndex,\\n                    tradePrices[_tradeParams.trades[i].productId],\\n                    fundingPaidPerPositions[_tradeParams.trades[i].productId],\\n                    _tradeParams.trades[i].tradeAmount,\\n                    _tradeParams.trades[i].metadata\\n                );\\n            }\\n        }\\n\\n        // Add protocol fee\\n        if (totalProtocolFee > 0) {\\n            IERC20(quoteAsset).approve(address(feeRecepient), totalProtocolFee);\\n            feeRecepient.sendProfitERC20(address(this), totalProtocolFee);\\n        }\\n\\n        int256 finalDepositOrWithdrawAmount;\\n\\n        finalDepositOrWithdrawAmount = traderVaults[_tradeParams.vaultId].updateUsdcPosition(\\n            _tradeParams.marginAmount.mul(1e2),\\n            perpetualMarketCore.getTradePriceInfo(getTradeAmountsToCloseVault(traderVaults[_tradeParams.vaultId]))\\n        );\\n\\n        // Try to update variance after trade\\n        perpetualMarketCore.updatePoolSnapshot();\\n\\n        if (finalDepositOrWithdrawAmount > 0) {\\n            uint256 depositAmount = uint256(finalDepositOrWithdrawAmount / 1e2);\\n            IERC20(quoteAsset).safeTransferFrom(msg.sender, address(this), depositAmount);\\n            emit DepositedToVault(msg.sender, _tradeParams.vaultId, depositAmount);\\n        } else if (finalDepositOrWithdrawAmount < 0) {\\n            uint256 withdrawAmount = uint256(-finalDepositOrWithdrawAmount) / 1e2;\\n            sendLiquidity(msg.sender, withdrawAmount);\\n            emit WithdrawnFromVault(msg.sender, _tradeParams.vaultId, withdrawAmount);\\n        }\\n    }\\n\\n    function getTradeAmounts(TradeParams[] memory _trades) internal pure returns (int256[2] memory tradeAmounts) {\\n        for (uint256 i = 0; i < _trades.length; i++) {\\n            tradeAmounts[_trades[i].productId] = tradeAmounts[_trades[i].productId].add(_trades[i].tradeAmount);\\n        }\\n\\n        return tradeAmounts;\\n    }\\n\\n    function getLimitPrices(TradeParams[] memory _trades) internal pure returns (uint256[2] memory limitPrices) {\\n        for (uint256 i = 0; i < _trades.length; i++) {\\n            limitPrices[_trades[i].productId] = _trades[i].limitPrice;\\n        }\\n\\n        return limitPrices;\\n    }\\n\\n    /**\\n     * @notice Gets trade amounts to close the vault\\n     */\\n    function getTradeAmountsToCloseVault(TraderVaultLib.TraderVault memory _traderVault)\\n        internal\\n        pure\\n        returns (int256[2] memory tradeAmounts)\\n    {\\n        int128[2] memory positionPerpetuals = _traderVault.getPositionPerpetuals();\\n\\n        tradeAmounts[0] = -positionPerpetuals[0];\\n        tradeAmounts[1] = -positionPerpetuals[1];\\n\\n        return tradeAmounts;\\n    }\\n\\n    /**\\n     * @notice Checks vault position limit and reverts if position exceeds limit\\n     */\\n    function checkVaultPositionLimit(TraderVaultLib.TraderVault memory _traderVault, int256[2] memory _tradeAmounts)\\n        internal\\n        view\\n    {\\n        int128[2] memory positionPerpetuals = _traderVault.getPositionPerpetuals();\\n\\n        for (uint256 productId = 0; productId < MAX_PRODUCT_ID; productId++) {\\n            int256 positionAfter = positionPerpetuals[productId].add(_tradeAmounts[productId]);\\n\\n            if (Math.abs(positionAfter) > Math.abs(positionPerpetuals[productId])) {\\n                // if the trader opens new position, check positionAfter is less than max.\\n                require(Math.abs(positionAfter) <= maxPositionsInVault[productId], \\\"PM5\\\");\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice Add margin to the vault\\n     * @param _vaultId id of the vault\\n     * @param _marginToAdd amount of margin to add\\n     */\\n    function addMargin(uint256 _vaultId, int256 _marginToAdd) external override {\\n        require(_vaultId > 0 && _vaultId < IVaultNFT(vaultNFT).nextId(), \\\"PM3\\\");\\n\\n        // increase USDC position\\n        traderVaults[_vaultId].addUsdcPosition(_marginToAdd.mul(1e2));\\n\\n        // receive USDC from caller\\n        uint256 depositAmount = _marginToAdd.toUint256();\\n        IERC20(quoteAsset).safeTransferFrom(msg.sender, address(this), depositAmount);\\n\\n        // emit event\\n        emit DepositedToVault(msg.sender, _vaultId, depositAmount);\\n    }\\n\\n    /**\\n     * @notice Liquidates a vault by Pool\\n     * Anyone can liquidate a vault whose PositionValue is less than MinCollateral.\\n     * The caller gets a portion of the margin as reward.\\n     * @param _vaultId The id of target vault\\n     */\\n    function liquidateByPool(uint256 _vaultId) external override notPaused {\\n        // funding payment should bee proceeded before liquidation\\n        perpetualMarketCore.executeFundingPayment();\\n\\n        TraderVaultLib.TraderVault storage traderVault = traderVaults[_vaultId];\\n\\n        IPerpetualMarketCore.TradePriceInfo memory tradePriceInfo = perpetualMarketCore.getTradePriceInfo(\\n            getTradeAmountsToCloseVault(traderVault)\\n        );\\n\\n        // Check if PositionValue is less than MinCollateral or not\\n        require(traderVault.checkVaultIsDanger(tradePriceInfo), \\\"vault is not danger\\\");\\n\\n        int256 minCollateral = traderVault.getMinCollateral(tradePriceInfo);\\n\\n        require(minCollateral > 0, \\\"vault has no positions\\\");\\n\\n        // Close all positions in the vault\\n        uint256 totalProtocolFee;\\n\\n        {\\n            uint256[2] memory tradePrices;\\n            int256[2] memory fundingPaidPerPositions;\\n\\n            (tradePrices, fundingPaidPerPositions, totalProtocolFee) = updatePoolPosition(\\n                traderVault,\\n                getTradeAmountsToCloseVault(traderVault),\\n                [uint256(0), uint256(0)]\\n            );\\n\\n            for (uint256 subVaultIndex = 0; subVaultIndex < traderVault.subVaults.length; subVaultIndex++) {\\n                for (uint256 productId = 0; productId < MAX_PRODUCT_ID; productId++) {\\n                    int128 amountAssetInVault = traderVault.subVaults[subVaultIndex].positionPerpetuals[productId];\\n\\n                    updateSubVault(\\n                        traderVault,\\n                        productId,\\n                        _vaultId,\\n                        subVaultIndex,\\n                        tradePrices[productId],\\n                        fundingPaidPerPositions[productId],\\n                        -amountAssetInVault,\\n                        \\\"\\\"\\n                    );\\n                }\\n            }\\n        }\\n\\n        uint256 reward = traderVault.decreaseLiquidationReward(minCollateral, LIQUIDATION_FEE);\\n\\n        // Sends a half of reward to the pool\\n        perpetualMarketCore.addLiquidity(reward / 2);\\n\\n        // Sends a half of reward to the liquidator\\n        sendLiquidity(msg.sender, reward / (2 * 1e2));\\n\\n        // Try to update variance after liquidation\\n        perpetualMarketCore.updatePoolSnapshot();\\n\\n        // Sends protocol fee\\n        if (totalProtocolFee > 0) {\\n            IERC20(quoteAsset).approve(address(feeRecepient), totalProtocolFee);\\n            feeRecepient.sendProfitERC20(address(this), totalProtocolFee);\\n        }\\n\\n        emit Liquidated(msg.sender, _vaultId, reward);\\n    }\\n\\n    /**\\n     * @notice Updates pool position.\\n     * It returns trade price and fundingPaidPerPosition for each product, and protocol fee.\\n     */\\n    function updatePoolPosition(\\n        TraderVaultLib.TraderVault memory _traderVault,\\n        int256[2] memory _tradeAmounts,\\n        uint256[2] memory _limitPrices\\n    )\\n        internal\\n        returns (\\n            uint256[2] memory tradePrices,\\n            int256[2] memory fundingPaidPerPositions,\\n            uint256 protocolFee\\n        )\\n    {\\n        checkVaultPositionLimit(_traderVault, _tradeAmounts);\\n\\n        (tradePrices, fundingPaidPerPositions, protocolFee) = perpetualMarketCore.updatePoolPositions(_tradeAmounts);\\n\\n        require(checkPrice(_tradeAmounts[0] > 0, tradePrices[0], _limitPrices[0]), \\\"PM1\\\");\\n        require(checkPrice(_tradeAmounts[1] > 0, tradePrices[1], _limitPrices[1]), \\\"PM1\\\");\\n\\n        protocolFee = protocolFee / 1e2;\\n    }\\n\\n    /**\\n     * @notice Update sub-vault\\n     */\\n    function updateSubVault(\\n        TraderVaultLib.TraderVault storage _traderVault,\\n        uint256 _productId,\\n        uint256 _vaultId,\\n        uint256 _subVaultIndex,\\n        uint256 _tradePrice,\\n        int256 _fundingFeePerPosition,\\n        int128 _tradeAmount,\\n        bytes memory _metadata\\n    ) internal {\\n        if (_tradeAmount == 0) {\\n            return;\\n        }\\n        (int256 deltaUsdcPosition, uint256 lpProfit) = _traderVault.updateVault(\\n            _subVaultIndex,\\n            _productId,\\n            _tradeAmount,\\n            _tradePrice,\\n            _fundingFeePerPosition\\n        );\\n\\n        perpetualMarketCore.addLiquidity(lpProfit);\\n\\n        emit PositionUpdated(\\n            msg.sender,\\n            _vaultId,\\n            _subVaultIndex,\\n            _productId,\\n            _tradeAmount,\\n            _tradePrice,\\n            _fundingFeePerPosition,\\n            deltaUsdcPosition,\\n            _metadata\\n        );\\n    }\\n\\n    /**\\n     * @notice Gets token amount for hedging\\n     * @return Amount of USDC and underlying reqired for hedging\\n     */\\n    function getTokenAmountForHedging()\\n        external\\n        view\\n        override\\n        returns (\\n            bool,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        NettingLib.CompleteParams memory completeParams = perpetualMarketCore.getTokenAmountForHedging();\\n\\n        return (\\n            completeParams.isLong,\\n            completeParams.amountUsdc / 1e2,\\n            Math.scale(completeParams.amountUnderlying, 8, ERC20(underlyingAsset).decimals())\\n        );\\n    }\\n\\n    /**\\n     * @notice Executes hedging\\n     */\\n    function execHedge(bool _withRebalance, uint256 _amountUsdc)\\n        external\\n        override\\n        onlyHedger\\n        returns (uint256 amountUnderlying)\\n    {\\n        // execute funding payment\\n        perpetualMarketCore.executeFundingPayment();\\n\\n        // Try to update variance after funding payment\\n        perpetualMarketCore.updatePoolSnapshot();\\n\\n        if (_withRebalance) {\\n            // rebalance before hedge\\n            perpetualMarketCore.rebalance();\\n        }\\n\\n        NettingLib.CompleteParams memory completeParams = perpetualMarketCore.getTokenAmountForHedging();\\n\\n        if (completeParams.isLong) {\\n            require(completeParams.amountUsdc / 1e2 >= _amountUsdc, \\\"PM8\\\");\\n        } else {\\n            require(completeParams.amountUsdc / 1e2 <= _amountUsdc, \\\"PM9\\\");\\n        }\\n\\n        completeParams.amountUsdc = _amountUsdc.mul(1e2);\\n\\n        perpetualMarketCore.completeHedgingProcedure(completeParams);\\n\\n        if (_withRebalance) {\\n            // rebalance after hedge\\n            perpetualMarketCore.rebalance();\\n        }\\n\\n        amountUnderlying = Math.scale(completeParams.amountUnderlying, 8, ERC20(underlyingAsset).decimals());\\n\\n        if (completeParams.isLong) {\\n            IERC20(underlyingAsset).safeTransferFrom(msg.sender, address(this), amountUnderlying);\\n            sendLiquidity(msg.sender, _amountUsdc);\\n        } else {\\n            IERC20(quoteAsset).safeTransferFrom(msg.sender, address(this), _amountUsdc);\\n            sendUndrlying(msg.sender, amountUnderlying);\\n        }\\n\\n        emit Hedged(msg.sender, completeParams.isLong, _amountUsdc, amountUnderlying);\\n    }\\n\\n    /**\\n     * @notice Compares trade price and limit price\\n     * For long, if trade price is less than limit price then return true.\\n     * For short, if trade price is greater than limit price then return true.\\n     * if limit price is 0 then always return true.\\n     * @param _isLong true if the trade is long and false if the trade is short\\n     * @param _tradePrice trade price per trade amount\\n     * @param _limitPrice the worst price the trader accept\\n     */\\n    function checkPrice(\\n        bool _isLong,\\n        uint256 _tradePrice,\\n        uint256 _limitPrice\\n    ) internal pure returns (bool) {\\n        if (_limitPrice == 0) {\\n            return true;\\n        }\\n        if (_isLong) {\\n            return _tradePrice <= _limitPrice;\\n        } else {\\n            return _tradePrice >= _limitPrice;\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets current LP token price\\n     * @param _deltaLiquidityAmount difference of liquidity\\n     * If LPs want LP token price of deposit, _deltaLiquidityAmount is positive number of amount to deposit.\\n     * On the other hand, if LPs want LP token price of withdrawal, _deltaLiquidityAmount is negative number of amount to withdraw.\\n     * @return LP token price scaled by 1e6\\n     */\\n    function getLPTokenPrice(int256 _deltaLiquidityAmount) external view override returns (uint256) {\\n        return perpetualMarketCore.getLPTokenPrice(_deltaLiquidityAmount);\\n    }\\n\\n    /**\\n     * @notice Gets trade price\\n     * @param _productId product id\\n     * @param _tradeAmounts amount of position to trade. positive to get long price and negative to get short price.\\n     * @return trade info\\n     */\\n    function getTradePrice(uint256 _productId, int256[2] memory _tradeAmounts)\\n        external\\n        view\\n        override\\n        returns (TradeInfo memory)\\n    {\\n        (\\n            int256 tradePrice,\\n            int256 indexPrice,\\n            int256 fundingRate,\\n            int256 tradeFee,\\n            int256 protocolFee\\n        ) = perpetualMarketCore.getTradePrice(_productId, _tradeAmounts);\\n\\n        return\\n            TradeInfo(\\n                tradePrice,\\n                indexPrice,\\n                fundingRate,\\n                tradeFee,\\n                protocolFee,\\n                indexPrice.mul(fundingRate).div(1e16),\\n                tradePrice.toUint256().mul(Math.abs(_tradeAmounts[_productId])).div(1e8),\\n                tradeFee.toUint256().mul(Math.abs(_tradeAmounts[_productId])).div(1e8)\\n            );\\n    }\\n\\n    /**\\n     * @notice Gets value of min collateral to add positions\\n     * @param _vaultId The id of target vault\\n     * @param _tradeAmounts amounts to trade\\n     * @return minCollateral scaled by 1e6\\n     */\\n    function getMinCollateralToAddPosition(uint256 _vaultId, int128[2] memory _tradeAmounts)\\n        external\\n        view\\n        override\\n        returns (int256 minCollateral)\\n    {\\n        TraderVaultLib.TraderVault memory traderVault = traderVaults[_vaultId];\\n\\n        minCollateral = traderVault.getMinCollateralToAddPosition(\\n            _tradeAmounts,\\n            perpetualMarketCore.getTradePriceInfo(getTradeAmountsToCloseVault(traderVault))\\n        );\\n\\n        minCollateral = minCollateral / 1e2;\\n    }\\n\\n    function getTraderVault(uint256 _vaultId) external view override returns (TraderVaultLib.TraderVault memory) {\\n        return traderVaults[_vaultId];\\n    }\\n\\n    /**\\n     * @notice Gets position value and min collateral\\n     * @param _vaultId The id of target vault\\n     */\\n    function getPositionValueAndMinCollateral(uint256 _vaultId) external view returns (int256, int256) {\\n        TraderVaultLib.TraderVault memory traderVault = traderVaults[_vaultId];\\n        IPerpetualMarketCore.TradePriceInfo memory tradePriceInfo = perpetualMarketCore.getTradePriceInfo(\\n            getTradeAmountsToCloseVault(traderVault)\\n        );\\n\\n        return (traderVault.getPositionValue(tradePriceInfo), traderVault.getMinCollateral(tradePriceInfo));\\n    }\\n\\n    /**\\n     * @notice Gets position value of a vault\\n     * @param _vaultId The id of target vault\\n     * @return vault status\\n     */\\n    function getVaultStatus(uint256 _vaultId) external view override returns (VaultStatus memory) {\\n        TraderVaultLib.TraderVault memory traderVault = traderVaults[_vaultId];\\n\\n        IPerpetualMarketCore.TradePriceInfo memory tradePriceInfo = perpetualMarketCore.getTradePriceInfo(\\n            getTradeAmountsToCloseVault(traderVault)\\n        );\\n\\n        int256[2][] memory positionValues = new int256[2][](traderVault.subVaults.length);\\n        int256[2][] memory fundingPaid = new int256[2][](traderVault.subVaults.length);\\n\\n        for (uint256 i = 0; i < traderVault.subVaults.length; i++) {\\n            for (uint256 j = 0; j < MAX_PRODUCT_ID; j++) {\\n                positionValues[i][j] = TraderVaultLib.getPerpetualValueOfSubVault(\\n                    traderVault.subVaults[i],\\n                    j,\\n                    tradePriceInfo\\n                );\\n                fundingPaid[i][j] = TraderVaultLib.getFundingFeePaidOfSubVault(\\n                    traderVault.subVaults[i],\\n                    j,\\n                    tradePriceInfo.amountsFundingPaidPerPosition\\n                );\\n            }\\n        }\\n\\n        return\\n            VaultStatus(\\n                traderVault.getPositionValue(tradePriceInfo),\\n                traderVault.getMinCollateral(tradePriceInfo),\\n                positionValues,\\n                fundingPaid,\\n                traderVault\\n            );\\n    }\\n\\n    /////////////////////////\\n    //  Admin Functions    //\\n    /////////////////////////\\n\\n    /**\\n     * @notice Sets new fee recepient\\n     * @param _feeRecepient The address of new fee recepient\\n     */\\n    function setFeeRecepient(address _feeRecepient) external onlyOwner {\\n        require(_feeRecepient != address(0));\\n        feeRecepient = IFeePool(_feeRecepient);\\n        emit SetFeeRecepient(_feeRecepient);\\n    }\\n\\n    /**\\n     * @notice set bot address\\n     * @param _hedger bot address\\n     */\\n    function setHedger(address _hedger) external onlyOwner {\\n        hedger = _hedger;\\n    }\\n\\n    /**\\n     * @notice Sets max amounts that a vault can hold\\n     * @param _maxFutureAmount max future amount\\n     * @param _maxSquaredAmount max squared amount\\n     */\\n    function setMaxAmount(uint256 _maxFutureAmount, uint256 _maxSquaredAmount) external onlyOwner {\\n        maxPositionsInVault[0] = _maxFutureAmount;\\n        maxPositionsInVault[1] = _maxSquaredAmount;\\n    }\\n\\n    /**\\n     * @notice pause the contract\\n     */\\n    function pause() external onlyOwner notPaused {\\n        isSystemPaused = true;\\n\\n        emit Paused();\\n    }\\n\\n    /**\\n     * @notice unpause the contract\\n     */\\n    function unPause() external onlyOwner isPaused {\\n        isSystemPaused = false;\\n\\n        emit UnPaused();\\n    }\\n}\\n\",\"keccak256\":\"0x4a17d983e8f555b82dc26e419c8d2518f32567b2d579b49dd73b959286054d7b\",\"license\":\"agpl-3.0\"},\"src/base/BaseLiquidityPool.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\n/**\\n * @title Base Liquidity Pool\\n * @notice Base Liquidity Pool Contract\\n */\\nabstract contract BaseLiquidityPool {\\n    using SafeERC20 for IERC20;\\n\\n    address public immutable quoteAsset;\\n    address public immutable underlyingAsset;\\n\\n    /**\\n     * @notice initialize liquidity pool\\n     */\\n    constructor(address _quoteAsset, address _underlyingAsset) {\\n        require(_quoteAsset != address(0));\\n        require(_underlyingAsset != address(0));\\n\\n        quoteAsset = _quoteAsset;\\n        underlyingAsset = _underlyingAsset;\\n    }\\n\\n    function sendLiquidity(address _recipient, uint256 _amount) internal {\\n        IERC20(quoteAsset).safeTransfer(_recipient, _amount);\\n    }\\n\\n    function sendUndrlying(address _recipient, uint256 _amount) internal {\\n        IERC20(underlyingAsset).safeTransfer(_recipient, _amount);\\n    }\\n}\\n\",\"keccak256\":\"0x1638bbb0bb10c0f3caee4397fde0aacce3750b347993e8145bdd8732b678ab93\",\"license\":\"agpl-3.0\"},\"src/interfaces/IFeePool.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\ninterface IFeePool {\\n    function sendProfitERC20(address _account, uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0x9b27b859ab6ce599b9933054e8ac79f2ee7b4ffecf591aac0c03993a6fdd44e5\",\"license\":\"agpl-3.0\"},\"src/interfaces/IPerpetualMarket.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"../lib/TraderVaultLib.sol\\\";\\n\\ninterface IPerpetualMarket {\\n    struct MultiTradeParams {\\n        uint256 vaultId;\\n        TradeParams[] trades;\\n        int256 marginAmount;\\n        uint256 deadline;\\n    }\\n\\n    struct TradeParams {\\n        uint256 productId;\\n        uint256 subVaultIndex;\\n        int128 tradeAmount;\\n        uint256 limitPrice;\\n        bytes metadata;\\n    }\\n\\n    struct VaultStatus {\\n        int256 positionValue;\\n        int256 minCollateral;\\n        int256[2][] positionValues;\\n        int256[2][] fundingPaid;\\n        TraderVaultLib.TraderVault rawVaultData;\\n    }\\n\\n    struct TradeInfo {\\n        int256 tradePrice;\\n        int256 indexPrice;\\n        int256 fundingRate;\\n        int256 tradeFee;\\n        int256 protocolFee;\\n        int256 fundingFee;\\n        uint256 totalValue;\\n        uint256 totalFee;\\n    }\\n\\n    function initialize(uint256 _depositAmount, int256 _initialFundingRate) external;\\n\\n    function deposit(uint256 _depositAmount) external;\\n\\n    function withdraw(uint128 _withdrawnAmount) external;\\n\\n    function trade(MultiTradeParams memory _tradeParams) external;\\n\\n    function addMargin(uint256 _vaultId, int256 _marginToAdd) external;\\n\\n    function liquidateByPool(uint256 _vaultId) external;\\n\\n    function getTokenAmountForHedging()\\n        external\\n        view\\n        returns (\\n            bool,\\n            uint256,\\n            uint256\\n        );\\n\\n    function execHedge(bool _withRebalance, uint256 _amountUsdc) external returns (uint256 amountUnderlying);\\n\\n    function getLPTokenPrice(int256 _deltaLiquidityAmount) external view returns (uint256);\\n\\n    function getTradePrice(uint256 _productId, int256[2] memory _tradeAmounts)\\n        external\\n        view\\n        returns (TradeInfo memory tradePriceInfo);\\n\\n    function getMinCollateralToAddPosition(uint256 _vaultId, int128[2] memory _tradeAmounts)\\n        external\\n        view\\n        returns (int256 minCollateral);\\n\\n    function getTraderVault(uint256 _vaultId) external view returns (TraderVaultLib.TraderVault memory);\\n\\n    function getVaultStatus(uint256 _vaultId) external view returns (VaultStatus memory);\\n}\\n\",\"keccak256\":\"0x15348cd580eb37f61884a575121cdffdc6347674577e39982b58726ba2173ffa\",\"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/interfaces/IVaultNFT.sol\":{\"content\":\"// SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IVaultNFT is IERC721 {\\n    function nextId() external returns (uint256);\\n\\n    function mintNFT(address _recipient) external returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x24579c7330ce36c6115b8767566670ff7ae48f51b773ac3afc105478cd7070f1\",\"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/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/TraderVaultLib.sol\":{\"content\":\"//SPDX-License-Identifier: agpl-3.0\\npragma solidity =0.7.6;\\npragma abicoder v2;\\n\\nimport \\\"@openzeppelin/contracts/utils/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SignedSafeMath.sol\\\";\\nimport \\\"../interfaces/IPerpetualMarketCore.sol\\\";\\nimport \\\"./Math.sol\\\";\\nimport \\\"./EntryPriceMath.sol\\\";\\n\\n/**\\n * @title TraderVaultLib\\n * @notice TraderVaultLib has functions to calculate position value and minimum collateral for implementing cross margin wallet.\\n *\\n * Data Structure\\n *  Vault\\n *  - PositionUSDC\\n *  - SubVault0(PositionPerpetuals, EntryPrices, entryFundingFee)\\n *  - SubVault1(PositionPerpetuals, EntryPrices, entryFundingFee)\\n *  - ...\\n *\\n *  PositionPerpetuals = [PositionSqueeth, PositionFuture]\\n *  EntryPrices = [EntryPriceSqueeth, EntryPriceFuture]\\n *  entryFundingFee = [entryFundingFeeqeeth, FundingFeeEntryValueFuture]\\n *\\n *\\n * Error codes\\n *  T0: PositionValue must be greater than MinCollateral\\n *  T1: PositionValue must be less than MinCollateral\\n *  T2: Vault is insolvent\\n *  T3: subVaultIndex is too large\\n *  T4: position must not be 0\\n *  T5: usdc to add must be positive\\n */\\nlibrary TraderVaultLib {\\n    using SafeCast for int256;\\n    using SafeCast for uint256;\\n    using SafeCast for uint128;\\n    using SafeMath for uint256;\\n    using SignedSafeMath for int256;\\n    using SignedSafeMath for int128;\\n\\n    uint256 private constant MAX_PRODUCT_ID = 2;\\n\\n    /// @dev minimum margin is 200 USDC\\n    uint256 private constant MIN_MARGIN = 200 * 1e8;\\n\\n    /// @dev risk parameter for MinCollateral calculation is 5.0%\\n    uint256 private constant RISK_PARAM_FOR_VAULT = 500;\\n\\n    struct SubVault {\\n        int128[2] positionPerpetuals;\\n        uint128[2] entryPrices;\\n        int256[2] entryFundingFee;\\n    }\\n\\n    struct TraderVault {\\n        int128 positionUsdc;\\n        SubVault[] subVaults;\\n    }\\n\\n    /**\\n     * @notice Gets amount of min collateral to add Squees/Future\\n     * @param _traderVault trader vault object\\n     * @param _tradeAmounts amount to trade\\n     * @param _tradePriceInfo trade price info\\n     * @return minCollateral and positionValue\\n     */\\n    function getMinCollateralToAddPosition(\\n        TraderVault memory _traderVault,\\n        int128[2] memory _tradeAmounts,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256 minCollateral) {\\n        int128[2] memory positionPerpetuals = getPositionPerpetuals(_traderVault);\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            positionPerpetuals[i] = positionPerpetuals[i].add(_tradeAmounts[i]).toInt128();\\n        }\\n\\n        minCollateral = calculateMinCollateral(positionPerpetuals, _tradePriceInfo);\\n    }\\n\\n    /**\\n     * @notice Updates USDC position\\n     * @param _traderVault trader vault object\\n     * @param _usdcPositionToAdd amount to add. if positive then increase amount, if negative then decrease amount.\\n     * @param _tradePriceInfo trade price info\\n     * @return finalUsdcPosition positive means amount of deposited margin\\n     * and negative means amount of withdrawn margin.\\n     */\\n    function updateUsdcPosition(\\n        TraderVault storage _traderVault,\\n        int256 _usdcPositionToAdd,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) external returns (int256 finalUsdcPosition) {\\n        finalUsdcPosition = _usdcPositionToAdd;\\n\\n        int256 positionValue = getPositionValue(_traderVault, _tradePriceInfo);\\n        int256 minCollateral = getMinCollateral(_traderVault, _tradePriceInfo);\\n        int256 maxWithdrawable = positionValue - minCollateral;\\n\\n        // If trader wants to withdraw all USDC, set maxWithdrawable.\\n        if (_usdcPositionToAdd < -maxWithdrawable && maxWithdrawable > 0 && _usdcPositionToAdd < 0) {\\n            finalUsdcPosition = -maxWithdrawable;\\n        }\\n\\n        _traderVault.positionUsdc = _traderVault.positionUsdc.add(finalUsdcPosition).toInt128();\\n\\n        require(!checkVaultIsDanger(_traderVault, _tradePriceInfo), \\\"T0\\\");\\n    }\\n\\n    /**\\n     * @notice Add USDC position\\n     * @param _traderVault trader vault object\\n     * @param _usdcPositionToAdd amount to add. value is always positive.\\n     */\\n    function addUsdcPosition(TraderVault storage _traderVault, int256 _usdcPositionToAdd) external {\\n        require(_usdcPositionToAdd > 0, \\\"T5\\\");\\n\\n        _traderVault.positionUsdc = _traderVault.positionUsdc.add(_usdcPositionToAdd).toInt128();\\n    }\\n\\n    /**\\n     * @notice Gets total position of perpetuals in the vault\\n     * @param _traderVault trader vault object\\n     * @return positionPerpetuals are total amount of perpetual scaled by 1e8\\n     */\\n    function getPositionPerpetuals(TraderVault memory _traderVault)\\n        internal\\n        pure\\n        returns (int128[2] memory positionPerpetuals)\\n    {\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            positionPerpetuals[i] = getPositionPerpetual(_traderVault, i);\\n        }\\n    }\\n\\n    /**\\n     * @notice Gets position of a perpetual in the vault\\n     * @param _traderVault trader vault object\\n     * @param _productId product id\\n     * @return positionPerpetual is amount of perpetual scaled by 1e8\\n     */\\n    function getPositionPerpetual(TraderVault memory _traderVault, uint256 _productId)\\n        internal\\n        pure\\n        returns (int128 positionPerpetual)\\n    {\\n        for (uint256 i = 0; i < _traderVault.subVaults.length; i++) {\\n            positionPerpetual = positionPerpetual\\n                .add(_traderVault.subVaults[i].positionPerpetuals[_productId])\\n                .toInt128();\\n        }\\n    }\\n\\n    /**\\n     * @notice Updates positions in the vault\\n     * @param _traderVault trader vault object\\n     * @param _subVaultIndex index of sub-vault\\n     * @param _productId product id\\n     * @param _positionPerpetual amount of position to increase or decrease\\n     * @param _tradePrice trade price\\n     * @param _fundingFeePerPosition entry funding fee paid per position\\n     */\\n    function updateVault(\\n        TraderVault storage _traderVault,\\n        uint256 _subVaultIndex,\\n        uint256 _productId,\\n        int128 _positionPerpetual,\\n        uint256 _tradePrice,\\n        int256 _fundingFeePerPosition\\n    ) external returns (int256 roundedDeltaUsdcPosition, uint256 lpProfit) {\\n        require(_positionPerpetual != 0, \\\"T4\\\");\\n\\n        if (_traderVault.subVaults.length == _subVaultIndex) {\\n            int128[2] memory positionPerpetuals;\\n            uint128[2] memory entryPrices;\\n            int256[2] memory entryFundingFee;\\n\\n            _traderVault.subVaults.push(SubVault(positionPerpetuals, entryPrices, entryFundingFee));\\n        } else {\\n            require(_traderVault.subVaults.length > _subVaultIndex, \\\"T3\\\");\\n        }\\n\\n        SubVault storage subVault = _traderVault.subVaults[_subVaultIndex];\\n        int256 deltaUsdcPosition;\\n\\n        {\\n            (int256 newEntryPrice, int256 profitValue) = EntryPriceMath.updateEntryPrice(\\n                int256(subVault.entryPrices[_productId]),\\n                subVault.positionPerpetuals[_productId],\\n                int256(_tradePrice),\\n                _positionPerpetual\\n            );\\n\\n            subVault.entryPrices[_productId] = newEntryPrice.toUint256().toUint128();\\n            deltaUsdcPosition = deltaUsdcPosition.add(profitValue);\\n        }\\n\\n        {\\n            (int256 newEntryFundingFee, int256 profitValue) = EntryPriceMath.updateEntryPrice(\\n                int256(subVault.entryFundingFee[_productId]),\\n                subVault.positionPerpetuals[_productId],\\n                _fundingFeePerPosition,\\n                _positionPerpetual\\n            );\\n\\n            subVault.entryFundingFee[_productId] = newEntryFundingFee;\\n            deltaUsdcPosition = deltaUsdcPosition.sub(profitValue.div(1e8));\\n        }\\n\\n        // if deltaUsdcPosition is positive, round down to the second decimal place, if negative round up.\\n        roundedDeltaUsdcPosition = Math.mulDiv(deltaUsdcPosition, 1, 1e6, deltaUsdcPosition < 0).mul(1e6);\\n\\n        if (deltaUsdcPosition > roundedDeltaUsdcPosition) {\\n            lpProfit = deltaUsdcPosition.sub(roundedDeltaUsdcPosition).toUint256();\\n        }\\n\\n        _traderVault.positionUsdc = _traderVault.positionUsdc.add(roundedDeltaUsdcPosition).toInt128();\\n\\n        subVault.positionPerpetuals[_productId] = subVault\\n            .positionPerpetuals[_productId]\\n            .add(_positionPerpetual)\\n            .toInt128();\\n    }\\n\\n    /**\\n     * @notice Checks the vault is danger or not\\n     * if PositionValue is less than MinCollateral return true\\n     * otherwise return false\\n     * @param _traderVault trader vault object\\n     */\\n    function checkVaultIsDanger(\\n        TraderVault memory _traderVault,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (bool) {\\n        int256 positionValue = getPositionValue(_traderVault, _tradePriceInfo);\\n\\n        return positionValue < getMinCollateral(_traderVault, _tradePriceInfo);\\n    }\\n\\n    /**\\n     * @notice Decreases liquidation reward from usdc position\\n     * @param _traderVault trader vault object\\n     * @param _minCollateral min collateral\\n     * @param _liquidationFee liquidation fee rate\\n     */\\n    function decreaseLiquidationReward(\\n        TraderVault storage _traderVault,\\n        int256 _minCollateral,\\n        int256 _liquidationFee\\n    ) external returns (uint256) {\\n        if (_traderVault.positionUsdc <= 0) {\\n            return 0;\\n        }\\n\\n        int256 reward = _minCollateral.mul(_liquidationFee).div(1e4);\\n\\n        // round down to the second decimal place.\\n        reward = reward.div(1e6).mul(1e6);\\n\\n        reward = Math.min(reward, _traderVault.positionUsdc);\\n\\n        // reduce margin\\n        // sub is safe because we know reward is less than positionUsdc\\n        _traderVault.positionUsdc -= reward.toInt128();\\n\\n        return reward.toUint256();\\n    }\\n\\n    /**\\n     * @notice Gets min collateral of the vault\\n     * @param _traderVault trader vault object\\n     * @param _tradePriceInfo trade price info\\n     * @return MinCollateral scaled by 1e8\\n     */\\n    function getMinCollateral(\\n        TraderVault memory _traderVault,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        int128[2] memory assetAmounts = getPositionPerpetuals(_traderVault);\\n\\n        return calculateMinCollateral(assetAmounts, _tradePriceInfo);\\n    }\\n\\n    /**\\n     * @notice Calculates min collateral\\n     * MinCollateral = alpha*S*(|2*S*(1+fundingSqueeth)*PositionSqueeth + (1+fundingFuture)*PositionFuture| + 2*alpha*S*(1+fundingSqueeth)*|PositionSqueeth|)\\n     * where alpha is 0.05\\n     * @param positionPerpetuals amount of perpetual positions\\n     * @param _tradePriceInfo trade price info\\n     * @return MinCollateral scaled by 1e8\\n     */\\n    function calculateMinCollateral(\\n        int128[2] memory positionPerpetuals,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        // priceWithFunding = S*(1+fundingSqueeth)\\n        int256 priceWithFunding = int256(_tradePriceInfo.spotPrice).mul(_tradePriceInfo.fundingRates[1].add(1e16)).div(\\n            1e8\\n        );\\n\\n        uint256 maxDelta = Math.abs(\\n            (priceWithFunding.mul(positionPerpetuals[1]).mul(2).div(1e20)).add(\\n                positionPerpetuals[0].mul(_tradePriceInfo.fundingRates[0].add(1e16)).div(1e16)\\n            )\\n        );\\n\\n        maxDelta = maxDelta.add(\\n            Math.abs(int256(RISK_PARAM_FOR_VAULT).mul(priceWithFunding).mul(2).mul(positionPerpetuals[1]).div(1e24))\\n        );\\n\\n        uint256 minCollateral = (RISK_PARAM_FOR_VAULT.mul(_tradePriceInfo.spotPrice).mul(maxDelta)) / 1e12;\\n\\n        if ((positionPerpetuals[0] != 0 || positionPerpetuals[1] != 0) && minCollateral < MIN_MARGIN) {\\n            minCollateral = MIN_MARGIN;\\n        }\\n\\n        return minCollateral.toInt256();\\n    }\\n\\n    /**\\n     * @notice Gets position value in the vault\\n     * PositionValue = USDC + \\u03a3(ValueOfSubVault_i)\\n     * @param _traderVault trader vault object\\n     * @param _tradePriceInfo trade price info\\n     * @return PositionValue scaled by 1e8\\n     */\\n    function getPositionValue(\\n        TraderVault memory _traderVault,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        int256 value = _traderVault.positionUsdc;\\n\\n        for (uint256 i = 0; i < _traderVault.subVaults.length; i++) {\\n            value = value.add(getSubVaultPositionValue(_traderVault.subVaults[i], _tradePriceInfo));\\n        }\\n\\n        return value;\\n    }\\n\\n    /**\\n     * @notice Gets position value in the sub-vault\\n     * ValueOfSubVault = TotalPerpetualValueOfSubVault + TotalFundingFeePaidOfSubVault\\n     * @param _subVault sub-vault object\\n     * @param _tradePriceInfo trade price info\\n     * @return ValueOfSubVault scaled by 1e8\\n     */\\n    function getSubVaultPositionValue(\\n        SubVault memory _subVault,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        return\\n            getTotalPerpetualValueOfSubVault(_subVault, _tradePriceInfo).add(\\n                getTotalFundingFeePaidOfSubVault(_subVault, _tradePriceInfo.amountsFundingPaidPerPosition)\\n            );\\n    }\\n\\n    /**\\n     * @notice Gets total perpetual value in the sub-vault\\n     * TotalPerpetualValueOfSubVault = \\u03a3(PerpetualValueOfSubVault_i)\\n     * @param _subVault sub-vault object\\n     * @param _tradePriceInfo trade price info\\n     * @return TotalPerpetualValueOfSubVault scaled by 1e8\\n     */\\n    function getTotalPerpetualValueOfSubVault(\\n        SubVault memory _subVault,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        int256 pnl;\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            pnl = pnl.add(getPerpetualValueOfSubVault(_subVault, i, _tradePriceInfo));\\n        }\\n\\n        return pnl;\\n    }\\n\\n    /**\\n     * @notice Gets perpetual value in the sub-vault\\n     * PerpetualValueOfSubVault_i = (TradePrice_i - EntryPrice_i)*Position_i\\n     * @param _subVault sub-vault object\\n     * @param _productId product id\\n     * @param _tradePriceInfo trade price info\\n     * @return PerpetualValueOfSubVault_i scaled by 1e8\\n     */\\n    function getPerpetualValueOfSubVault(\\n        SubVault memory _subVault,\\n        uint256 _productId,\\n        IPerpetualMarketCore.TradePriceInfo memory _tradePriceInfo\\n    ) internal pure returns (int256) {\\n        int256 pnl = _tradePriceInfo.tradePrices[_productId].sub(_subVault.entryPrices[_productId].toInt256()).mul(\\n            _subVault.positionPerpetuals[_productId]\\n        );\\n\\n        return pnl / 1e8;\\n    }\\n\\n    /**\\n     * @notice Gets total funding fee in the sub-vault\\n     * TotalFundingFeePaidOfSubVault = \\u03a3(FundingFeePaidOfSubVault_i)\\n     * @param _subVault sub-vault object\\n     * @param _amountsFundingPaidPerPosition the cumulative funding fee paid by long per position\\n     * @return TotalFundingFeePaidOfSubVault scaled by 1e8\\n     */\\n    function getTotalFundingFeePaidOfSubVault(\\n        SubVault memory _subVault,\\n        int256[2] memory _amountsFundingPaidPerPosition\\n    ) internal pure returns (int256) {\\n        int256 fundingFee;\\n\\n        for (uint256 i = 0; i < MAX_PRODUCT_ID; i++) {\\n            fundingFee = fundingFee.add(getFundingFeePaidOfSubVault(_subVault, i, _amountsFundingPaidPerPosition));\\n        }\\n\\n        return fundingFee;\\n    }\\n\\n    /**\\n     * @notice Gets funding fee in the sub-vault\\n     * FundingFeePaidOfSubVault_i = Position_i*(EntryFundingFee_i - FundingFeeGlobal_i)\\n     * @param _subVault sub-vault object\\n     * @param _productId product id\\n     * @param _amountsFundingPaidPerPosition cumulative funding fee paid by long per position.\\n     * @return FundingFeePaidOfSubVault_i scaled by 1e8\\n     */\\n    function getFundingFeePaidOfSubVault(\\n        SubVault memory _subVault,\\n        uint256 _productId,\\n        int256[2] memory _amountsFundingPaidPerPosition\\n    ) internal pure returns (int256) {\\n        int256 fundingFee = _subVault.entryFundingFee[_productId].sub(_amountsFundingPaidPerPosition[_productId]).mul(\\n            _subVault.positionPerpetuals[_productId]\\n        );\\n\\n        return fundingFee.div(1e16);\\n    }\\n}\\n\",\"keccak256\":\"0x390c1efbddb42545060b7d9aede56187aa59b84b0dc82aa0dc65f09210879be5\",\"license\":\"agpl-3.0\"}},\"version\":1}",
  "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005bc138038062005bc1833981016040819052620000349162000162565b83836001600160a01b0382166200004a57600080fd5b6001600160a01b0381166200005e57600080fd5b6001600160601b0319606092831b8116608052911b1660a05260006200008362000141565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038216620000e157600080fd5b60018054336001600160a01b03199182161790915560609590951b6001600160601b03191660c0526002805486166001600160a01b03938416179055600580549095169116179092555050655af3107a40006003819055600455620001d1565b3390565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080600080600060a086880312156200017a578081fd5b620001858662000145565b9450620001956020870162000145565b9350620001a56040870162000145565b9250620001b56060870162000145565b9150620001c56080870162000145565b90509295509295909350565b60805160601c60a05160601c60c05160601c615901620002c06000398061042952806104b352806106d452806109c05280610c515280610cc45280610d3d5280610db35280610ec35280610f3252806113c652806115c9528061175a52806118a2528061195952806122bf528061234752806125665280612698528061272252806129ad5280612e6b52806130a652806134435280613e4a528061401b525080610fb05280611060528061138a528061180b5280613dcf5250806110a4528061126c52806123db528061260352806127be5280612cf652806131295280613838528061386752506159016000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80637691c4ac116100f9578063c9d48a9611610097578063eea484d811610071578063eea484d8146103a2578063f2fde38b146103c2578063f7b188a5146103d5578063fdf262b7146103dd576101c4565b8063c9d48a9614610369578063d39235731461037c578063dae0f6d91461038f576101c4565b80638da5cb5b116100d35780638da5cb5b1461032857806399be545a14610330578063a0642dfd14610343578063b6b55f2514610356576101c4565b80637691c4ac146102f45780638456cb5914610309578063854ad1b714610311576101c4565b806349ebb77d11610166578063715018a611610140578063715018a6146102b05780637158da7c146102b857806373f3489e146102c05780637481a763146102d3576101c4565b806349ebb77d1461026a578063525df5a11461028a5780636124fa8e1461029d576101c4565b806313b38140116101a257806313b381401461020f5780632188650e1461022f57806324fe71ea1461024257806333a37ffb1461024a576101c4565b806302387a7b146101c957806302755411146101de578063079cff94146101f1575b600080fd5b6101dc6101d7366004614fad565b6103e5565b005b6101dc6101ec366004614bc4565b61059c565b6101f9610620565b6040516102069190615241565b60405180910390f35b61022261021d366004614cdc565b61062f565b6040516102069190615308565b6101dc61023d3660046150cf565b610646565b6101f96106b3565b61025d610258366004615057565b6106c2565b60405161020691906154cb565b61027d610278366004614cdc565b61083e565b60405161020691906155d8565b610222610298366004614cb1565b610c22565b6101dc6102ab3660046150cf565b61111e565b6101dc6112dc565b6101f9611388565b6102226102ce366004614cdc565b6113ac565b6102e66102e1366004614cdc565b61144b565b604051610206929190615311565b6102fc61168c565b60405161020691906152e5565b6101dc611695565b610319611752565b604051610206939291906152f0565b6101f961186e565b6101dc61033e366004614cdc565b61187d565b6101dc6103513660046150cf565b612510565b6101dc610364366004614cdc565b612666565b6101dc610377366004614dd3565b612821565b6101dc61038a366004614bc4565b6131fb565b61022261039d366004614fc9565b6132c6565b6103b56103b0366004614cdc565b6134f9565b6040516102069190615524565b6101dc6103d0366004614bc4565b61367b565b6101dc61377d565b6101f9613836565b60075460ff16156104115760405162461bcd60e51b8152600401610408906153fa565b60405180910390fd5b6000816001600160801b03161161042757600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505060405163f3fef3a360e01b8152600092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063f3fef3a3906104ee903390606487029060040161527b565b602060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190614cf4565b905061055533836001600160801b031661385a565b336001600160a01b03167f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc68284604051610590929190615658565b60405180910390a25050565b6105a4613892565b6001600160a01b03166105b561186e565b6001600160a01b0316146105fe576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b6003816002811061063f57600080fd5b0154905081565b61064e613892565b6001600160a01b031661065f61186e565b6001600160a01b0316146106a8576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600391909155600455565b6002546001600160a01b031681565b6106ca614a2f565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333a37ffb89896040518363ffffffff1660e01b8152600401610720929190615644565b60a06040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190614d0c565b945094509450945094506040518061010001604052808681526020018581526020018481526020018381526020018281526020016107c8662386f26fc100006107c2878961389690919063ffffffff16565b90613946565b81526020016108066305f5e1006108006107f18c8e600281106107e757fe5b60200201516139fe565b6107fa8b613a15565b90613a6c565b90613ac5565b815260200161082e6305f5e1006108006108258c8e600281106107e757fe5b6107fa88613a15565b9052955050505050505b92915050565b610846614a74565b6000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529194929385840193909290879084015b828210156109b2576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116108c7575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116109235750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116109875750505050508152505081526020019060010190610890565b5050505081525050905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e976109f684613b2c565b6040518263ffffffff1660e01b8152600401610a1291906152d7565b60e06040518083038186803b158015610a2a57600080fd5b505afa158015610a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a629190614f3e565b9050600082602001515167ffffffffffffffff81118015610a8257600080fd5b50604051908082528060200260200182016040528015610abc57816020015b610aa9614aa8565b815260200190600190039081610aa15790505b509050600083602001515167ffffffffffffffff81118015610add57600080fd5b50604051908082528060200260200182016040528015610b1757816020015b610b04614aa8565b815260200190600190039081610afc5790505b50905060005b846020015151811015610bdb5760005b6002811015610bd257610b5886602001518381518110610b4957fe5b60200260200101518287613b62565b848381518110610b6457fe5b60200260200101518260028110610b7757fe5b602002018181525050610ba686602001518381518110610b9357fe5b6020026020010151828760600151613bda565b838381518110610bb257fe5b60200260200101518260028110610bc557fe5b6020020152600101610b2d565b50600101610b1d565b506040805160a0810190915280610bf28686613c38565b8152602001610c018686613c8c565b8152602001838152602001828152602001858152509450505050505b919050565b6001546000906001600160a01b03163314610c4f5760405162461bcd60e51b8152600401610408906153c0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610caa57600080fd5b505af1158015610cbe573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d1d57600080fd5b505af1158015610d31573d6000803e3d6000fd5b505050508215610daf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d7c2a1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d9657600080fd5b505af1158015610daa573d6000803e3d6000fd5b505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663854ad1b76040518163ffffffff1660e01b815260040160806040518083038186803b158015610e0a57600080fd5b505afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190614d6e565b9050806060015115610e795780518390606490041015610e745760405162461bcd60e51b8152600401610408906153a3565b610e9f565b80518390606490041115610e9f5760405162461bcd60e51b815260040161040890615481565b610eaa836064613a6c565b815260405163128c113f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063128c113f90610ef890849060040161549e565b600060405180830381600087803b158015610f1257600080fd5b505af1158015610f26573d6000803e3d6000fd5b505050508315610fa4577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d7c2a1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f8b57600080fd5b505af1158015610f9f573d6000803e3d6000fd5b505050505b611047816020015160087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561100757600080fd5b505afa15801561101b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103f91906150f0565b60ff16613cac565b9150806060015115611097576110886001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085613d62565b611092338461385a565b6110d6565b6110cc6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086613d62565b6110d63383613dc2565b7f97ecad77f31756d3d2f581bf1acec77dbdb445bf9b69afff2c62d02d4d2547de338260600151858560405161110f9493929190615255565b60405180910390a15092915050565b6000821180156111b45750600560009054906101000a90046001600160a01b03166001600160a01b03166361b8ce8c6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b19190614cf4565b82105b6111d05760405162461bcd60e51b815260040161040890615417565b600082815260066020526040902073B6a4A36f7E918a084E5bB39475B30b06cB9CEd91906369e2bed090611205846064613896565b6040518363ffffffff1660e01b8152600401611222929190615311565b60006040518083038186803b15801561123a57600080fd5b505af415801561124e573d6000803e3d6000fd5b50505050600061125d82613a15565b90506112946001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084613d62565b336001600160a01b03167ffc3608744ea5805574f007540fe37736bbebd81365de55991f3b17a16295521d84836040516112cf929190615311565b60405180910390a2505050565b6112e4613892565b6001600160a01b03166112f561186e565b6001600160a01b03161461133e576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516339f9a44f60e11b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906373f3489e906113fb908590600401615308565b60206040518083038186803b15801561141357600080fd5b505afa158015611427573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190614cf4565b6000818152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552869586959394938582019390929091879084015b828210156115bb576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116114d0575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f0104928301926001038202915080841161152c5750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116115905750505050508152505081526020019060010190611499565b5050505081525050905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e976115ff84613b2c565b6040518263ffffffff1660e01b815260040161161b91906152d7565b60e06040518083038186803b15801561163357600080fd5b505afa158015611647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166b9190614f3e565b90506116778282613c38565b6116818383613c8c565b935093505050915091565b60075460ff1681565b61169d613892565b6001600160a01b03166116ae61186e565b6001600160a01b0316146116f7576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b60075460ff161561171a5760405162461bcd60e51b8152600401610408906153fa565b6007805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663854ad1b76040518163ffffffff1660e01b815260040160806040518083038186803b1580156117b157600080fd5b505afa1580156117c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e99190614d6e565b9050806060015160648260000151816117fe57fe5b04611862836020015160087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561100757600080fd5b93509350935050909192565b6000546001600160a01b031690565b60075460ff16156118a05760405162461bcd60e51b8152600401610408906153fa565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118fb57600080fd5b505af115801561190f573d6000803e3d6000fd5b5050506000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529296506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694631c2f4e9794611ac1948993858401939091908a9084015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116119c9575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611a255750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611a895750505050508152505081526020019060010190611992565b5050505081525050613b2c565b6040518263ffffffff1660e01b8152600401611add91906152d7565b60e06040518083038186803b158015611af557600080fd5b505afa158015611b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2d9190614f3e565b6040805180820182528454600f90810b810b900b81526001850180548351602082810282018101909552818152949550611ca2948694889381860193909160009084015b82821015611c93576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611ba8575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611c045750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611c685750505050508152505081526020019060010190611b71565b50505091525090919050613df6565b611cbe5760405162461bcd60e51b815260040161040890615376565b6000611e4382846040518060400160405290816000820160009054906101000a9004600f0b600f0b600f0b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611e34576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611d49575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611da55750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611e095750505050508152505081526020019060010190611d12565b50505091525090919050613c8c565b905060008113611e655760405162461bcd60e51b815260040161040890615434565b6000611e6f614aa8565b611e77614aa8565b6040805180820182528754600f90810b810b900b8152600188018054835160208281028201810190955281815261215c948b9381860193909160009084015b82821015611fd8576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611eed575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611f495750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611fad5750505050508152505081526020019060010190611eb6565b505050915250506040805180820182528954600f90810b810b900b815260018a0180548351602082810282018101909552818152612140948d9381860193909160009084015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612055575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116120b15750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612115575050505050815250508152602001906001019061201e565b6040518060400160405280600081526020016000815250613e17565b9450909250905060005b600187015481101561221a5760005b600281101561221157600088600101838154811061218f57fe5b906000526020600020906004020160000182600281106121ab57fe5b600291828204019190066010029054906101000a9004600f0b905061220889838c868987600281106121d957fe5b60200201518988600281106121ea57fe5b60200201518760000360405180602001604052806000815250613f59565b50600101612175565b50600101612166565b505060405163652aa48360e01b81526000915073B6a4A36f7E918a084E5bB39475B30b06cB9CEd919063652aa4839061225d90889087906103e890600401615537565b60206040518083038186803b15801561227557600080fd5b505af4158015612289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ad9190614cf4565b6040516328e32c8560e11b81529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906351c6590a906122ff906002850490600401615308565b600060405180830381600087803b15801561231957600080fd5b505af115801561232d573d6000803e3d6000fd5b505050506123453360c8838161233f57fe5b0461385a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156123a057600080fd5b505af11580156123b4573d6000803e3d6000fd5b5050505060008211156124ce5760025460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b392612416929190911690869060040161529d565b602060405180830381600087803b15801561243057600080fd5b505af1158015612444573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124689190614c95565b506002546040516301acfa2360e51b81526001600160a01b039091169063359f44609061249b903090869060040161529d565b600060405180830381600087803b1580156124b557600080fd5b505af11580156124c9573d6000803e3d6000fd5b505050505b857f09c223cfcd8c93e245f558f5f8de755fc0930fd9bc257441155ef5d54a170e0f338360405161250092919061529d565b60405180910390a2505050505050565b60075460ff16156125335760405162461bcd60e51b8152600401610408906153fa565b6000821180156125435750600081135b61254c57600080fd5b60405163e7dc45d360e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e7dc45d3906125a2903390606488029087906004016152b6565b602060405180830381600087803b1580156125bc57600080fd5b505af11580156125d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f49190614cf4565b905061262b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086613d62565b336001600160a01b03167f73a19dd210f1a7f902193214c0ee91dd35ee5b4d920cba8d519eca65a7b488ca82856040516112cf929190615311565b60075460ff16156126895760405162461bcd60e51b8152600401610408906153fa565b6000811161269657600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156126f157600080fd5b505af1158015612705573d6000803e3d6000fd5b50506040516311f9fbc960e21b8152600092506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691506347e7ef249061275d903390606487029060040161529d565b602060405180830381600087803b15801561277757600080fd5b505af115801561278b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127af9190614cf4565b90506127e66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085613d62565b336001600160a01b03167f73a19dd210f1a7f902193214c0ee91dd35ee5b4d920cba8d519eca65a7b488ca8284604051610590929190615311565b60075460ff16156128445760405162461bcd60e51b8152600401610408906153fa565b60608101511580612859575043816060015110155b6128755760405162461bcd60e51b815260040161040890615359565b8051612904576005546040516354ba0f2760e01b81526001600160a01b03909116906354ba0f27906128ab903390600401615241565b602060405180830381600087803b1580156128c557600080fd5b505af11580156128d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fd9190614cf4565b81526129ab565b60055481516040516331a9108f60e11b815233926001600160a01b031691636352211e916129359190600401615308565b60206040518083038186803b15801561294d57600080fd5b505afa158015612961573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129859190614be0565b6001600160a01b0316146129ab5760405162461bcd60e51b81526004016104089061533c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612a0657600080fd5b505af1158015612a1a573d6000803e3d6000fd5b505050506000612a28614aa8565b612a30614aa8565b83516000908152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552612bc796929593948685019490939084015b82821015612ba0576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612ab5575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411612b115750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612b755750505050508152505081526020019060010190612a7e565b5050505081525050612bb586602001516140de565b612bc28760200151614174565b613e17565b9450909250905060005b846020015151811015612cd257612cca600660008760000151815260200190815260200160002086602001518381518110612c0857fe5b602002602001015160000151876000015188602001518581518110612c2957fe5b602002602001015160200151878a602001518781518110612c4657fe5b60200260200101516000015160028110612c5c57fe5b6020020151878b602001518881518110612c7257fe5b60200260200101516000015160028110612c8857fe5b60200201518b602001518881518110612c9d57fe5b6020026020010151604001518c602001518981518110612cb957fe5b602002602001015160800151613f59565b600101612bd1565b505081159050612de95760025460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b392612d31929190911690859060040161529d565b602060405180830381600087803b158015612d4b57600080fd5b505af1158015612d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d839190614c95565b506002546040516301acfa2360e51b81526001600160a01b039091169063359f446090612db6903090859060040161529d565b600060405180830381600087803b158015612dd057600080fd5b505af1158015612de4573d6000803e3d6000fd5b505050505b81516000908152600660205260408082209084015173B6a4A36f7E918a084E5bB39475B30b06cB9CEd919163e69e266d91612e25906064613896565b86516000908152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001696631c2f4e9796612fc8969495948682019490939092909184015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612edd575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411612f395750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612f9d5750505050508152505081526020019060010190612ea6565b6040518263ffffffff1660e01b8152600401612fe491906152d7565b60e06040518083038186803b158015612ffc57600080fd5b505afa158015613010573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130349190614f3e565b6040518463ffffffff1660e01b81526004016130529392919061554d565b60206040518083038186803b15801561306a57600080fd5b505af415801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a29190614cf4565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156130ff57600080fd5b505af1158015613113573d6000803e3d6000fd5b50505050600081131561319c57606481056131597f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316333084613d62565b835160405133917ffc3608744ea5805574f007540fe37736bbebd81365de55991f3b17a16295521d9161318e91908590615311565b60405180910390a2506131f6565b60008112156131f65760646000829003046131b7338261385a565b835160405133917f41d0e87fb7cc3fb87474e510116fbe22a7658539f639b5de6d9c0bdae606d3eb916131ec91908590615311565b60405180910390a2505b505050565b613203613892565b6001600160a01b031661321461186e565b6001600160a01b03161461325d576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b6001600160a01b03811661327057600080fd5b600280546001600160a01b0319166001600160a01b0383161790556040517fa10652b59c38f986e02273779b46014194b54d90e963da79e87af931cf6a4848906132bb908390615241565b60405180910390a150565b6000828152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552869592948584019390929190879084015b82821015613433576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411613348575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116133a45750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116134085750505050508152505081526020019060010190613311565b505050508152505090506134ed837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e9761347985613b2c565b6040518263ffffffff1660e01b815260040161349591906152d7565b60e06040518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190614f3e565b8391906141d0565b60649005949350505050565b613501614ac6565b6000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529195929486810194939192919084015b8282101561366d576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411613582575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116135de5750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311613642575050505050815250508152602001906001019061354b565b505050915250909392505050565b613683613892565b6001600160a01b031661369461186e565b6001600160a01b0316146136dd576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b6001600160a01b0381166137225760405162461bcd60e51b815260040180806020018281038252602681526020018061575f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b613785613892565b6001600160a01b031661379661186e565b6001600160a01b0316146137df576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b60075460ff166138015760405162461bcd60e51b81526004016104089061531f565b6007805460ff191690556040517f472cf038e2a5f33dbaa68760dbf94ab4e159535e6580c0ac63f8202c7c6c0bb290600090a1565b7f000000000000000000000000000000000000000000000000000000000000000081565b61388e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383614251565b5050565b3390565b6000826138a557506000610838565b826000191480156138b95750600160ff1b82145b156138f55760405162461bcd60e51b815260040180806020018281038252602781526020018061582f6027913960400191505060405180910390fd5b8282028284828161390257fe5b051461393f5760405162461bcd60e51b815260040180806020018281038252602781526020018061582f6027913960400191505060405180910390fd5b9392505050565b60008161399a576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b816000191480156139ae5750600160ff1b83145b156139ea5760405162461bcd60e51b81526004018080602001828103825260218152602001806157cd6021913960400191505060405180910390fd5b60008284816139f557fe5b05949350505050565b600080821215613a115781600003610838565b5090565b600080821215613a11576040805162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f736974697665604482015290519081900360640190fd5b600082613a7b57506000610838565b82820282848281613a8857fe5b041461393f5760405162461bcd60e51b81526004018080602001828103825260218152602001806157ee6021913960400191505060405180910390fd5b6000808211613b1b576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613b2457fe5b049392505050565b613b34614aa8565b6000613b3f836142a3565b80516000908103600f90810b8552602092830151909103900b9083015250919050565b600080613bca85600001518560028110613b7857fe5b6020020151600f0b613bc4613ba988602001518860028110613b9657fe5b60200201516001600160801b03166142e4565b86602001518860028110613bb957fe5b602002015190614328565b90613896565b6305f5e100900595945050505050565b600080613c1c85600001518560028110613bf057fe5b6020020151600f0b613bc4858760028110613c0757fe5b602002015188604001518860028110613bb957fe5b9050613c2f81662386f26fc10000613946565b95945050505050565b8151600090600f0b815b846020015151811015613c8457613c7a613c7386602001518381518110613c6557fe5b60200260200101518661438d565b83906143ac565b9150600101613c42565b509392505050565b600080613c98846142a3565b9050613ca48184614411565b949350505050565b600081831115613d0857604682840310613cf2576040805162461bcd60e51b8152602060048201526002602482015261269960f11b604482015290519081900360640190fd5b613d0184838503600a0a613ac5565b905061393f565b81831015613d5b57604683830310613d4c576040805162461bcd60e51b8152602060048201526002602482015261269960f11b604482015290519081900360640190fd5b613d0184848403600a0a613a6c565b508261393f565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613dbc908590614575565b50505050565b61388e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383614251565b600080613e038484613c38565b9050613e0f8484613c8c565b139392505050565b613e1f614aa8565b613e27614aa8565b6000613e338686614626565b604051630b818e5960e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e06396490613e7f9088906004016152d7565b60a060405180830381600087803b158015613e9957600080fd5b505af1158015613ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ed19190614bfc565b875183519396509194509250613ef49160009182129187905b60200201516146cd565b613f105760405162461bcd60e51b8152600401610408906153dd565b613f2e60008660016020020151138460016020020151866001613eea565b613f4a5760405162461bcd60e51b8152600401610408906153dd565b60648104905093509350939050565b81600f0b60001415613f6a576140d4565b60405163a8ffb3b960e01b8152600090819073B6a4A36f7E918a084E5bB39475B30b06cB9CEd919063a8ffb3b990613fb0908d908b908e908a908d908d906004016155ad565b604080518083038186803b158015613fc757600080fd5b505af4158015613fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fff9190614d4b565b6040516328e32c8560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906351c6590a90614050908490600401615308565b600060405180830381600087803b15801561406a57600080fd5b505af115801561407e573d6000803e3d6000fd5b50505050336001600160a01b03167fbfb264ae14733b7c7f6701d57d6a0dbaf244d34bf5912958835dccf887b4beea89898c888b8b898b6040516140c998979695949392919061566f565b60405180910390a250505b5050505050505050565b6140e6614aa8565b60005b825181101561416e5761413e83828151811061410157fe5b602002602001015160400151600f0b8385848151811061411d57fe5b6020026020010151600001516002811061413357fe5b6020020151906143ac565b8284838151811061414b57fe5b6020026020010151600001516002811061416157fe5b60200201526001016140e9565b50919050565b61417c614aa8565b60005b825181101561416e5782818151811061419457fe5b602002602001015160600151828483815181106141ad57fe5b602002602001015160000151600281106141c357fe5b602002015260010161417f565b6000806141dc856142a3565b905060005b60028110156142465761422361421e8683600281106141fc57fe5b6020020151600f0b84846002811061421057fe5b6020020151600f0b906143ac565b6146f6565b82826002811061422f57fe5b600f92830b90920b602090920201526001016141e1565b50613c2f8184614411565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526131f6908490614575565b6142ab614aa8565b60005b600281101561416e576142c18382614757565b8282600281106142cd57fe5b600f92830b90920b602090920201526001016142ae565b6000600160ff1b8210613a115760405162461bcd60e51b81526004018080602001828103825260288152602001806158566028913960400191505060405180910390fd5b600081830381831280159061433d5750838113155b80614352575060008312801561435257508381135b61393f5760405162461bcd60e51b815260040180806020018281038252602481526020018061587e6024913960400191505060405180910390fd5b600061393f6143a08484606001516147b8565b6143aa85856147df565b905b60008282018183128015906143c15750838112155b806143d657506000831280156143d657508381125b61393f5760405162461bcd60e51b81526004018080602001828103825260218152602001806157ac6021913960400191505060405180910390fd5b60008061444c6305f5e1006107c261443b662386f26fc10000876040015160016002811061413357fe5b86516001600160801b031690613896565b905060006144b76144b261448b662386f26fc100006107c2614480662386f26fc100008a6040015160006002811061413357fe5b8a51600f0b90613896565b6143aa68056bc75e2d631000006107c26002613bc48c600160200201518a90600f0b613896565b6139fe565b90506144f16144ea6144b269d3c21bcecceda10000006107c28960016020020151600f0b613bc46002816101f48b613896565b8290614806565b9050600064e8d4a51000614521836107fa88600001516001600160801b03166101f4613a6c90919063ffffffff16565b8161452857fe5b87519190049150600f0b15158061454557506020860151600f0b15155b801561455557506404a817c80081105b1561456257506404a817c8005b61456b816142e4565b9695505050505050565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148609092919063ffffffff16565b8051909150156131f6578080602001905160208110156145e957600080fd5b50516131f65760405162461bcd60e51b815260040180806020018281038252602a8152602001806158a2602a913960400191505060405180910390fd5b6000614631836142a3565b905060005b6002811015613dbc57600061466184836002811061465057fe5b602002015184846002811061421057fe5b905061467f83836002811061467257fe5b6020020151600f0b6139fe565b614688826139fe565b11156146c4576003826002811061469b57fe5b01546146a6826139fe565b11156146c45760405162461bcd60e51b815260040161040890615464565b50600101614636565b6000816146dc5750600161393f565b83156146ec57508082111561393f565b508082101561393f565b60006f7fffffffffffffffffffffffffffffff19821215801561471c57506001607f1b82125b613a115760405162461bcd60e51b81526004018080602001828103825260278152602001806157856027913960400191505060405180910390fd5b6000805b8360200151518110156147b1576147a761421e8560200151838151811061477e57fe5b602002602001015160000151856002811061479557fe5b6020020151600f85810b91900b6143ac565b915060010161475b565b5092915050565b60008060005b6002811015613c84576147d5613c73868387613bda565b91506001016147be565b60008060005b6002811015613c84576147fc613c73868387613b62565b91506001016147e5565b60008282018381101561393f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6060613ca484846000858561487485614985565b6148c5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106149035780518252601f1990920191602091820191016148e4565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614965576040519150601f19603f3d011682016040523d82523d6000602084013e61496a565b606091505b509150915061497a82828661498b565b979650505050505050565b3b151590565b6060831561499a57508161393f565b8251156149aa5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156149f45781810151838201526020016149dc565b50505050905090810190601f168015614a215780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001614aa3614ac6565b905290565b60405180604001604052806002906020820280368337509192915050565b60408051808201909152600081526060602082015290565b600082601f830112614aee578081fd5b6040516040810181811067ffffffffffffffff82111715614b0b57fe5b8060405250808385604086011115614b21578384fd5b835b6002811015614b42578151835260209283019290910190600101614b23565b509195945050505050565b600082601f830112614b5d578081fd5b813567ffffffffffffffff811115614b7157fe5b614b84601f8201601f19166020016156ff565b818152846020838601011115614b98578283fd5b816020850160208301379081016020019190915292915050565b8035600f81900b8114610c1d57600080fd5b600060208284031215614bd5578081fd5b813561393f81615723565b600060208284031215614bf1578081fd5b815161393f81615723565b600080600060a08486031215614c10578182fd5b84601f850112614c1e578182fd5b6040516040810181811067ffffffffffffffff82111715614c3b57fe5b806040525080856040870188811115614c52578586fd5b855b6002811015614c73578251845260209384019390920191600101614c54565b50839650614c818982614ade565b955050505050608084015190509250925092565b600060208284031215614ca6578081fd5b815161393f8161573b565b60008060408385031215614cc3578182fd5b8235614cce8161573b565b946020939093013593505050565b600060208284031215614ced578081fd5b5035919050565b600060208284031215614d05578081fd5b5051919050565b600080600080600060a08688031215614d23578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b60008060408385031215614d5d578182fd5b505080516020909101519092909150565b600060808284031215614d7f578081fd5b6040516080810181811067ffffffffffffffff82111715614d9c57fe5b80604052508251815260208301516020820152604083015160408201526060830151614dc78161573b565b60608201529392505050565b600060208284031215614de4578081fd5b67ffffffffffffffff8083351115614dfa578182fd5b8235830160808186031215614e0d578283fd5b604051608081018181108482111715614e2257fe5b60405281358152602082013583811115614e3a578485fd5b8201601f81018713614e4a578485fd5b803584811115614e5657fe5b614e646020808302016156ff565b818152602080820191908401885b84811015614f15578135860160a0818e03601f19011215614e91578a8bfd5b60405160a081018181108c82111715614ea657fe5b80604052506020820135815260408201356020820152614ec860608301614bb2565b6040820152608082013560608201528a60a08301351115614ee7578b8cfd5b614efa8e602060a0850135850101614b4d565b60808201528552506020938401939190910190600101614e72565b505060208501525050506040828101359082015260609182013591810191909152949350505050565b600060e08284031215614f4f578081fd5b6040516080810181811067ffffffffffffffff82111715614f6c57fe5b6040528251614f7a81615749565b8152614f898460208501614ade565b6020820152614f9b8460608501614ade565b6040820152614dc78460a08501614ade565b600060208284031215614fbe578081fd5b813561393f81615749565b60008060608385031215614fdb578182fd5b82359150602084603f850112614fef578182fd5b6040516040810181811067ffffffffffffffff8211171561500c57fe5b6040528085830160608701881015615022578485fd5b845b60028110156150485761503682614bb2565b83529184019190840190600101615024565b50505080925050509250929050565b60008060608385031215615069578182fd5b82359150602084603f85011261507d578182fd5b6040516040810181811067ffffffffffffffff8211171561509a57fe5b60405280858301606087018810156150b0578485fd5b845b6002811015615048578135835291840191908401906001016150b2565b600080604083850312156150e1578182fd5b50508035926020909101359150565b600060208284031215615101578081fd5b815160ff8116811461393f578182fd5b6000815180845260208085019450808401835b8381101561514a57615137878351615155565b6040969096019590820190600101615124565b509495945050505050565b8060005b6002811015613dbc578151845260209384019390910190600101615159565b600060408084018351600f81810b87526020915081860151848389015283815180865260608a01915084830195508792505b808310156152345785518051838a5b60028110156151d8578251880b825291880191908801906001016151b9565b505050858101518884018a5b600281101561520a5782516001600160801b0316825291880191908801906001016151e4565b50505087015161521d6080840182615155565b5060c08201915084860195506001830192506151aa565b5098975050505050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0394909416845291151560208401526040830152606082015260800190565b6001600160a01b039290921682526001600160801b0316602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b604081016108388284615155565b901515815260200190565b92151583526020830191909152604082015260600190565b90815260200190565b918252602082015260400190565b602080825260039082015262504d3760e81b604082015260600190565b60208082526003908201526228269960e91b604082015260600190565b6020808252600390820152620504d360ec1b604082015260600190565b6020808252601390820152723b30bab63a1034b9903737ba103230b733b2b960691b604082015260600190565b6020808252600390820152620a09a760eb1b604082015260600190565b60208082526003908201526214134d60ea1b604082015260600190565b602080825260039082015262504d3160e81b604082015260600190565b60208082526003908201526228269b60e91b604082015260600190565b602080825260039082015262504d3360e81b604082015260600190565b6020808252601690820152757661756c7420686173206e6f20706f736974696f6e7360501b604082015260600190565b602080825260039082015262504d3560e81b604082015260600190565b602080825260039082015262504d3960e81b604082015260600190565b81518152602080830151908201526040808301519082015260609182015115159181019190915260800190565b600061010082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b60006020825261393f6020830184615178565b9283526020830191909152604082015260600190565b838152602080820184905282516001600160801b0316604083015282015161012082019061557e6060840182615155565b50604083015161559160a0840182615155565b5060608301516155a460e0840182615155565b50949350505050565b95865260208601949094526040850192909252600f0b6060840152608083015260a082015260c00190565b6000602082528251602083015260208301516040830152604083015160a0606084015261560860c0840182615111565b90506060840151601f19808584030160808601526156268383615111565b925060808601519150808584030160a086015250613c2f8282615178565b8281526060810161393f6020830184615155565b9182526001600160801b0316602082015260400190565b60006101008a835260208a8185015289604085015288600f0b60608501528760808501528660a08501528560c08501528160e0850152845180838601528392505b808310156156cf578583018201518584016101200152918101916156b0565b808311156156e1578361012082870101525b601f01601f191693909301610120019b9a5050505050505050505050565b60405181810167ffffffffffffffff8111828210171561571b57fe5b604052919050565b6001600160a01b038116811461573857600080fd5b50565b801515811461573857600080fd5b6001600160801b038116811461573857600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f775369676e6564536166654d6174683a206469766973696f6e206f766572666c6f77536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220d6956d2e92f4a6999df6a3cb297a31c749d6f0661f14e074a9de4774b7d3c7a164736f6c63430007060033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80637691c4ac116100f9578063c9d48a9611610097578063eea484d811610071578063eea484d8146103a2578063f2fde38b146103c2578063f7b188a5146103d5578063fdf262b7146103dd576101c4565b8063c9d48a9614610369578063d39235731461037c578063dae0f6d91461038f576101c4565b80638da5cb5b116100d35780638da5cb5b1461032857806399be545a14610330578063a0642dfd14610343578063b6b55f2514610356576101c4565b80637691c4ac146102f45780638456cb5914610309578063854ad1b714610311576101c4565b806349ebb77d11610166578063715018a611610140578063715018a6146102b05780637158da7c146102b857806373f3489e146102c05780637481a763146102d3576101c4565b806349ebb77d1461026a578063525df5a11461028a5780636124fa8e1461029d576101c4565b806313b38140116101a257806313b381401461020f5780632188650e1461022f57806324fe71ea1461024257806333a37ffb1461024a576101c4565b806302387a7b146101c957806302755411146101de578063079cff94146101f1575b600080fd5b6101dc6101d7366004614fad565b6103e5565b005b6101dc6101ec366004614bc4565b61059c565b6101f9610620565b6040516102069190615241565b60405180910390f35b61022261021d366004614cdc565b61062f565b6040516102069190615308565b6101dc61023d3660046150cf565b610646565b6101f96106b3565b61025d610258366004615057565b6106c2565b60405161020691906154cb565b61027d610278366004614cdc565b61083e565b60405161020691906155d8565b610222610298366004614cb1565b610c22565b6101dc6102ab3660046150cf565b61111e565b6101dc6112dc565b6101f9611388565b6102226102ce366004614cdc565b6113ac565b6102e66102e1366004614cdc565b61144b565b604051610206929190615311565b6102fc61168c565b60405161020691906152e5565b6101dc611695565b610319611752565b604051610206939291906152f0565b6101f961186e565b6101dc61033e366004614cdc565b61187d565b6101dc6103513660046150cf565b612510565b6101dc610364366004614cdc565b612666565b6101dc610377366004614dd3565b612821565b6101dc61038a366004614bc4565b6131fb565b61022261039d366004614fc9565b6132c6565b6103b56103b0366004614cdc565b6134f9565b6040516102069190615524565b6101dc6103d0366004614bc4565b61367b565b6101dc61377d565b6101f9613836565b60075460ff16156104115760405162461bcd60e51b8152600401610408906153fa565b60405180910390fd5b6000816001600160801b03161161042757600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561048257600080fd5b505af1158015610496573d6000803e3d6000fd5b505060405163f3fef3a360e01b8152600092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063f3fef3a3906104ee903390606487029060040161527b565b602060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190614cf4565b905061055533836001600160801b031661385a565b336001600160a01b03167f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc68284604051610590929190615658565b60405180910390a25050565b6105a4613892565b6001600160a01b03166105b561186e565b6001600160a01b0316146105fe576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b6003816002811061063f57600080fd5b0154905081565b61064e613892565b6001600160a01b031661065f61186e565b6001600160a01b0316146106a8576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600391909155600455565b6002546001600160a01b031681565b6106ca614a2f565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333a37ffb89896040518363ffffffff1660e01b8152600401610720929190615644565b60a06040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190614d0c565b945094509450945094506040518061010001604052808681526020018581526020018481526020018381526020018281526020016107c8662386f26fc100006107c2878961389690919063ffffffff16565b90613946565b81526020016108066305f5e1006108006107f18c8e600281106107e757fe5b60200201516139fe565b6107fa8b613a15565b90613a6c565b90613ac5565b815260200161082e6305f5e1006108006108258c8e600281106107e757fe5b6107fa88613a15565b9052955050505050505b92915050565b610846614a74565b6000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529194929385840193909290879084015b828210156109b2576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116108c7575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116109235750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116109875750505050508152505081526020019060010190610890565b5050505081525050905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e976109f684613b2c565b6040518263ffffffff1660e01b8152600401610a1291906152d7565b60e06040518083038186803b158015610a2a57600080fd5b505afa158015610a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a629190614f3e565b9050600082602001515167ffffffffffffffff81118015610a8257600080fd5b50604051908082528060200260200182016040528015610abc57816020015b610aa9614aa8565b815260200190600190039081610aa15790505b509050600083602001515167ffffffffffffffff81118015610add57600080fd5b50604051908082528060200260200182016040528015610b1757816020015b610b04614aa8565b815260200190600190039081610afc5790505b50905060005b846020015151811015610bdb5760005b6002811015610bd257610b5886602001518381518110610b4957fe5b60200260200101518287613b62565b848381518110610b6457fe5b60200260200101518260028110610b7757fe5b602002018181525050610ba686602001518381518110610b9357fe5b6020026020010151828760600151613bda565b838381518110610bb257fe5b60200260200101518260028110610bc557fe5b6020020152600101610b2d565b50600101610b1d565b506040805160a0810190915280610bf28686613c38565b8152602001610c018686613c8c565b8152602001838152602001828152602001858152509450505050505b919050565b6001546000906001600160a01b03163314610c4f5760405162461bcd60e51b8152600401610408906153c0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610caa57600080fd5b505af1158015610cbe573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d1d57600080fd5b505af1158015610d31573d6000803e3d6000fd5b505050508215610daf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d7c2a1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d9657600080fd5b505af1158015610daa573d6000803e3d6000fd5b505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663854ad1b76040518163ffffffff1660e01b815260040160806040518083038186803b158015610e0a57600080fd5b505afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190614d6e565b9050806060015115610e795780518390606490041015610e745760405162461bcd60e51b8152600401610408906153a3565b610e9f565b80518390606490041115610e9f5760405162461bcd60e51b815260040161040890615481565b610eaa836064613a6c565b815260405163128c113f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063128c113f90610ef890849060040161549e565b600060405180830381600087803b158015610f1257600080fd5b505af1158015610f26573d6000803e3d6000fd5b505050508315610fa4577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d7c2a1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f8b57600080fd5b505af1158015610f9f573d6000803e3d6000fd5b505050505b611047816020015160087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561100757600080fd5b505afa15801561101b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103f91906150f0565b60ff16613cac565b9150806060015115611097576110886001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085613d62565b611092338461385a565b6110d6565b6110cc6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086613d62565b6110d63383613dc2565b7f97ecad77f31756d3d2f581bf1acec77dbdb445bf9b69afff2c62d02d4d2547de338260600151858560405161110f9493929190615255565b60405180910390a15092915050565b6000821180156111b45750600560009054906101000a90046001600160a01b03166001600160a01b03166361b8ce8c6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b19190614cf4565b82105b6111d05760405162461bcd60e51b815260040161040890615417565b600082815260066020526040902073__$d529c113b49f05715913138dde996bfccf$__906369e2bed090611205846064613896565b6040518363ffffffff1660e01b8152600401611222929190615311565b60006040518083038186803b15801561123a57600080fd5b505af415801561124e573d6000803e3d6000fd5b50505050600061125d82613a15565b90506112946001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084613d62565b336001600160a01b03167ffc3608744ea5805574f007540fe37736bbebd81365de55991f3b17a16295521d84836040516112cf929190615311565b60405180910390a2505050565b6112e4613892565b6001600160a01b03166112f561186e565b6001600160a01b03161461133e576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516339f9a44f60e11b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906373f3489e906113fb908590600401615308565b60206040518083038186803b15801561141357600080fd5b505afa158015611427573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190614cf4565b6000818152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552869586959394938582019390929091879084015b828210156115bb576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116114d0575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f0104928301926001038202915080841161152c5750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116115905750505050508152505081526020019060010190611499565b5050505081525050905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e976115ff84613b2c565b6040518263ffffffff1660e01b815260040161161b91906152d7565b60e06040518083038186803b15801561163357600080fd5b505afa158015611647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166b9190614f3e565b90506116778282613c38565b6116818383613c8c565b935093505050915091565b60075460ff1681565b61169d613892565b6001600160a01b03166116ae61186e565b6001600160a01b0316146116f7576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b60075460ff161561171a5760405162461bcd60e51b8152600401610408906153fa565b6007805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663854ad1b76040518163ffffffff1660e01b815260040160806040518083038186803b1580156117b157600080fd5b505afa1580156117c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e99190614d6e565b9050806060015160648260000151816117fe57fe5b04611862836020015160087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561100757600080fd5b93509350935050909192565b6000546001600160a01b031690565b60075460ff16156118a05760405162461bcd60e51b8152600401610408906153fa565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156118fb57600080fd5b505af115801561190f573d6000803e3d6000fd5b5050506000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529296506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694631c2f4e9794611ac1948993858401939091908a9084015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f010492830192600103820291508084116119c9575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611a255750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611a895750505050508152505081526020019060010190611992565b5050505081525050613b2c565b6040518263ffffffff1660e01b8152600401611add91906152d7565b60e06040518083038186803b158015611af557600080fd5b505afa158015611b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2d9190614f3e565b6040805180820182528454600f90810b810b900b81526001850180548351602082810282018101909552818152949550611ca2948694889381860193909160009084015b82821015611c93576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611ba8575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611c045750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611c685750505050508152505081526020019060010190611b71565b50505091525090919050613df6565b611cbe5760405162461bcd60e51b815260040161040890615376565b6000611e4382846040518060400160405290816000820160009054906101000a9004600f0b600f0b600f0b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611e34576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611d49575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611da55750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611e095750505050508152505081526020019060010190611d12565b50505091525090919050613c8c565b905060008113611e655760405162461bcd60e51b815260040161040890615434565b6000611e6f614aa8565b611e77614aa8565b6040805180820182528754600f90810b810b900b8152600188018054835160208281028201810190955281815261215c948b9381860193909160009084015b82821015611fd8576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411611eed575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611f495750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311611fad5750505050508152505081526020019060010190611eb6565b505050915250506040805180820182528954600f90810b810b900b815260018a0180548351602082810282018101909552818152612140948d9381860193909160009084015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612055575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116120b15750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612115575050505050815250508152602001906001019061201e565b6040518060400160405280600081526020016000815250613e17565b9450909250905060005b600187015481101561221a5760005b600281101561221157600088600101838154811061218f57fe5b906000526020600020906004020160000182600281106121ab57fe5b600291828204019190066010029054906101000a9004600f0b905061220889838c868987600281106121d957fe5b60200201518988600281106121ea57fe5b60200201518760000360405180602001604052806000815250613f59565b50600101612175565b50600101612166565b505060405163652aa48360e01b81526000915073__$d529c113b49f05715913138dde996bfccf$__9063652aa4839061225d90889087906103e890600401615537565b60206040518083038186803b15801561227557600080fd5b505af4158015612289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ad9190614cf4565b6040516328e32c8560e11b81529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906351c6590a906122ff906002850490600401615308565b600060405180830381600087803b15801561231957600080fd5b505af115801561232d573d6000803e3d6000fd5b505050506123453360c8838161233f57fe5b0461385a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156123a057600080fd5b505af11580156123b4573d6000803e3d6000fd5b5050505060008211156124ce5760025460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b392612416929190911690869060040161529d565b602060405180830381600087803b15801561243057600080fd5b505af1158015612444573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124689190614c95565b506002546040516301acfa2360e51b81526001600160a01b039091169063359f44609061249b903090869060040161529d565b600060405180830381600087803b1580156124b557600080fd5b505af11580156124c9573d6000803e3d6000fd5b505050505b857f09c223cfcd8c93e245f558f5f8de755fc0930fd9bc257441155ef5d54a170e0f338360405161250092919061529d565b60405180910390a2505050505050565b60075460ff16156125335760405162461bcd60e51b8152600401610408906153fa565b6000821180156125435750600081135b61254c57600080fd5b60405163e7dc45d360e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e7dc45d3906125a2903390606488029087906004016152b6565b602060405180830381600087803b1580156125bc57600080fd5b505af11580156125d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f49190614cf4565b905061262b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086613d62565b336001600160a01b03167f73a19dd210f1a7f902193214c0ee91dd35ee5b4d920cba8d519eca65a7b488ca82856040516112cf929190615311565b60075460ff16156126895760405162461bcd60e51b8152600401610408906153fa565b6000811161269657600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156126f157600080fd5b505af1158015612705573d6000803e3d6000fd5b50506040516311f9fbc960e21b8152600092506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691506347e7ef249061275d903390606487029060040161529d565b602060405180830381600087803b15801561277757600080fd5b505af115801561278b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127af9190614cf4565b90506127e66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085613d62565b336001600160a01b03167f73a19dd210f1a7f902193214c0ee91dd35ee5b4d920cba8d519eca65a7b488ca8284604051610590929190615311565b60075460ff16156128445760405162461bcd60e51b8152600401610408906153fa565b60608101511580612859575043816060015110155b6128755760405162461bcd60e51b815260040161040890615359565b8051612904576005546040516354ba0f2760e01b81526001600160a01b03909116906354ba0f27906128ab903390600401615241565b602060405180830381600087803b1580156128c557600080fd5b505af11580156128d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fd9190614cf4565b81526129ab565b60055481516040516331a9108f60e11b815233926001600160a01b031691636352211e916129359190600401615308565b60206040518083038186803b15801561294d57600080fd5b505afa158015612961573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129859190614be0565b6001600160a01b0316146129ab5760405162461bcd60e51b81526004016104089061533c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637d8c26596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612a0657600080fd5b505af1158015612a1a573d6000803e3d6000fd5b505050506000612a28614aa8565b612a30614aa8565b83516000908152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552612bc796929593948685019490939084015b82821015612ba0576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612ab5575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411612b115750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612b755750505050508152505081526020019060010190612a7e565b5050505081525050612bb586602001516140de565b612bc28760200151614174565b613e17565b9450909250905060005b846020015151811015612cd257612cca600660008760000151815260200190815260200160002086602001518381518110612c0857fe5b602002602001015160000151876000015188602001518581518110612c2957fe5b602002602001015160200151878a602001518781518110612c4657fe5b60200260200101516000015160028110612c5c57fe5b6020020151878b602001518881518110612c7257fe5b60200260200101516000015160028110612c8857fe5b60200201518b602001518881518110612c9d57fe5b6020026020010151604001518c602001518981518110612cb957fe5b602002602001015160800151613f59565b600101612bd1565b505081159050612de95760025460405163095ea7b360e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263095ea7b392612d31929190911690859060040161529d565b602060405180830381600087803b158015612d4b57600080fd5b505af1158015612d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d839190614c95565b506002546040516301acfa2360e51b81526001600160a01b039091169063359f446090612db6903090859060040161529d565b600060405180830381600087803b158015612dd057600080fd5b505af1158015612de4573d6000803e3d6000fd5b505050505b81516000908152600660205260408082209084015173__$d529c113b49f05715913138dde996bfccf$__9163e69e266d91612e25906064613896565b86516000908152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001696631c2f4e9796612fc8969495948682019490939092909184015b82821015611ab4576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411612edd575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411612f395750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311612f9d5750505050508152505081526020019060010190612ea6565b6040518263ffffffff1660e01b8152600401612fe491906152d7565b60e06040518083038186803b158015612ffc57600080fd5b505afa158015613010573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130349190614f3e565b6040518463ffffffff1660e01b81526004016130529392919061554d565b60206040518083038186803b15801561306a57600080fd5b505af415801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a29190614cf4565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387c3a09a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156130ff57600080fd5b505af1158015613113573d6000803e3d6000fd5b50505050600081131561319c57606481056131597f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316333084613d62565b835160405133917ffc3608744ea5805574f007540fe37736bbebd81365de55991f3b17a16295521d9161318e91908590615311565b60405180910390a2506131f6565b60008112156131f65760646000829003046131b7338261385a565b835160405133917f41d0e87fb7cc3fb87474e510116fbe22a7658539f639b5de6d9c0bdae606d3eb916131ec91908590615311565b60405180910390a2505b505050565b613203613892565b6001600160a01b031661321461186e565b6001600160a01b03161461325d576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b6001600160a01b03811661327057600080fd5b600280546001600160a01b0319166001600160a01b0383161790556040517fa10652b59c38f986e02273779b46014194b54d90e963da79e87af931cf6a4848906132bb908390615241565b60405180910390a150565b6000828152600660209081526040808320815180830183528154600f90810b810b900b8152600182018054845181870281018701909552808552869592948584019390929190879084015b82821015613433576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411613348575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116133a45750505092845250506040805180820191829052602090930192915060028481019182845b8154815260200190600101908083116134085750505050508152505081526020019060010190613311565b505050508152505090506134ed837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631c2f4e9761347985613b2c565b6040518263ffffffff1660e01b815260040161349591906152d7565b60e06040518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190614f3e565b8391906141d0565b60649005949350505050565b613501614ac6565b6000828152600660209081526040808320815180830183528154600f90810b810b900b81526001820180548451818702810187019095528085529195929486810194939192919084015b8282101561366d576000848152602090206040805160a0810190915290600484020181606081018260028282826020028201916000905b82829054906101000a9004600f0b600f0b81526020019060100190602082600f01049283019260010382029150808411613582575050509284525050604080518082019182905260209093019291506001840190600290826000855b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116135de5750505092845250506040805180820191829052602090930192915060028481019182845b815481526020019060010190808311613642575050505050815250508152602001906001019061354b565b505050915250909392505050565b613683613892565b6001600160a01b031661369461186e565b6001600160a01b0316146136dd576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b6001600160a01b0381166137225760405162461bcd60e51b815260040180806020018281038252602681526020018061575f6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b613785613892565b6001600160a01b031661379661186e565b6001600160a01b0316146137df576040805162461bcd60e51b8152602060048201819052602482015260008051602061580f833981519152604482015290519081900360640190fd5b60075460ff166138015760405162461bcd60e51b81526004016104089061531f565b6007805460ff191690556040517f472cf038e2a5f33dbaa68760dbf94ab4e159535e6580c0ac63f8202c7c6c0bb290600090a1565b7f000000000000000000000000000000000000000000000000000000000000000081565b61388e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383614251565b5050565b3390565b6000826138a557506000610838565b826000191480156138b95750600160ff1b82145b156138f55760405162461bcd60e51b815260040180806020018281038252602781526020018061582f6027913960400191505060405180910390fd5b8282028284828161390257fe5b051461393f5760405162461bcd60e51b815260040180806020018281038252602781526020018061582f6027913960400191505060405180910390fd5b9392505050565b60008161399a576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b816000191480156139ae5750600160ff1b83145b156139ea5760405162461bcd60e51b81526004018080602001828103825260218152602001806157cd6021913960400191505060405180910390fd5b60008284816139f557fe5b05949350505050565b600080821215613a115781600003610838565b5090565b600080821215613a11576040805162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f736974697665604482015290519081900360640190fd5b600082613a7b57506000610838565b82820282848281613a8857fe5b041461393f5760405162461bcd60e51b81526004018080602001828103825260218152602001806157ee6021913960400191505060405180910390fd5b6000808211613b1b576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613b2457fe5b049392505050565b613b34614aa8565b6000613b3f836142a3565b80516000908103600f90810b8552602092830151909103900b9083015250919050565b600080613bca85600001518560028110613b7857fe5b6020020151600f0b613bc4613ba988602001518860028110613b9657fe5b60200201516001600160801b03166142e4565b86602001518860028110613bb957fe5b602002015190614328565b90613896565b6305f5e100900595945050505050565b600080613c1c85600001518560028110613bf057fe5b6020020151600f0b613bc4858760028110613c0757fe5b602002015188604001518860028110613bb957fe5b9050613c2f81662386f26fc10000613946565b95945050505050565b8151600090600f0b815b846020015151811015613c8457613c7a613c7386602001518381518110613c6557fe5b60200260200101518661438d565b83906143ac565b9150600101613c42565b509392505050565b600080613c98846142a3565b9050613ca48184614411565b949350505050565b600081831115613d0857604682840310613cf2576040805162461bcd60e51b8152602060048201526002602482015261269960f11b604482015290519081900360640190fd5b613d0184838503600a0a613ac5565b905061393f565b81831015613d5b57604683830310613d4c576040805162461bcd60e51b8152602060048201526002602482015261269960f11b604482015290519081900360640190fd5b613d0184848403600a0a613a6c565b508261393f565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613dbc908590614575565b50505050565b61388e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383614251565b600080613e038484613c38565b9050613e0f8484613c8c565b139392505050565b613e1f614aa8565b613e27614aa8565b6000613e338686614626565b604051630b818e5960e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e06396490613e7f9088906004016152d7565b60a060405180830381600087803b158015613e9957600080fd5b505af1158015613ead573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ed19190614bfc565b875183519396509194509250613ef49160009182129187905b60200201516146cd565b613f105760405162461bcd60e51b8152600401610408906153dd565b613f2e60008660016020020151138460016020020151866001613eea565b613f4a5760405162461bcd60e51b8152600401610408906153dd565b60648104905093509350939050565b81600f0b60001415613f6a576140d4565b60405163a8ffb3b960e01b8152600090819073__$d529c113b49f05715913138dde996bfccf$__9063a8ffb3b990613fb0908d908b908e908a908d908d906004016155ad565b604080518083038186803b158015613fc757600080fd5b505af4158015613fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fff9190614d4b565b6040516328e32c8560e11b815291935091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906351c6590a90614050908490600401615308565b600060405180830381600087803b15801561406a57600080fd5b505af115801561407e573d6000803e3d6000fd5b50505050336001600160a01b03167fbfb264ae14733b7c7f6701d57d6a0dbaf244d34bf5912958835dccf887b4beea89898c888b8b898b6040516140c998979695949392919061566f565b60405180910390a250505b5050505050505050565b6140e6614aa8565b60005b825181101561416e5761413e83828151811061410157fe5b602002602001015160400151600f0b8385848151811061411d57fe5b6020026020010151600001516002811061413357fe5b6020020151906143ac565b8284838151811061414b57fe5b6020026020010151600001516002811061416157fe5b60200201526001016140e9565b50919050565b61417c614aa8565b60005b825181101561416e5782818151811061419457fe5b602002602001015160600151828483815181106141ad57fe5b602002602001015160000151600281106141c357fe5b602002015260010161417f565b6000806141dc856142a3565b905060005b60028110156142465761422361421e8683600281106141fc57fe5b6020020151600f0b84846002811061421057fe5b6020020151600f0b906143ac565b6146f6565b82826002811061422f57fe5b600f92830b90920b602090920201526001016141e1565b50613c2f8184614411565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526131f6908490614575565b6142ab614aa8565b60005b600281101561416e576142c18382614757565b8282600281106142cd57fe5b600f92830b90920b602090920201526001016142ae565b6000600160ff1b8210613a115760405162461bcd60e51b81526004018080602001828103825260288152602001806158566028913960400191505060405180910390fd5b600081830381831280159061433d5750838113155b80614352575060008312801561435257508381135b61393f5760405162461bcd60e51b815260040180806020018281038252602481526020018061587e6024913960400191505060405180910390fd5b600061393f6143a08484606001516147b8565b6143aa85856147df565b905b60008282018183128015906143c15750838112155b806143d657506000831280156143d657508381125b61393f5760405162461bcd60e51b81526004018080602001828103825260218152602001806157ac6021913960400191505060405180910390fd5b60008061444c6305f5e1006107c261443b662386f26fc10000876040015160016002811061413357fe5b86516001600160801b031690613896565b905060006144b76144b261448b662386f26fc100006107c2614480662386f26fc100008a6040015160006002811061413357fe5b8a51600f0b90613896565b6143aa68056bc75e2d631000006107c26002613bc48c600160200201518a90600f0b613896565b6139fe565b90506144f16144ea6144b269d3c21bcecceda10000006107c28960016020020151600f0b613bc46002816101f48b613896565b8290614806565b9050600064e8d4a51000614521836107fa88600001516001600160801b03166101f4613a6c90919063ffffffff16565b8161452857fe5b87519190049150600f0b15158061454557506020860151600f0b15155b801561455557506404a817c80081105b1561456257506404a817c8005b61456b816142e4565b9695505050505050565b60006145ca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148609092919063ffffffff16565b8051909150156131f6578080602001905160208110156145e957600080fd5b50516131f65760405162461bcd60e51b815260040180806020018281038252602a8152602001806158a2602a913960400191505060405180910390fd5b6000614631836142a3565b905060005b6002811015613dbc57600061466184836002811061465057fe5b602002015184846002811061421057fe5b905061467f83836002811061467257fe5b6020020151600f0b6139fe565b614688826139fe565b11156146c4576003826002811061469b57fe5b01546146a6826139fe565b11156146c45760405162461bcd60e51b815260040161040890615464565b50600101614636565b6000816146dc5750600161393f565b83156146ec57508082111561393f565b508082101561393f565b60006f7fffffffffffffffffffffffffffffff19821215801561471c57506001607f1b82125b613a115760405162461bcd60e51b81526004018080602001828103825260278152602001806157856027913960400191505060405180910390fd5b6000805b8360200151518110156147b1576147a761421e8560200151838151811061477e57fe5b602002602001015160000151856002811061479557fe5b6020020151600f85810b91900b6143ac565b915060010161475b565b5092915050565b60008060005b6002811015613c84576147d5613c73868387613bda565b91506001016147be565b60008060005b6002811015613c84576147fc613c73868387613b62565b91506001016147e5565b60008282018381101561393f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6060613ca484846000858561487485614985565b6148c5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106149035780518252601f1990920191602091820191016148e4565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614965576040519150601f19603f3d011682016040523d82523d6000602084013e61496a565b606091505b509150915061497a82828661498b565b979650505050505050565b3b151590565b6060831561499a57508161393f565b8251156149aa5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156149f45781810151838201526020016149dc565b50505050905090810190601f168015614a215780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001614aa3614ac6565b905290565b60405180604001604052806002906020820280368337509192915050565b60408051808201909152600081526060602082015290565b600082601f830112614aee578081fd5b6040516040810181811067ffffffffffffffff82111715614b0b57fe5b8060405250808385604086011115614b21578384fd5b835b6002811015614b42578151835260209283019290910190600101614b23565b509195945050505050565b600082601f830112614b5d578081fd5b813567ffffffffffffffff811115614b7157fe5b614b84601f8201601f19166020016156ff565b818152846020838601011115614b98578283fd5b816020850160208301379081016020019190915292915050565b8035600f81900b8114610c1d57600080fd5b600060208284031215614bd5578081fd5b813561393f81615723565b600060208284031215614bf1578081fd5b815161393f81615723565b600080600060a08486031215614c10578182fd5b84601f850112614c1e578182fd5b6040516040810181811067ffffffffffffffff82111715614c3b57fe5b806040525080856040870188811115614c52578586fd5b855b6002811015614c73578251845260209384019390920191600101614c54565b50839650614c818982614ade565b955050505050608084015190509250925092565b600060208284031215614ca6578081fd5b815161393f8161573b565b60008060408385031215614cc3578182fd5b8235614cce8161573b565b946020939093013593505050565b600060208284031215614ced578081fd5b5035919050565b600060208284031215614d05578081fd5b5051919050565b600080600080600060a08688031215614d23578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b60008060408385031215614d5d578182fd5b505080516020909101519092909150565b600060808284031215614d7f578081fd5b6040516080810181811067ffffffffffffffff82111715614d9c57fe5b80604052508251815260208301516020820152604083015160408201526060830151614dc78161573b565b60608201529392505050565b600060208284031215614de4578081fd5b67ffffffffffffffff8083351115614dfa578182fd5b8235830160808186031215614e0d578283fd5b604051608081018181108482111715614e2257fe5b60405281358152602082013583811115614e3a578485fd5b8201601f81018713614e4a578485fd5b803584811115614e5657fe5b614e646020808302016156ff565b818152602080820191908401885b84811015614f15578135860160a0818e03601f19011215614e91578a8bfd5b60405160a081018181108c82111715614ea657fe5b80604052506020820135815260408201356020820152614ec860608301614bb2565b6040820152608082013560608201528a60a08301351115614ee7578b8cfd5b614efa8e602060a0850135850101614b4d565b60808201528552506020938401939190910190600101614e72565b505060208501525050506040828101359082015260609182013591810191909152949350505050565b600060e08284031215614f4f578081fd5b6040516080810181811067ffffffffffffffff82111715614f6c57fe5b6040528251614f7a81615749565b8152614f898460208501614ade565b6020820152614f9b8460608501614ade565b6040820152614dc78460a08501614ade565b600060208284031215614fbe578081fd5b813561393f81615749565b60008060608385031215614fdb578182fd5b82359150602084603f850112614fef578182fd5b6040516040810181811067ffffffffffffffff8211171561500c57fe5b6040528085830160608701881015615022578485fd5b845b60028110156150485761503682614bb2565b83529184019190840190600101615024565b50505080925050509250929050565b60008060608385031215615069578182fd5b82359150602084603f85011261507d578182fd5b6040516040810181811067ffffffffffffffff8211171561509a57fe5b60405280858301606087018810156150b0578485fd5b845b6002811015615048578135835291840191908401906001016150b2565b600080604083850312156150e1578182fd5b50508035926020909101359150565b600060208284031215615101578081fd5b815160ff8116811461393f578182fd5b6000815180845260208085019450808401835b8381101561514a57615137878351615155565b6040969096019590820190600101615124565b509495945050505050565b8060005b6002811015613dbc578151845260209384019390910190600101615159565b600060408084018351600f81810b87526020915081860151848389015283815180865260608a01915084830195508792505b808310156152345785518051838a5b60028110156151d8578251880b825291880191908801906001016151b9565b505050858101518884018a5b600281101561520a5782516001600160801b0316825291880191908801906001016151e4565b50505087015161521d6080840182615155565b5060c08201915084860195506001830192506151aa565b5098975050505050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0394909416845291151560208401526040830152606082015260800190565b6001600160a01b039290921682526001600160801b0316602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b604081016108388284615155565b901515815260200190565b92151583526020830191909152604082015260600190565b90815260200190565b918252602082015260400190565b602080825260039082015262504d3760e81b604082015260600190565b60208082526003908201526228269960e91b604082015260600190565b6020808252600390820152620504d360ec1b604082015260600190565b6020808252601390820152723b30bab63a1034b9903737ba103230b733b2b960691b604082015260600190565b6020808252600390820152620a09a760eb1b604082015260600190565b60208082526003908201526214134d60ea1b604082015260600190565b602080825260039082015262504d3160e81b604082015260600190565b60208082526003908201526228269b60e91b604082015260600190565b602080825260039082015262504d3360e81b604082015260600190565b6020808252601690820152757661756c7420686173206e6f20706f736974696f6e7360501b604082015260600190565b602080825260039082015262504d3560e81b604082015260600190565b602080825260039082015262504d3960e81b604082015260600190565b81518152602080830151908201526040808301519082015260609182015115159181019190915260800190565b600061010082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b60006020825261393f6020830184615178565b9283526020830191909152604082015260600190565b838152602080820184905282516001600160801b0316604083015282015161012082019061557e6060840182615155565b50604083015161559160a0840182615155565b5060608301516155a460e0840182615155565b50949350505050565b95865260208601949094526040850192909252600f0b6060840152608083015260a082015260c00190565b6000602082528251602083015260208301516040830152604083015160a0606084015261560860c0840182615111565b90506060840151601f19808584030160808601526156268383615111565b925060808601519150808584030160a086015250613c2f8282615178565b8281526060810161393f6020830184615155565b9182526001600160801b0316602082015260400190565b60006101008a835260208a8185015289604085015288600f0b60608501528760808501528660a08501528560c08501528160e0850152845180838601528392505b808310156156cf578583018201518584016101200152918101916156b0565b808311156156e1578361012082870101525b601f01601f191693909301610120019b9a5050505050505050505050565b60405181810167ffffffffffffffff8111828210171561571b57fe5b604052919050565b6001600160a01b038116811461573857600080fd5b50565b801515811461573857600080fd5b6001600160801b038116811461573857600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f775369676e6564536166654d6174683a206469766973696f6e206f766572666c6f77536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220d6956d2e92f4a6999df6a3cb297a31c749d6f0661f14e074a9de4774b7d3c7a164736f6c63430007060033",
  "libraries": {
    "TraderVaultLib": "0xB6a4A36f7E918a084E5bB39475B30b06cB9CEd91"
  },
  "devdoc": {
    "kind": "dev",
    "methods": {
      "addMargin(uint256,int256)": {
        "params": {
          "_marginToAdd": "amount of margin to add",
          "_vaultId": "id of the vault"
        }
      },
      "getLPTokenPrice(int256)": {
        "params": {
          "_deltaLiquidityAmount": "difference of liquidity If LPs want LP token price of deposit, _deltaLiquidityAmount is positive number of amount to deposit. On the other hand, if LPs want LP token price of withdrawal, _deltaLiquidityAmount is negative number of amount to withdraw."
        },
        "returns": {
          "_0": "LP token price scaled by 1e6"
        }
      },
      "getMinCollateralToAddPosition(uint256,int128[2])": {
        "params": {
          "_tradeAmounts": "amounts to trade",
          "_vaultId": "The id of target vault"
        },
        "returns": {
          "minCollateral": "scaled by 1e6"
        }
      },
      "getPositionValueAndMinCollateral(uint256)": {
        "params": {
          "_vaultId": "The id of target vault"
        }
      },
      "getTokenAmountForHedging()": {
        "returns": {
          "_0": "Amount of USDC and underlying reqired for hedging"
        }
      },
      "getTradePrice(uint256,int256[2])": {
        "params": {
          "_productId": "product id",
          "_tradeAmounts": "amount of position to trade. positive to get long price and negative to get short price."
        },
        "returns": {
          "_0": "trade info"
        }
      },
      "getVaultStatus(uint256)": {
        "params": {
          "_vaultId": "The id of target vault"
        },
        "returns": {
          "_0": "vault status"
        }
      },
      "initialize(uint256,int256)": {
        "params": {
          "_depositAmount": "deposit amount",
          "_initialFundingRate": "initial funding rate"
        }
      },
      "liquidateByPool(uint256)": {
        "params": {
          "_vaultId": "The id of target vault"
        }
      },
      "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."
      },
      "setFeeRecepient(address)": {
        "params": {
          "_feeRecepient": "The address of new fee recepient"
        }
      },
      "setHedger(address)": {
        "params": {
          "_hedger": "bot address"
        }
      },
      "setMaxAmount(uint256,uint256)": {
        "params": {
          "_maxFutureAmount": "max future amount",
          "_maxSquaredAmount": "max squared amount"
        }
      },
      "trade((uint256,(uint256,uint256,int128,uint256,bytes)[],int256,uint256))": {
        "params": {
          "_tradeParams": "trade parameters"
        }
      },
      "transferOwnership(address)": {
        "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
      }
    },
    "stateVariables": {
      "LIQUIDATION_FEE": {
        "details": "liquidation fee is 10%"
      },
      "hedger": {
        "details": "hedger address"
      },
      "isSystemPaused": {
        "details": "is system paused"
      },
      "maxPositionsInVault": {
        "details": "maximum positions in a vault"
      }
    },
    "title": "Perpetual Market",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "addMargin(uint256,int256)": {
        "notice": "Add margin to the vault"
      },
      "constructor": {
        "notice": "Constructor of Perpetual Market contract"
      },
      "deposit(uint256)": {
        "notice": "Provides liquidity to the pool and mints LP tokens"
      },
      "execHedge(bool,uint256)": {
        "notice": "Executes hedging"
      },
      "getLPTokenPrice(int256)": {
        "notice": "Gets current LP token price"
      },
      "getMinCollateralToAddPosition(uint256,int128[2])": {
        "notice": "Gets value of min collateral to add positions"
      },
      "getPositionValueAndMinCollateral(uint256)": {
        "notice": "Gets position value and min collateral"
      },
      "getTokenAmountForHedging()": {
        "notice": "Gets token amount for hedging"
      },
      "getTradePrice(uint256,int256[2])": {
        "notice": "Gets trade price"
      },
      "getVaultStatus(uint256)": {
        "notice": "Gets position value of a vault"
      },
      "initialize(uint256,int256)": {
        "notice": "Initializes Perpetual Pool"
      },
      "liquidateByPool(uint256)": {
        "notice": "Liquidates a vault by Pool Anyone can liquidate a vault whose PositionValue is less than MinCollateral. The caller gets a portion of the margin as reward."
      },
      "pause()": {
        "notice": "pause the contract"
      },
      "setFeeRecepient(address)": {
        "notice": "Sets new fee recepient"
      },
      "setHedger(address)": {
        "notice": "set bot address"
      },
      "setMaxAmount(uint256,uint256)": {
        "notice": "Sets max amounts that a vault can hold"
      },
      "trade((uint256,(uint256,uint256,int128,uint256,bytes)[],int256,uint256))": {
        "notice": "Opens new positions or closes hold position of the perpetual contracts and manage margin in the vault at the same time."
      },
      "unPause()": {
        "notice": "unpause the contract"
      },
      "withdraw(uint128)": {
        "notice": "Withdraws liquidity from the pool and burn LP tokens"
      }
    },
    "notice": "Perpetual Market Contract is entry point of traders and liquidity providers. It manages traders' vault storage and holds funds from traders and liquidity providers. Error Codes PM0: tx exceed deadline PM1: limit price PM2: caller is not vault owner PM3: vault not found PM4: caller is not hedger PM5: vault limit PM6: Paused PM7: Not paused PM8: USDC amount is too large PM9: USDC amount is too small",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 53,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "_owner",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 6992,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "hedger",
        "offset": 0,
        "slot": "1",
        "type": "t_address"
      },
      {
        "astId": 6994,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "feeRecepient",
        "offset": 0,
        "slot": "2",
        "type": "t_contract(IFeePool)12815"
      },
      {
        "astId": 6999,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "maxPositionsInVault",
        "offset": 0,
        "slot": "3",
        "type": "t_array(t_uint256)2_storage"
      },
      {
        "astId": 7001,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "vaultNFT",
        "offset": 0,
        "slot": "5",
        "type": "t_address"
      },
      {
        "astId": 7005,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "traderVaults",
        "offset": 0,
        "slot": "6",
        "type": "t_mapping(t_uint256,t_struct(TraderVault)15226_storage)"
      },
      {
        "astId": 7008,
        "contract": "src/PerpetualMarket.sol:PerpetualMarket",
        "label": "isSystemPaused",
        "offset": 0,
        "slot": "7",
        "type": "t_bool"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_int128)2_storage": {
        "base": "t_int128",
        "encoding": "inplace",
        "label": "int128[2]",
        "numberOfBytes": "32"
      },
      "t_array(t_int256)2_storage": {
        "base": "t_int256",
        "encoding": "inplace",
        "label": "int256[2]",
        "numberOfBytes": "64"
      },
      "t_array(t_struct(SubVault)15220_storage)dyn_storage": {
        "base": "t_struct(SubVault)15220_storage",
        "encoding": "dynamic_array",
        "label": "struct TraderVaultLib.SubVault[]",
        "numberOfBytes": "32"
      },
      "t_array(t_uint128)2_storage": {
        "base": "t_uint128",
        "encoding": "inplace",
        "label": "uint128[2]",
        "numberOfBytes": "32"
      },
      "t_array(t_uint256)2_storage": {
        "base": "t_uint256",
        "encoding": "inplace",
        "label": "uint256[2]",
        "numberOfBytes": "64"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_contract(IFeePool)12815": {
        "encoding": "inplace",
        "label": "contract IFeePool",
        "numberOfBytes": "20"
      },
      "t_int128": {
        "encoding": "inplace",
        "label": "int128",
        "numberOfBytes": "16"
      },
      "t_int256": {
        "encoding": "inplace",
        "label": "int256",
        "numberOfBytes": "32"
      },
      "t_mapping(t_uint256,t_struct(TraderVault)15226_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => struct TraderVaultLib.TraderVault)",
        "numberOfBytes": "32",
        "value": "t_struct(TraderVault)15226_storage"
      },
      "t_struct(SubVault)15220_storage": {
        "encoding": "inplace",
        "label": "struct TraderVaultLib.SubVault",
        "members": [
          {
            "astId": 15211,
            "contract": "src/PerpetualMarket.sol:PerpetualMarket",
            "label": "positionPerpetuals",
            "offset": 0,
            "slot": "0",
            "type": "t_array(t_int128)2_storage"
          },
          {
            "astId": 15215,
            "contract": "src/PerpetualMarket.sol:PerpetualMarket",
            "label": "entryPrices",
            "offset": 0,
            "slot": "1",
            "type": "t_array(t_uint128)2_storage"
          },
          {
            "astId": 15219,
            "contract": "src/PerpetualMarket.sol:PerpetualMarket",
            "label": "entryFundingFee",
            "offset": 0,
            "slot": "2",
            "type": "t_array(t_int256)2_storage"
          }
        ],
        "numberOfBytes": "128"
      },
      "t_struct(TraderVault)15226_storage": {
        "encoding": "inplace",
        "label": "struct TraderVaultLib.TraderVault",
        "members": [
          {
            "astId": 15222,
            "contract": "src/PerpetualMarket.sol:PerpetualMarket",
            "label": "positionUsdc",
            "offset": 0,
            "slot": "0",
            "type": "t_int128"
          },
          {
            "astId": 15225,
            "contract": "src/PerpetualMarket.sol:PerpetualMarket",
            "label": "subVaults",
            "offset": 0,
            "slot": "1",
            "type": "t_array(t_struct(SubVault)15220_storage)dyn_storage"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint128": {
        "encoding": "inplace",
        "label": "uint128",
        "numberOfBytes": "16"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}