From d77d2c7ff6025a8487f63fa01ee4147317d8bf94 Mon Sep 17 00:00:00 2001 From: arjun-io <2940142+arjun-io@users.noreply.github.com> Date: Wed, 21 Jun 2023 13:14:32 -0400 Subject: [PATCH] Upgrade ARB Goerli Product Impl Deployment (#197) --- .../arbitrumGoerli/Product_Impl.json | 28 +-- .../008bd4aa82b76d91af7a1bfbf9fddc30.json | 165 ++++++++++++++++++ 2 files changed, 179 insertions(+), 14 deletions(-) create mode 100644 packages/perennial/deployments/arbitrumGoerli/solcInputs/008bd4aa82b76d91af7a1bfbf9fddc30.json diff --git a/packages/perennial/deployments/arbitrumGoerli/Product_Impl.json b/packages/perennial/deployments/arbitrumGoerli/Product_Impl.json index 94bfdecf..46268be5 100644 --- a/packages/perennial/deployments/arbitrumGoerli/Product_Impl.json +++ b/packages/perennial/deployments/arbitrumGoerli/Product_Impl.json @@ -1,5 +1,5 @@ { - "address": "0x4a0f50b19b02AC927911C559629536B9a24d9314", + "address": "0x140FDD078CD02236FA118a2c8995DAF9ab1bb5e8", "abi": [ { "inputs": [], @@ -1724,26 +1724,26 @@ "type": "function" } ], - "transactionHash": "0x8833e147879db568e1cf99fa55b7750ea3417219af0e324d3779f2793e90ef5a", + "transactionHash": "0xcce9d949ab42165582cb7f819ebc9c31acd3bf937fd55afe79b7fcc459007396", "receipt": { "to": null, "from": "0x66a7fDB96C583c59597de16d8b2B989231415339", - "contractAddress": "0x4a0f50b19b02AC927911C559629536B9a24d9314", - "transactionIndex": 1, - "gasUsed": "5352748", + "contractAddress": "0x140FDD078CD02236FA118a2c8995DAF9ab1bb5e8", + "transactionIndex": 2, + "gasUsed": "5351680", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe55ebf77f0f4ed4d439b2cb264fbb11adb3d10248331594169f760ab89810ff9", - "transactionHash": "0x8833e147879db568e1cf99fa55b7750ea3417219af0e324d3779f2793e90ef5a", + "blockHash": "0x423742848909fd75313250f47a15d4dd28c10783bf984339e2ad13c3a484045b", + "transactionHash": "0xcce9d949ab42165582cb7f819ebc9c31acd3bf937fd55afe79b7fcc459007396", "logs": [], - "blockNumber": 4213952, - "cumulativeGasUsed": "5352748", + "blockNumber": 27276482, + "cumulativeGasUsed": "5546886", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "a94c7c3630faebd0874cdd6386cdd2fc", - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CurveMathOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Fixed18OverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"}],\"name\":\"Fixed18PackingOverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"}],\"name\":\"Fixed18PackingUnderflowError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidControllerError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"NotAccountOrMultiInvokerError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotCollateralError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"NotOwnerError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"}],\"name\":\"NotProductError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParamProviderInvalidParamValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PausedError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"name\":\"PayoffDefinitionNotContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"}],\"name\":\"PayoffDefinitionUnsupportedTransform\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PayoffProviderInvalidOracle\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PayoffProviderInvalidPayoffDefinitionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PendingFeeUpdatesUnsupportedValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductClosedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductDoubleSidedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductInLiquidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductInsufficientCollateralError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"socializationFactor\",\"type\":\"uint256\"}],\"name\":\"ProductInsufficientLiquidityError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductMakerOverLimitError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductOracleBootstrappingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductOverClosedError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"UFixed18PackingOverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UInitializableAlreadyInitializedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableNotInitializingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableZeroVersionError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UReentrancyGuardReentrantCallError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toVersion\",\"type\":\"uint256\"}],\"name\":\"AccountSettle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"newClosed\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"ClosedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newFundingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"FundingFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"JumpRateUtilizationCurveUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMaintenance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MaintenanceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MakeClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MakeOpened\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MakerLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"OracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"}],\"name\":\"PendingMakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"}],\"name\":\"PendingPositionFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"}],\"name\":\"PendingTakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"PositionFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toVersion\",\"type\":\"uint256\"}],\"name\":\"Settle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TakeClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TakeOpened\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"TakerFeeUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"atVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"Fixed18\",\"name\":\"price\",\"type\":\"int256\"}],\"internalType\":\"struct IOracleProvider.OracleVersion\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"closeAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeMake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeMakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeTake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeTakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"Fixed18\",\"name\":\"price\",\"type\":\"int256\"}],\"internalType\":\"struct IOracleProvider.OracleVersion\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"internalType\":\"struct PayoffDefinition\",\"name\":\"payoffDefinition\",\"type\":\"tuple\"},{\"internalType\":\"contract IOracleProvider\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"maintenance\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"fundingFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"makerFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"takerFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"positionFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"makerLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"utilizationCurve\",\"type\":\"tuple\"}],\"internalType\":\"struct IProduct.ProductInfo\",\"name\":\"productInfo_\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isClosed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isLiquidating\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"latestVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maintenance\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"maintenance\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"maintenanceNext\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makerFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makerLimit\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openMake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openMakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openTake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openTakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IOracleProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoffDefinition\",\"outputs\":[{\"components\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"internalType\":\"struct PayoffDefinition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeUpdates\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"makerFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingMakerFee\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"takerFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingTakerFee\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"positionFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingPositionFee\",\"type\":\"uint64\"}],\"internalType\":\"struct PendingFeeUpdates\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"position\",\"outputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"positionAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"positionFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"pre\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"openPosition\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"closePosition\",\"type\":\"tuple\"}],\"internalType\":\"struct PrePosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pre\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"openPosition\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"closePosition\",\"type\":\"tuple\"}],\"internalType\":\"struct PrePosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"position_\",\"type\":\"tuple\"}],\"name\":\"rate\",\"outputs\":[{\"internalType\":\"Fixed18\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"settleAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"shareAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"Fixed18\",\"name\":\"maker\",\"type\":\"int256\"},{\"internalType\":\"Fixed18\",\"name\":\"taker\",\"type\":\"int256\"}],\"internalType\":\"struct Accumulator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"takerFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"newClosed\",\"type\":\"bool\"}],\"name\":\"updateClosed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newFundingFee\",\"type\":\"uint256\"}],\"name\":\"updateFundingFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMaintenance\",\"type\":\"uint256\"}],\"name\":\"updateMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"}],\"name\":\"updateMakerFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMakerLimit\",\"type\":\"uint256\"}],\"name\":\"updateMakerLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IOracleProvider\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"updateOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"}],\"name\":\"updatePositionFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"}],\"name\":\"updateTakerFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"newUtilizationCurve\",\"type\":\"tuple\"}],\"name\":\"updateUtilizationCurve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"utilizationCurve\",\"outputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"valueAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"Fixed18\",\"name\":\"maker\",\"type\":\"int256\"},{\"internalType\":\"Fixed18\",\"name\":\"taker\",\"type\":\"int256\"}],\"internalType\":\"struct Accumulator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Cloned by the Controller contract to launch new product markets.\",\"kind\":\"dev\",\"methods\":{\"atVersion(uint256)\":{\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Oracle version at `oracleVersion` with price transformed by payoff function\"}},\"closeAll(address)\":{\"details\":\"Only callable by the Collateral contract as part of the liquidation flow\",\"params\":{\"account\":\"Account to close out\"}},\"closeMake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to close\"}},\"closeMakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to close the position for\",\"amount\":\"Amount of the position to close\"}},\"closeTake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to close\"}},\"closeTakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to close the position for\",\"amount\":\"Amount of the position to close\"}},\"currentVersion()\":{\"returns\":{\"_0\":\"Current oracle version transformed by the payoff definition\"}},\"initialize((string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"params\":{\"productInfo_\":\"Product initialization params\"}},\"isClosed(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The the account is closed\"}},\"isLiquidating(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Whether the account is in liquidation\"}},\"latestVersion()\":{\"returns\":{\"_0\":\"Latest settled oracle version of the product\"}},\"latestVersion(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Latest settled oracle version of the account\"}},\"maintenance(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The current maintenance requirement\"}},\"maintenanceNext(address)\":{\"details\":\"Assumes no price change and no funding, used to protect user from over-opening\",\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The next maintenance requirement\"}},\"openMake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to open\"}},\"openMakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to open position for\",\"amount\":\"Amount of the position to open\"}},\"openTake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to open\"}},\"openTakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to open the position for\",\"amount\":\"Amount of the position to open\"}},\"position(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Current position of the account\"}},\"positionAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global position at oracle version\"}},\"pre()\":{\"returns\":{\"_0\":\"Global pending-settlement position\"}},\"pre(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Current pre-position of the account\"}},\"rate((uint256,uint256))\":{\"details\":\"Handles 0-maker/taker edge cases\",\"params\":{\"position_\":\"Position to base utilization on\"},\"returns\":{\"_0\":\"The per-second rate\"}},\"settleAccount(address)\":{\"params\":{\"account\":\"Account to settle\"}},\"shareAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global accumulator share at oracle version\"}},\"updateClosed(bool)\":{\"details\":\"only callable by product owner. Settles the product before flipping the flag\",\"params\":{\"newClosed\":\"new closed value\"}},\"updateFundingFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newFundingFee\":\"new funding fee value\"}},\"updateMaintenance(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMaintenance\":\"new maintenance value\"}},\"updateMakerFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMakerFee\":\"new maker fee value\"}},\"updateMakerLimit(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMakerLimit\":\"new maker limit value\"}},\"updateOracle(address)\":{\"details\":\"only callable by product owner\",\"params\":{\"newOracle\":\"new oracle address\"}},\"updatePositionFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newPositionFee\":\"new position fee value\"}},\"updateTakerFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newTakerFee\":\"new taker fee value\"}},\"updateUtilizationCurve((int128,int128,int128,uint128))\":{\"details\":\"only callable by product owner\",\"params\":{\"newUtilizationCurve\":\"new utilization curve value\"}},\"valueAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global accumulator value at oracle version\"}}},\"stateVariables\":{\"_accumulator\":{\"details\":\"The global accumulator state for the product\"},\"_accumulators\":{\"details\":\"The individual accumulator state for each account\"},\"_closed\":{\"details\":\"Whether or not the product is closed\"},\"_position\":{\"details\":\"The global position state for the product\"},\"_positions\":{\"details\":\"The individual position state for each account\"},\"name\":{\"details\":\"The name of the product\"},\"symbol\":{\"details\":\"The symbol of the product\"}},\"title\":\"Product\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"atVersion(uint256)\":{\"notice\":\"Returns the oracle version at `oracleVersion` transformed by the payoff definition\"},\"closeAll(address)\":{\"notice\":\"Closes all open and pending positions, locking for liquidation\"},\"closeMake(uint256)\":{\"notice\":\"Closes a maker position for `msg.sender`\"},\"closeMakeFor(address,uint256)\":{\"notice\":\"Closes a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"closeTake(uint256)\":{\"notice\":\"Closes a taker position for `msg.sender`\"},\"closeTakeFor(address,uint256)\":{\"notice\":\"Closes a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"currentVersion()\":{\"notice\":\"Returns the current oracle version transformed by the payoff definition\"},\"initialize((string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"notice\":\"Initializes the contract state\"},\"isClosed(address)\":{\"notice\":\"Returns whether `account` has a completely zero'd position\"},\"isLiquidating(address)\":{\"notice\":\"Returns whether `account` is currently locked for an in-progress liquidation\"},\"latestVersion()\":{\"notice\":\"Returns the global latest settled oracle version\"},\"latestVersion(address)\":{\"notice\":\"Returns `account`'s latest settled oracle version\"},\"maintenance(address)\":{\"notice\":\"Returns the maintenance requirement for `account`\"},\"maintenanceNext(address)\":{\"notice\":\"Returns the maintenance requirement for `account` after next settlement\"},\"openMake(uint256)\":{\"notice\":\"Opens a maker position for `msg.sender`\"},\"openMakeFor(address,uint256)\":{\"notice\":\"Opens a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"openTake(uint256)\":{\"notice\":\"Opens a taker position for `msg.sender`\"},\"openTakeFor(address,uint256)\":{\"notice\":\"Opens a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"position(address)\":{\"notice\":\"Returns `account`'s current position\"},\"positionAtVersion(uint256)\":{\"notice\":\"Returns the global position at oracleVersion `oracleVersion`\"},\"pre()\":{\"notice\":\"Returns the current global pending-settlement position\"},\"pre(address)\":{\"notice\":\"Returns `account`'s current pending-settlement position\"},\"rate((uint256,uint256))\":{\"notice\":\"Returns The per-second rate based on the provided `position`\"},\"settle()\":{\"notice\":\"Surfaces global settlement externally\"},\"settleAccount(address)\":{\"notice\":\"Surfaces account settlement externally\"},\"shareAtVersion(uint256)\":{\"notice\":\"Returns the global accumulator share at oracleVersion `oracleVersion`\"},\"updateClosed(bool)\":{\"notice\":\"Updates product closed state\"},\"updateFundingFee(uint256)\":{\"notice\":\"Updates the funding fee to `newFundingFee`\"},\"updateMaintenance(uint256)\":{\"notice\":\"Updates the maintenance to `newMaintenance`\"},\"updateMakerFee(uint256)\":{\"notice\":\"Updates the maker fee to `newMakerFee`\"},\"updateMakerLimit(uint256)\":{\"notice\":\"Updates the maker limit to `newMakerLimit`\"},\"updateOracle(address)\":{\"notice\":\"Updates underlying product oracle\"},\"updatePositionFee(uint256)\":{\"notice\":\"Updates the position fee to `newPositionFee`\"},\"updateTakerFee(uint256)\":{\"notice\":\"Updates the taker fee to `newTakerFee`\"},\"updateUtilizationCurve((int128,int128,int128,uint128))\":{\"notice\":\"Updates the utilization curve to `newUtilizationCurve`\"},\"valueAtVersion(uint256)\":{\"notice\":\"Returns the global accumulator value at oracleVersion `oracleVersion`\"}},\"notice\":\"Manages logic and state for a single product market.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/product/Product.sol\":\"Product\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":true,\"cse\":true,\"deduplicate\":true,\"inliner\":true,\"jumpdestRemover\":true,\"orderLiterals\":true,\"peephole\":true,\"yul\":true,\"yulDetails\":{\"optimizerSteps\":\"dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul\",\"stackAllocation\":true}},\"runs\":1},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\":{\"keccak256\":\"0xb9c0b0fc0dfcd44492b029ede04d304f6906b030cb925dc0fc2579e8c58d9734\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://a013a45803a911ea2e797ffd54c457ccd4d6250680c1bec9931b4ea97a6665ad\",\"dweb:/ipfs/QmWy6PxqoFBnHF5oHnn9pmrthz2ktHnaobw8WzYgQ6TrbC\"]},\"@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol\":{\"keccak256\":\"0xdb96e26082a471c7803e892ecd8d2877f23cd9e31f13a3e407dd5f8909078864\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e347199f4798f8310f24fc4099f8ffd68d7a89273381198a70c89d91368ec8b5\",\"dweb:/ipfs/Qmb16jC83BBpseaWY6vMMEL1fkkSPTiuez86SAP6Vb25dx\"]},\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\":{\"keccak256\":\"0x11e8ebb40917dcce08a6366e6fa8d25b037552d4ea66b96c13e6f45b1f817c52\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://48167543bd2b36b513aa5d637d831cb5053bbdec63e1cb901954a935aac7b74d\",\"dweb:/ipfs/QmVJrtmW44o6hcbV2EVd1mqcsKAFoiRs7XmLiGRBrxqHha\"]},\"@equilibria/root/control/unstructured/UInitializable.sol\":{\"keccak256\":\"0xd2743d8fcc220ed2ccdc0bba1db0a3e107741bd5c0cac47ca8c0b5a00ba2fd7f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://56aadd6e4d60dde940c2d1dd0f4d39aaca7666850a8af9f288c81cb36ef780d3\",\"dweb:/ipfs/QmSFeJURqupzavfsCTZJHQKDYDnzQnyGAA24oeDCDHpJz4\"]},\"@equilibria/root/control/unstructured/UReentrancyGuard.sol\":{\"keccak256\":\"0x4962245ca8fdda3dc40c0f942a3568d90fb69428a6927b058018b01c90eb9fc9\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://2fc71fcb0176819e0266d3e9ffc9f02548b8513d360d29aeb951577b997caed7\",\"dweb:/ipfs/QmQtdTj4akRn6ZNzQYB1KsxzgdewJGrZNaZp4WYGqbquZA\"]},\"@equilibria/root/curve/CurveMath.sol\":{\"keccak256\":\"0x60d159f9ddf0dbe81124ecad58bba734b4cf82877637ff8d9d7f3e92f2da4ded\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://21ec7d55c7edb5e33a8448f90f8229a69e3ad88ce36f174515008ef6a01aa6d3\",\"dweb:/ipfs/QmNR72iJ8ayUBg8KiwDEdU5bsPf2UU9APPXG4bU1Ehq6zk\"]},\"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\":{\"keccak256\":\"0xae202813874bc306d51b3dab8194c86f6483bb20bf1f673ddaee16aa8de567ff\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://078af55f041677c10be7eb87c4c4d7683288b2c04b936bccca9929315b4e7b45\",\"dweb:/ipfs/QmbmQsXNmfVxL95qHFQiaEQpt8PHohnpLdd94T3THYFubF\"]},\"@equilibria/root/number/types/Fixed18.sol\":{\"keccak256\":\"0x613587461ef3437ef33229cdda7d34ea746278721baf06e20b2e43977f43174d\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://630392f0e52d45747543e562ed58962bfa70c867031bdc2f304193072afbd618\",\"dweb:/ipfs/QmT1Zrvart6MYLvf4XqZUjm99L5AfuBcczV27ed3V4AvbW\"]},\"@equilibria/root/number/types/PackedFixed18.sol\":{\"keccak256\":\"0xb52960cc8e3132e45d342bbbb1c6a96219022cd8557997933bd8250170268b64\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d3dde781dcb4cd5b7aff0d1a2b5d38bd9a321afd371aed6f88e4b4b2bc2a5984\",\"dweb:/ipfs/QmYaAukn1c8tE21HC2N415XZxT1H8zMQeoUoxh3iJTgxyA\"]},\"@equilibria/root/number/types/PackedUFixed18.sol\":{\"keccak256\":\"0xb5c5cd32d6530b2fe75228b6be32ebcb7762f6d7988b85a6b85a289ce8256d51\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://162ccf052216233008e732f0059d7cfde5c0aa70a5d4cf6549b1840f2ea791cc\",\"dweb:/ipfs/QmT95S1UHQbsT2ehAG42tLw4RUwCGijQ4fTkndL126yJmE\"]},\"@equilibria/root/number/types/UFixed18.sol\":{\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://eb72bd190425ef3165df4c255617dfccb494563b3f9953c91aa8c4619cce779f\",\"dweb:/ipfs/QmZdmxTZh8DtGZeE1xzrPxSDNnicRTXpPgG97AsbE3TA3C\"]},\"@equilibria/root/storage/UStorage.sol\":{\"keccak256\":\"0xe2b8491d1b5aa93f7e059e1a8f156b0ab37fef9ed973be97a64f2eabfc2cc172\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://67fd3b83c6e94369d5a75c8fbd15341c4f0c12d6612dc222bc4d82882c1c0f93\",\"dweb:/ipfs/QmNj8i2c5mZysTxoQWg2A21iWyYna6okSHQjHvp6ycQ1Mh\"]},\"@equilibria/root/token/types/Token18.sol\":{\"keccak256\":\"0x6b12afaece814f0ab186200a4729e93eb685a21d3e9b5a3372ff283a7ad5dc23\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e0118aeb6adc917b2ceadb82cc3a7a56d144ce4c8479296a4b288998c95e23e8\",\"dweb:/ipfs/QmcuREZS6RQU4brXKJ6cYE9dadqMJkrSrRDS7uEVau9eLJ\"]},\"@equilibria/root/token/types/Token6.sol\":{\"keccak256\":\"0x5ec7bee45a0e13f91ab2399472cf11136496073ad470cd70244855e12a7b6e65\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1aa85b4f3e8c72530bd1ef51445400ca646e1c809b9519f7ad8da588632a43b2\",\"dweb:/ipfs/QmS43PEuLdSaGrELtQ7wVg9wZB3NN2HbaSdDSy2GMxuofT\"]},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4632c341a06ba5c079b51ca5a915efab4e6ab57735b37839b3e8365ff806a43e\",\"dweb:/ipfs/QmTHT3xHYed2wajEoA5qu7ii2BxLpPhQZHwAhtLK5Z7ANK\"]},\"@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b3a57d0854b2fdce6ebff933a48dca2445643d1eccfc27f00292e937f26c6a58\",\"dweb:/ipfs/QmW45rZooS9TqR4YXUbjRbtf2Bpb5ouSarBvfW1LdGprvV\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ab84f13e6e6e0823854a0cddd49e96df052092d5919f95587607f0ed28a64cb6\",\"dweb:/ipfs/QmbNtqAq23ZDjCzHukQaa7B3y6rcobscm6FZF5PMQXcnVr\"]},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"contracts/controller/UControllerProvider.sol\":{\"keccak256\":\"0xf1563a6a8849193342e759b942b7c85b97d4c96fae03c3d09d8f4f32d1933593\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b897a1523ac1c779810260b01e77f7d2293707e3ff0685f3997f831de53cc087\",\"dweb:/ipfs/QmafCuN5GtmTerFR7JVp4qQipnF6sZ5kLkP1NvFv398TCZ\"]},\"contracts/interfaces/ICollateral.sol\":{\"keccak256\":\"0x6fb67eb5fc3ed4a74522677da3349d75105389369892756a60fcab4c901d352b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://af5a9b9bf3c72cb88230413966455cfcb0d43f88f1eeb52f8f083ca8cd46d55f\",\"dweb:/ipfs/Qmd8VjEoZpuY7CcDD942adQkwa9QVfyX6kEgBQ5gRymaMh\"]},\"contracts/interfaces/IContractPayoffProvider.sol\":{\"keccak256\":\"0xd73df106d032e976fd959ee6713240e36f54277ce5f215eaec8d5a2c6720a86b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b7932019acd64c5310eb266645d9bf9d13ba414ad4cbb8399b5c5fd5702d5d14\",\"dweb:/ipfs/QmVCXi3HXbGxm3kd6MsMULEFjtq8ecWvtREXnkgPgQFNnr\"]},\"contracts/interfaces/IController.sol\":{\"keccak256\":\"0xb6798b45b76edb91f6e56380eeeacdcfb37bbeb620a2d9c3e9993c39675bbd48\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://734265e658ee8f87a0a08471fcdc65d882f7dd49ee3efc5559b7c7282f619771\",\"dweb:/ipfs/QmYvK4xyECRyPtNhPybtMv3BKRuSZRi47WtaFruosn3Wfc\"]},\"contracts/interfaces/IIncentivizer.sol\":{\"keccak256\":\"0xd9d65d1190d830c8b797829f94194db86bb712e51f404e8c3e2c9b1df5645649\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d248dc35209163884a17bcd7c0b31cf2d2281937f1010b30a42cfad0a2e12b68\",\"dweb:/ipfs/QmWkBSxtdPt3NPMMfBe3z4xhARXR5X4yCXPzCddYwxqEcy\"]},\"contracts/interfaces/IMultiInvoker.sol\":{\"keccak256\":\"0x80e035472b990b026888f326b4dcceb7526491607b61e50592ceb8d36cc99728\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1142b4a43b7d8552d292cd19c3263fc1582899a01fd3a659a199bc496c468a44\",\"dweb:/ipfs/Qmcyqieo11NBPa3AVAZ7gJKKQXakaaCozLDFGRwWp5cHng\"]},\"contracts/interfaces/IParamProvider.sol\":{\"keccak256\":\"0x21584bd07296eb4e8bd6076fd20afad320e781c19c60b479c9340c69b0f37517\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://2f2383b1730f8cd24391e0fb0beb4bbac4b61a40c6cffbae896dcc76b1db082e\",\"dweb:/ipfs/QmbvpuozfVnqU9nfTcEjpspDkrQVHW1mQHGiwiH8ukdoNM\"]},\"contracts/interfaces/IPayoffProvider.sol\":{\"keccak256\":\"0x803d22f7513c2c5186f77f6bc7cc34673ed762e40f106f9aef512eb9b57018af\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1403986623f860afabf115596051af425c80cc249fb148253a5e87dfd455aed2\",\"dweb:/ipfs/QmUhBNs3KpUEA4KenAcpd5oVQJBGTR5V1u8mX6F8bAg8kc\"]},\"contracts/interfaces/IProduct.sol\":{\"keccak256\":\"0x8e53ea97d8d59519adcbc2aa3600b5e51de1d59efec485a88eca8b574a35a00f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://7da1edcd8f7dc5da9c8ecf338e937499819fb17603909b7d581f6a06286fe6c2\",\"dweb:/ipfs/QmaRHxZToKkQPihgegwv5F9jZTf4Q78WVSPmLNa2wLQoZ8\"]},\"contracts/interfaces/types/Accumulator.sol\":{\"keccak256\":\"0x7ccd0a72aa593cefb9f4337cf312799f357b82fcb3f0379de0dc503d1cb7e387\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://884ee8101d531f8f596620dbe6f513bdaea06c5d113865fabb26131320286341\",\"dweb:/ipfs/QmRKjXfdTPqErTBz4xFvZMTVX88jxKKw14f1rcfAF7Z2Mr\"]},\"contracts/interfaces/types/PackedAccumulator.sol\":{\"keccak256\":\"0xd83f2822d4f6c818087a232b54007730992c34ff77377fc307a282f886e7cf65\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://0c9c635aa32e6feac02cd3d979f21dd01d70fce677da803958a5f7bf8262177d\",\"dweb:/ipfs/QmQnYbmci8WqyBNzvY7cer56Kwf9PU2Rt3GNn5rdzDQzRa\"]},\"contracts/interfaces/types/PackedPosition.sol\":{\"keccak256\":\"0x04968e6794f6244cb3415cea111d640273a81faea957872988d0cb580f45df1e\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://86c7a1c999d14ef22410bca74c51d3fbdf5ad0160a38eaad89c5e38361b981d0\",\"dweb:/ipfs/QmehdLThnFyoEv79C5xoSPmGFPxjmFvMjcCY94BD2iYmKN\"]},\"contracts/interfaces/types/PayoffDefinition.sol\":{\"keccak256\":\"0x99f9b5d5facba16885a375beac2a05129e7b23a8cceee048a7affd7f12a18a8f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://dfaffcac92ebc04fef807ccfae17db0351915e7adb1773ee26334e0587618816\",\"dweb:/ipfs/QmPSDaVSM2z5MrMhUiMFs87irR9kNhhhSQJ1UMLXSkvjPE\"]},\"contracts/interfaces/types/PendingFeeUpdates.sol\":{\"keccak256\":\"0xd98c681bdd6e1808e311615b3c4ac3b557ce5ec461f7b1cc645a51590eaf6f93\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://a59012b0fa282b06a97dec9e0df0523257252284ea34d0b4400af7de70838577\",\"dweb:/ipfs/QmTfNDGMoanmh2znjkqdVR3YgRqZdgPAhQ11c8xaPMLQkw\"]},\"contracts/interfaces/types/Position.sol\":{\"keccak256\":\"0x367918730021f3d6b7035f40c53b00b4316eb5e7fa409ed6285ba6d49971aab1\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://46483854393228b729c6f0aafc419b3971e585e576d1493051fd1f276f14452d\",\"dweb:/ipfs/QmU7PMGN4WZftsQVUzPyucrCFELKhguHVTSTdFbuPwcoZd\"]},\"contracts/interfaces/types/PrePosition.sol\":{\"keccak256\":\"0x4d4443c34648f0352ed7c26ce8b837b6c7613169e53e95d92c8c59ee9e335692\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://c5cd07e3d702a038cc8c99a609245df39c565c5585ca15037c2b47b572e07eac\",\"dweb:/ipfs/Qmca5QAqbKx9UU5Db1UrSuXtTuWQyjkTRDurFK7fLbPu1N\"]},\"contracts/interfaces/types/ProgramInfo.sol\":{\"keccak256\":\"0x280fcaf931b49abaec46b95ccbabaaf856a4b8e8d036413c9c3b3af25585d161\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e755bb9bb2fa8c2f2b20226c214cf7306dfa3d84c7cfc275104b7c546d86334b\",\"dweb:/ipfs/QmbFuHfUek97FYpVQF9hP9pUZUVyTaqejvpZAzbikFWVxn\"]},\"contracts/product/Product.sol\":{\"keccak256\":\"0x746b03c35afb9837e92abb0988c2b544ded788268f6f398c6387c6b5017327de\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://637726d2e5df9127e1044cc9cde71a6494668670a1aeb3879c3a798ff538f57b\",\"dweb:/ipfs/QmbvFZfWntUDfujJ2C2AWE6dgKpHUVgdYHRut4YT7XVRXo\"]},\"contracts/product/UParamProvider.sol\":{\"keccak256\":\"0xdd346fdc4c1e10c093265a811c035f7878e852b104bde73edacc3911f82337ab\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e691f72f5006faea191846f5948b5dd1bc45ed45726484ceed20efc826151708\",\"dweb:/ipfs/QmdYcRWWTyGcj3idLCkeGL8AnHFAUPBJCH3ssr8dZ2WDHN\"]},\"contracts/product/UPayoffProvider.sol\":{\"keccak256\":\"0xb2be54ef6cf8444780f183a32d0ba44618b9868697d7eb0344359bd1ceefa3b8\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d84febed6661f3cf3e8ec5baa6e83604dae7b1c492346a9b2ecb5564e9084d7c\",\"dweb:/ipfs/QmWdHHYqHWiX7STg8xW27gSR43Fg74T1XASn9XteiSXi48\"]},\"contracts/product/types/accumulator/AccountAccumulator.sol\":{\"keccak256\":\"0xda7efcfb641583cc1c7577f4348d97abe9e59989274d7bb166da2b19ebffd67a\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b0e5c9c2b8d7297cf3becea46412fc4adde42ddda3500944a8f75c8d004d1e34\",\"dweb:/ipfs/QmP2KQwbixuSCwZFdQX2uXBL9oXYBQQefbXvofZ3JX6PTx\"]},\"contracts/product/types/accumulator/VersionedAccumulator.sol\":{\"keccak256\":\"0xfa6c397bf064a7a7767c30f1c9be017a92b0a5f24f59ff1a132b81cd69f5c60a\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://c06c04121938bc5ccc53482eb9c5eb510ccf833d1e99f47dd72c51ee6fd9a1d3\",\"dweb:/ipfs/QmZegN29oqYbVjWQS3fLEC6HqamqwLBKP2aS56eo3aAg9q\"]},\"contracts/product/types/position/AccountPosition.sol\":{\"keccak256\":\"0x54bf5a232b1c14887a717bee9e935ac9f0f5de671a863cf2fcdbc1fd19a4dc85\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://993c7c9eb4da8573cb53fb282bb51d0aceb237de173391faad3bed232fb394b6\",\"dweb:/ipfs/QmYbWoMdtiJAPJeFY7WdmvD3weZ75bcLDH4ZdrPGHViPHZ\"]},\"contracts/product/types/position/VersionedPosition.sol\":{\"keccak256\":\"0x7e7314dc2829b47f03af3046280edb01a0bbe91cc63456f831f810eced8c1902\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://f1e13bb157fa60a63349a2139a7644868b70d9d23a49a3dea2581ea8926ed20a\",\"dweb:/ipfs/QmQGpogHBaXtbAuoGgTHHt4jBSNpD9NQsW6JfY3sRzAEic\"]}},\"version\":1}", - "bytecode": "0x6080806040523461001757615fdc90816200001d8239f35b600080fdfe60806040526004361015610013575b600080fd5b60003560e01c806305d5c1cb146103fb57806306fdde03146103f25780630dbc9ce1146103e957806311da60b4146103e0578063153261e5146103d757806319377567146103ce5780631cb44dfc146103c55780631e0c6fb9146103bc57806320fe9c3c146103b3578063212e0ad3146103aa5780632131ea4a146103a15780632d2e52be146103985780633a25c1111461038f5780633e17b8c71461038657806343f0179b1461037d578063476fa96d1461037457806354fb39211461036b57806356bc1ad41461036257806358ca6f981461035957806359218fe914610350578063597e1fb51461034757806359ea287d1461033e5780635d16e1201461033557806360ec91d61461032c578063611c71b4146103235780636943b0171461031a5780636c376cc5146103115780636ecffff91461030857806373b88f3b146102ff57806376f37001146102f65780637dc0d1d0146102ed5780637ece075d146102e45780638c94b48f146102db5780638e480b20146102d257806391689024146102c95780639378bf7b146102c057806395d89b41146102b75780639a427d03146102ae5780639d888e86146102a5578063a12e1b331461029c578063ab582f2914610293578063b7648fb91461028a578063c07f47d414610281578063d7d7d6b814610278578063e1c3c98d1461026f578063e503b00714610266578063f667f8971461025d578063f6b3200814610254578063f77c47911461024b5763fc741c7c1461024357600080fd5b61000e6123b0565b5061000e612379565b5061000e6122c2565b5061000e612201565b5061000e6120cc565b5061000e611fc5565b5061000e611f01565b5061000e611ee2565b5061000e611e9d565b5061000e611e47565b5061000e611e1e565b5061000e611d45565b5061000e611d0f565b5061000e611cde565b5061000e611b95565b5061000e611b50565b5061000e611b12565b5061000e611a0b565b5061000e6119dd565b5061000e61197d565b5061000e6118c1565b5061000e6117eb565b5061000e611646565b5061000e61161a565b5061000e611576565b5061000e61146f565b5061000e61140d565b5061000e6113e1565b5061000e6113b9565b5061000e61138b565b5061000e6112db565b5061000e611295565b5061000e61118e565b5061000e611087565b5061000e61105c565b5061000e611030565b5061000e610f29565b5061000e610ebf565b5061000e610d66565b5061000e610bf4565b5061000e610ae2565b5061000e610a90565b5061000e610a3a565b5061000e6108e7565b5061000e6108aa565b5061000e61075e565b5061000e610676565b5061000e61064a565b5061000e61061a565b5061000e61042f565b600091031261000e57565b6002111561041957565b634e487b7160e01b600052602160045260246000fd5b503461000e57600036600319011261000e57606061044b61490e565b60405190805161045a8161040f565b8252602081015161046a8161040f565b6020830152604061ffff19910151166040820152f35b50634e487b7160e01b600052600060045260246000fd5b90600182811c921680156104c7575b60208310146104b157565b634e487b7160e01b600052602260045260246000fd5b91607f16916104a6565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101761050b57604052565b6105136104d1565b604052565b906105c4575b6040519081600082549261053184610497565b9081845260019485811690816000146105a1575060011461055e575b505061055b925003826104e8565b90565b9093915060005260209081600020936000915b81831061058957505061055b9350820101388061054d565b85548784018501529485019486945091830191610571565b91505061055b94506020925060ff191682840152151560051b820101388061054d565b6105cc610480565b61051e565b6020808252825181830181905290939260005b82811061060657505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016105e4565b503461000e57600036600319011261000e5761064661063a600080610518565b604051918291826105d1565b0390f35b503461000e57600036600319011261000e576020600080516020615e6783398151915254604051908152f35b503461000e5760008060031936011261075b57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561073c575b839161070e575b506106fc576001906106f7612663565b505580f35b604051633b3b4caf60e21b8152600490fd5b61072f915060203d8111610735575b61072781836104e8565b8101906125fa565b386106e7565b503d61071d565b61074461260f565b6106e0565b604051637990191b60e11b8152600490fd5b80fd5b503461000e57608036600319011261000e5761079061078b600080516020615f6783398151915254611971565b611971565b604051633e92a73360e11b8152906020908183806107b13060048301613d24565b0381845afa92831561089d575b60009361086e575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610861575b600092610834575b5050336001600160a01b0390911603610816576108146004614674565b005b60405163123d8bcf60e21b81526004810191909152602490fd5b0390fd5b6108539250803d1061085a575b61084b81836104e8565b81019061263d565b38806107f7565b503d610841565b61086961260f565b6107ef565b61088f919350823d8411610896575b61088781836104e8565b810190613c8b565b91386107c6565b503d61087d565b6108a561260f565b6107be565b503461000e57600036600319011261000e576020600080516020615f4783398151915254604051908152f35b6001600160a01b0381160361000e57565b503461000e5760208060031936011261000e5760043590610907826108d6565b61092261078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806109413060048301613d24565b0381845afa9283156109ec575b6000936109cd575b50604051635091e19f60e11b815260048101849052908290829060249082905afa9182156109c0575b6000926109a3575b5050336001600160a01b03909116036108165761081482613d81565b6109b99250803d1061085a5761084b81836104e8565b3880610987565b6109c861260f565b61097f565b6109e5919350823d84116108965761088781836104e8565b9138610956565b6109f461260f565b61094e565b60208091805184520151910152565b610a38909291926060604060a083019580518452610a2e602082015160208601906109f9565b01519101906109f9565b565b503461000e57602036600319011261000e57600435610a58816108d6565b610a60613a70565b5060018060a01b03166000526002602052610646610a846002604060002001612d5c565b60405191829182610a08565b503461000e57602036600319011261000e57610aaa6131d2565b50610646610abb600435600a6150c5565b604051918291829190916020806040830194805184520151910152565b8015150361000e57565b503461000e5760208060031936011261000e5760043590610b0282610ad8565b610b1d61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380610b3c3060048301613d24565b0381845afa928315610be7575b600093610bc8575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610bbb575b600092610b9e575b5050336001600160a01b03909116036108165761081482613d37565b610bb49250803d1061085a5761084b81836104e8565b3880610b82565b610bc361260f565b610b7a565b610be0919350823d84116108965761088781836104e8565b9138610b51565b610bef61260f565b610b49565b503461000e5760408060031936011261000e576004803590610c15826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610d4c575b600091610d2f575b50610d1f57808616331491858315610cc0575b505050905015610ca357600184610ca060243586613364565b55005b51636dc3a3c360e01b815290819061083090339085908401612d07565b9193819350855192838092630479e58f60e41b82525afa918215610d12575b600092610cf5575b505016331480388085610c87565b610d0b9250803d1061085a5761084b81836104e8565b3880610ce7565b610d1a61260f565b610cdf565b50505051633b3b4caf60e21b8152fd5b610d469150833d85116107355761072781836104e8565b38610c74565b610d5461260f565b610c6c565b51637990191b60e11b8152fd5b503461000e5760408060031936011261000e576004803590610d87826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610eb2575b600091610e95575b50610d1f57600080516020615ec783398151915254610e8557808616331491858315610e26575b505050905015610ca357600184610ca060243586613504565b9193819350855192838092630479e58f60e41b82525afa918215610e78575b600092610e5b575b505016331480388085610e0d565b610e719250803d1061085a5761084b81836104e8565b3880610e4d565b610e8061260f565b610e45565b5050505163ded15dbf60e01b8152fd5b610eac9150833d85116107355761072781836104e8565b38610de6565b610eba61260f565b610dde565b503461000e57600036600319011261000e5760c0610edb613ebe565b6040519080511515825260a060018060401b039182602082015116602085015260408101511515604085015282606082015116606085015260808101511515608085015201511660a0820152f35b503461000e5760208060031936011261000e57610f5761078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380610f763060048301613d24565b0381845afa928315611023575b600093611004575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610ff7575b600092610fda575b5050336001600160a01b0390911603610816576108146004356140ee565b610ff09250803d1061085a5761084b81836104e8565b3880610fbc565b610fff61260f565b610fb4565b61101c919350823d84116108965761088781836104e8565b9138610f8b565b61102b61260f565b610f83565b503461000e57600036600319011261000e576020600080516020615ea783398151915254604051908152f35b503461000e57602036600319011261000e576110766131d2565b50610646610abb600435600a615130565b503461000e5760208060031936011261000e576110b561078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806110d43060048301613d24565b0381845afa928315611181575b600093611162575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611155575b600092611138575b5050336001600160a01b03909116036108165761081460043561443e565b61114e9250803d1061085a5761084b81836104e8565b388061111a565b61115d61260f565b611112565b61117a919350823d84116108965761088781836104e8565b91386110e9565b61118961260f565b6110e1565b503461000e5760208060031936011261000e576111bc61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806111db3060048301613d24565b0381845afa928315611288575b600093611269575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561125c575b60009261123f575b5050336001600160a01b039091160361081657610814600435613f8e565b6112559250803d1061085a5761084b81836104e8565b3880611221565b61126461260f565b611219565b611281919350823d84116108965761088781836104e8565b91386111f0565b61129061260f565b6111e8565b503461000e57602036600319011261000e576004356112b3816108d6565b60018060a01b03166000526002602052602060ff600760406000200154166040519015158152f35b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561137e575b600091611360575b506106fc57600190610ca060043533613809565b611378915060203d81116107355761072781836104e8565b3861134c565b61138661260f565b611344565b503461000e57600036600319011261000e576020600080516020615ec7833981519152546040519015158152f35b503461000e57600036600319011261000e576113d3613a70565b50610646610a846004612d5c565b503461000e57600036600319011261000e576020600080516020615e0783398151915254604051908152f35b503461000e57604036600319011261000e576020611467611442611435600435602435613c65565b61143d613e25565b613aaf565b611462670de0b6b3a764000061145c816301e133806130db565b926130db565b613c04565b604051908152f35b503461000e5760208060031936011261000e5761149d61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806114bc3060048301613d24565b0381845afa928315611569575b60009361154a575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561153d575b600092611520575b5050336001600160a01b039091160361081657610814600435614310565b6115369250803d1061085a5761084b81836104e8565b3880611502565b61154561260f565b6114fa565b611562919350823d84116108965761088781836104e8565b91386114d1565b61157161260f565b6114c9565b503461000e57602036600319011261000e57600435611594816108d6565b60018060a01b0316600052600260205261064660406000206115ef604051916115be6060846104e8565b6115c781612d3c565b835260ff60076115d960028401612d5c565b92836020870152015416151560408401526148d6565b9081611609575b5060405190151581529081906020820190565b6116149150516148f7565b386115f6565b503461000e57600036600319011261000e576020600080516020615d4783398151915254604051908152f35b503461000e5760031960203682011261000e57600435906001600160401b03821161000e576102008260040191833603011261000e5760017f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b81815410156117d257819055600080516020615de783398151915292818455303b1515806117ca575b6117b857333b156117a6577fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f32936117906117896117a195602460009533600080516020615f678339815191525561172e61172460a483016123dc565b604483019061496f565b6117366125c1565b61176e611747366101848401612402565b61016483013561014484013561012485013561010486013560e487013560c4880135613d96565b61178261177b8480612466565b90896124ec565b0190612466565b90856124ec565b556040519081529081906020820190565b0390a1005b6040516314878b6960e01b8152600490fd5b604051631a27c4a960e21b8152600490fd5b5060006116c8565b604051631e7a9d9560e01b815260048101839052602490fd5b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156118b4575b600091611896575b506106fc57600080516020615ec78339815191525461188457600190610ca060043533612d21565b60405163ded15dbf60e01b8152600490fd5b6118ae915060203d81116107355761072781836104e8565b3861185c565b6118bc61260f565b611854565b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611964575b600091611946575b506106fc57600190610ca060043533613364565b61195e915060203d81116107355761072781836104e8565b38611932565b61196c61260f565b61192a565b6001600160a01b031690565b503461000e57600036600319011261000e57600080516020615da7833981519152546040516001600160a01b039091168152602090f35b6040809180518452602081015160208501520151910152565b606081019291610a3891906119b4565b503461000e57602036600319011261000e5760606119fc600435614b96565b611a0960405180926119b4565bf35b503461000e5760208060031936011261000e57611a3961078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380611a583060048301613d24565b0381845afa928315611b05575b600093611ae6575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611ad9575b600092611abc575b5050336001600160a01b039091160361081657610814600435614553565b611ad29250803d1061085a5761084b81836104e8565b3880611a9e565b611ae161260f565b611a96565b611afe919350823d84116108965761088781836104e8565b9138611a6d565b611b0d61260f565b611a65565b503461000e57602036600319011261000e57600435611b30816108d6565b60018060a01b031660005260096020526020604060002054604051908152f35b503461000e57602036600319011261000e57600435611b6e816108d6565b60018060a01b031660005260026020526020611467611b906040600020612d3c565b615a77565b503461000e5760408060031936011261000e576004803590611bb6826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115611cd1575b600091611cb4575b50610d1f57600080516020615ec783398151915254610e8557808616331491858315611c55575b505050905015610ca357600184610ca060243586612d21565b9193819350855192838092630479e58f60e41b82525afa918215611ca7575b600092611c8a575b505016331480388085611c3c565b611ca09250803d1061085a5761084b81836104e8565b3880611c7c565b611caf61260f565b611c74565b611ccb9150833d85116107355761072781836104e8565b38611c15565b611cd961260f565b611c0d565b503461000e57600036600319011261000e5761064661063a60006001610518565b604081019291610a3891906109f9565b503461000e57602036600319011261000e57611d296131d2565b506040611d396004356003615c0f565b611a09825180926109f9565b503461000e57600036600319011261000e57611d5f61261c565b50600080516020615da783398151915254604051634ec4474360e11b81526060916119fc91908390829060049082906001600160a01b03165afa908115611ddc575b600091611daf575b50614cd1565b611dcf9150833d8111611dd5575b611dc781836104e8565b810190614b63565b38611da9565b503d611dbd565b611de461260f565b611da1565b6060908051600f0b83526020810151600f0b60208401526040810151600f0b60408401528160018060801b0391015116910152565b503461000e57600036600319011261000e576080611e3a613e25565b611a096040518092611de9565b503461000e57602036600319011261000e57600435611e65816108d6565b60018060a01b031660005260026020526020611467611b906040600020611e976002611e9083612d3c565b9201612d5c565b906131ed565b503461000e57602036600319011261000e57600435611ebb816108d6565b611ec36131d2565b5060018060a01b031660005260026020526040611d3981600020612d3c565b503461000e57600036600319011261000e576020600a54604051908152f35b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611fb8575b600091611f9a575b506106fc57600080516020615ec78339815191525461188457600190610ca060043533613504565b611fb2915060203d81116107355761072781836104e8565b38611f72565b611fc061260f565b611f6a565b503461000e5760208060031936011261000e57611ff361078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806120123060048301613d24565b0381845afa9283156120bf575b6000936120a0575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215612093575b600092612076575b5050336001600160a01b039091160361081657610814600435614047565b61208c9250803d1061085a5761084b81836104e8565b3880612058565b61209b61260f565b612050565b6120b8919350823d84116108965761088781836104e8565b9138612027565b6120c761260f565b61201f565b503461000e5760408060031936011261000e5760048035906120ed826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa9081156121f4575b6000916121d7575b50610d1f57808616331491858315612178575b505050905015610ca357600184610ca060243586613809565b9193819350855192838092630479e58f60e41b82525afa9182156121ca575b6000926121ad575b50501633148038808561215f565b6121c39250803d1061085a5761084b81836104e8565b388061219f565b6121d261260f565b612197565b6121ee9150833d85116107355761072781836104e8565b3861214c565b6121fc61260f565b612144565b503461000e57602036600319011261000e5760043561221f816108d6565b600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156122b5575b600091612297575b506106fc57610ca0600192612291612663565b9061298a565b6122af915060203d81116107355761072781836104e8565b3861227e565b6122bd61260f565b612276565b503461000e57602036600319011261000e576004356122e0816108d6565b600460206122ff61078b600080516020615f6783398151915254611971565b60405163d8dfeb4560e01b815292839182905afa90811561236c575b60009161234e575b506001600160a01b0316330361233c57610814906139eb565b6040516340cbe9b160e01b8152600490fd5b612366915060203d811161085a5761084b81836104e8565b38612323565b61237461260f565b61231b565b503461000e57600036600319011261000e57600080516020615f67833981519152546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600080516020615e8783398151915254604051908152f35b3561055b816108d6565b90610a3860405192836104e8565b359081600f0b820361000e57565b919082608091031261000e5760405161241c6080826104e8565b60608193612429816123f4565b8352612437602082016123f4565b6020840152612448604082016123f4565b60408401520135906001600160801b038216820361000e5760600152565b903590601e198136030182121561000e57018035906001600160401b03821161000e5760200191813603831361000e57565b90601f81116124a657505050565b600091825260208220906020601f850160051c830194106124e2575b601f0160051c01915b8281106124d757505050565b8181556001016124cb565b90925082906124c2565b9092916001600160401b0381116125b4575b6125128161250c8454610497565b84612498565b6000601f821160011461254c5781929394600092612541575b50508160011b916000199060031b1c1916179055565b01359050388061252b565b601f1982169461256184600052602060002090565b91805b87811061259c575083600195969710612582575b505050811b019055565b0135600019600384901b60f8161c19169055388080612578565b90926020600181928686013581550194019101612564565b6125bc6104d1565b6124fe565b303b1515806125e3575b6117b8576001600080516020615e4783398151915255565b50600080516020615de783398151915254156125cb565b9081602091031261000e575161055b81610ad8565b506040513d6000823e3d90fd5b6040519061262b6060836104e8565b60006040838281528260208201520152565b9081602091031261000e575161055b816108d6565b908152602081019190915260400190565b61266b61261c565b50612684600080516020615f6783398151915254611971565b9061268d614c7c565b91600a5490835182146128e6576126a382614b96565b906126b085516004612916565b855181036128d7575084915b604051631bf1901f60e21b81526001600160a01b03926020929084169184908481600481875afa9081156128ca575b6000916128ad575b501690813b1561000e5760405163a55ff01d60e01b81528992600090829081838161272189600483016119cd565b03925af180156128a0575b61288b575b506127558661274d81612742613c9a565b94600386600a615171565b986003615c6e565b61275d6146cc565b8551825103612857575b5050816004916040519283809263d8dfeb4560e01b82525afa91821561284a575b60009261282d575b50501691823b1561000e57604051637f3dd53b60e01b815260048101919091527f88a84ea6dd274b386afd27dbbe11b6192b25017f5e60bb8c4053dfddb45c294d926000908290602490829084905af18015612820575b612805575b505183519061280060405192839283612652565b0390a1565b80612814600061281a936104e8565b80610404565b386127ec565b61282861260f565b6127e7565b6128439250803d1061085a5761084b81836104e8565b3880612790565b61285261260f565b612788565b6004929661286e859388600361287495600a615171565b90612901565b956128828987516003615c6e565b91889150612767565b80612814600061289a936104e8565b38612731565b6128a861260f565b61272c565b6128c49150853d871161085a5761084b81836104e8565b386126f3565b6128d261260f565b6126eb565b6128e090614b96565b916126bc565b5050565b50634e487b7160e01b600052601160045260246000fd5b9190820180921161290e57565b610a386128ea565b5480612920575090565b9050600181018091116129305790565b61055b6128ea565b9060018060a01b0316600052602052604060002090565b6001600160a01b039091168152608081019291610a3891602001906119b4565b6001600160a01b039091168152602081019190915260400190565b6129a2600080516020615f6783398151915254611971565b6129ad826009612938565b54835114612cc4576129cd60026129c48482612938565b01845190612916565b83518103612cb5575082915b60018060a01b038092166040805194631bf1901f60e21b9283875260208660049882818b81875afa908115612ca8575b600091612c8b575b5016803b1561000e578792878a92600088518092818381612a408d63060c0d2760e21b998a84528c840161294f565b03925af18015612c7e575b612c69575b50612a7c612a77612a628b6009612938565b612a6d8c6002612938565b600a8a5192614fbb565b612ce5565b97612a9187612a8c8c6002612938565b6159e5565b86518d5103612b85575b5050829086519283809263d8dfeb4560e01b82525afa918215612b78575b600092612b5b575b505016803b1561000e576000612b3494612b139287837f9d7055d24918d8c2fd08660a27bf31d4086fa71a51cd07874276470223aa480f9b8851968795869485936364e5a46f60e11b8552840161296f565b03925af18015612b4e575b612b39575b505195519051938493169583612652565b0390a2565b806128146000612b48936104e8565b38612b23565b612b5661260f565b612b1e565b612b719250803d1061085a5761084b81836104e8565b3880612ac1565b612b8061260f565b612ab9565b909491979250865190815283818c818b5afa908115612c5c575b600091612c3f575b5016803b1561000e57612c158a92612c0f612a778b8f808f9a838b998f60008094612bde8f9351978896879586948552840161294f565b03925af18015612c32575b612c1d575b50600a612c07612bff846009612938565b936002612938565b915192614fbb565b90612cc9565b969038612a9b565b806128146000612c2c936104e8565b38612bee565b612c3a61260f565b612be9565b612c569150843d861161085a5761084b81836104e8565b38612ba7565b612c6461260f565b612b9f565b806128146000612c78936104e8565b38612a50565b612c8661260f565b612a4b565b612ca29150833d851161085a5761084b81836104e8565b38612a11565b612cb061260f565b612a09565b612cbe90614b96565b916129d9565b505050565b9190916000838201938412911290801582169115161761290e57565b6020815191015190600082820192831291129080158216911516176129305790565b6001600160a01b0391821681529116602082015260400190565b90610a3891612d37612d31612663565b8261298a565b612d94565b90604051612d4b6040826104e8565b602060018294805484520154910152565b90604051612d6b6060826104e8565b6040612d8f6003839580548552612d8460018201612d3c565b602086015201612d3c565b910152565b60018060a01b03908181166000526020916002835260409360ff600786600020015416612f3b5790612dc7849284612f4c565b81612de361078b600080516020615f6783398151915254611971565b9186519586809463d8dfeb4560e01b825260049889915afa928315612f2e575b600093612f0f575b5086516301c8232360e71b8152928391829081612e2b308a8c8401612d07565b0392165afa918215612f02575b600092612ee5575b5050612ed657612e54612e59916002612938565b615b55565b612ec857600080516020615ec7833981519152546128e657612e90612e8b612e82600a54613a9b565b611e9784612d5c565b6132c5565b91612ea3670de0b6b3a7640000846131a4565b15612ead57505050565b5163d8b8b95160e01b81529081019182529081906020010390fd5b90516390898fd160e01b8152fd5b5090516324a21d2960e01b8152fd5b612efb9250803d106107355761072781836104e8565b3880612e40565b612f0a61260f565b612e38565b612f27919350823d841161085a5761084b81836104e8565b9138612e0b565b612f3661260f565b612e03565b8451636830d4d760e01b8152600490fd5b90612f58600a54614b96565b90612f72816002612f698682612938565b01845190613342565b612f7f8183516004613342565b612fae612f98612f9260408501516131c1565b8361318d565b600080516020615ea7833981519152549061318d565b9182612fe4575b516040516001600160a01b0390941693600080516020615d878339815191529350918291612b34919083612652565b61303d6004602061300661078b600080516020615f6783398151915254611971565b60405163d8dfeb4560e01b815292839182905afa9081156130ce575b6000916130b0575b506001600160a01b03169360001961310c565b833b1561000e576000613078600080516020615d878339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156130a3575b61308e575b50612fb5565b80612814600061309d936104e8565b38613088565b6130ab61260f565b613083565b6130c8915060203d811161085a5761084b81836104e8565b3861302a565b6130d661260f565b613022565b818102929160008212600160ff1b8214166130ff575b818405149015171561290e57565b6131076128ea565b6130f1565b60008113613135576000136131215750600090565b61312d61055b9161313b565b6000196130db565b5061055b905b6001600160ff1b03811161314c5790565b6024906040519062a07eb560e01b82526004820152fd5b8181029291811591840414171561290e57565b50634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916131a091613163565b0490565b8181116131ba57106131b557600190565b600090565b5050600290565b60008082126131ce575090565b0390565b604051906131e16040836104e8565b60006020838281520152565b90604061320b61055b936131ff6131d2565b50602084015190613214565b91015190613272565b9061321d6131d2565b5060208083519383518501809511613265575b01519101518101809111613258575b6040519161324e6040846104e8565b8252602082015290565b6132606128ea565b61323f565b61326d6128ea565b613230565b9061327b6131d2565b50602080835193835185039485116132ab575b01519101518103908111613258576040519161324e6040846104e8565b6132b36128ea565b61328e565b9190820391821161290e57565b602081015160009190806132e257505050670de0b6b3a764000090565b6132ec9151613308565b670de0b6b3a7640000915080821015613303575090565b905090565b670de0b6b3a764000090818102918183041490151715613335575b811561332d570490565b6131a0613176565b61333d6128ea565b613323565b9091600282018054918201809211613358575555565b6133606128ea565b5555565b61336f612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb5761339e916133dd565b60005260026020526133b36040600020615bbb565b6133b957565b604051633975ab9360e01b8152600490fd5b604051636830d4d760e01b8152600490fd5b906133e9600a54614b96565b906134038160026133fa8682612938565b018451906134ee565b61341081835160046134ee565b613423612f98612f9260408501516131c1565b9182613459575b516040516001600160a01b0390941693600080516020615e278339815191529350918291612b34919083612652565b61347b6004602061300661078b600080516020615f6783398151915254611971565b833b1561000e5760006134b6600080516020615e278339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156134e1575b6134cc575b5061342a565b8061281460006134db936104e8565b386134c6565b6134e961260f565b6134c1565b9091600482018054918201809211613358575555565b90613516613510612663565b8361298a565b600a54156136aa5760018060a01b03918281166000526020926002845260409260ff60078560002001541661369957906135518592846136bc565b8161356d61078b600080516020615f6783398151915254611971565b9185519687809463d8dfeb4560e01b82526004998a915afa92831561368c575b60009361366d575b5085516301c8232360e71b81529283918290816135b5308a8d8401612d07565b0392165afa918215613660575b600092613643575b505061363557612e546135de916002612938565b613628576136136135fc6135f3600a54613a9b565b611e9785612d5c565b51600080516020615f4783398151915254906137e3565b61361b575050565b5163677e872f60e11b8152fd5b516390898fd160e01b8152fd5b50516324a21d2960e01b8152fd5b6136599250803d106107355761072781836104e8565b38806135ca565b61366861260f565b6135c2565b613685919350823d841161085a5761084b81836104e8565b9138613595565b61369461260f565b61358d565b8351636830d4d760e01b8152600490fd5b60405163c25d67ab60e01b8152600490fd5b906136c8600a54614b96565b906136e28160026136d98682612938565b018451906137f3565b6136ef81835160046137f3565b613718613702612f9260408501516131c1565b600080516020615e87833981519152549061318d565b918261374e575b516040516001600160a01b0390941693600080516020615f278339815191529350918291612b34919083612652565b6137706004602061300661078b600080516020615f6783398151915254611971565b833b1561000e5760006137ab600080516020615f278339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156137d6575b6137c1575b5061371f565b8061281460006137d0936104e8565b386137bb565b6137de61260f565b6137b6565b6002916137ef916131a4565b1490565b9091600182018054918201809211613358575555565b90610a3891613819612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb57613848916138c4565b600052600260205261385d6040600020615bbb565b6133b957600080516020615ec783398151915254610a3857613890612e8b613886600a54613a9b565b611e976004612d5c565b6138a2670de0b6b3a7640000826131a4565b156138aa5750565b60405163d8b8b95160e01b81526004810191909152602490fd5b906138d0600a54614b96565b906138ea8160026138e18682612938565b018451906139d5565b6138f781835160046139d5565b61390a613702612f9260408501516131c1565b9182613940575b516040516001600160a01b0390941693600080516020615f878339815191529350918291612b34919083612652565b6139626004602061300661078b600080516020615f6783398151915254611971565b833b1561000e57600061399d600080516020615f878339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156139c8575b6139b3575b50613911565b8061281460006139c2936104e8565b386139ad565b6139d061260f565b6139a8565b9091600382018054918201809211613358575555565b600080516020615ec78339815191525461188457600790613a0d612d31612663565b613a6260018060a01b038216918260005260026020526020613a4f604060002094613a3786612d3c565b9060005260028352611e976002604060002001612d5c565b613a5a8151846138c4565b0151906133dd565b01805460ff19166001179055565b60405190613a7f6060836104e8565b8160008152613a8c6131d2565b60208201526040612d8f6131d2565b61055b90613aa76131d2565b506003615c0f565b60608101519091906001600160801b0316613aca81836131a4565b15613b1257670de0b6b3a764000090613ae382846131a4565b15613af55750505060200151600f0b90565b9083916020604061055b960151930151600f0b92600f0b90613b28565b9161055b9260408251920151600f0b91600f0b60005b90929391613b3682846131a4565b158015613bd8575b613bc65761055b94613b94613b8f83613b9a9686670de0b6b3a7640000976114629703928311613bb9575b8986039560008b128015828913169188121617613bac575b8103908111613b9f57613308565b61313b565b906130db565b612cc9565b613ba76128ea565b613308565b613bb46128ea565b613b81565b613bc16128ea565b613b69565b604051630db0f7cb60e01b8152600490fd5b506002613be582856131a4565b14613b3e565b8181039291600013801582851316918412161761290e57565b8115613c2c575b600160ff1b8114600019831416613c20570590565b613c286128ea565b0590565b613c34613176565b613c0b565b61146261055b92670de0b6b3a7640000926130db565b90611462670de0b6b3a764000061055b936130db565b9080613c825750613c7c57670de0b6b3a764000090565b60001990565b61055b91613308565b9081602091031261000e575190565b600080516020615e0783398151915254600080516020615f678339815191525460405163e975c0c360e01b815290602090829060049082906001600160a01b03165afa908115613d17575b600091613cf9575b50808210613303575090565b613d11915060203d81116108965761088781836104e8565b38613ced565b613d1f61260f565b613ce5565b6001600160a01b03909116815260200190565b7f482763b305ee10cd21c16c0cbeed259f2e4fcacdc9767cef16dc1fbe483d34886020613d62612663565b83600080516020615ec7833981519152555192604051938452151592a2565b600a54610a38916001600160a01b0316614c17565b95949295939093303b151580613de7575b6117b857610a3896613dd3613ddd94613dce613de298613dc9613dd896613f43565b613fe1565b61409a565b6142bc565b6143ea565b614518565b6145a6565b50600080516020615de78339815191525415613da7565b60405190613e0d6080836104e8565b60006060838281528260208201528260408201520152565b613e2d613dfe565b50613e36613dfe565b50604051613e456080826104e8565b600080516020615f078339815191525480600f0b825260801d600f0b6020820152600080516020615ee78339815191525480600f0b604083015260801c606082015290565b60405190613e9960c0836104e8565b8160a06000918281528260208201528260408201528260608201528260808201520152565b613ec6613e8a565b50613ecf613e8a565b50604051613ede60c0826104e8565b600080516020615d678339815191525460ff808216151583526001600160401b03600883901c81166020850152604883901c821615156040850152605083901c81166060850152609083901c9091161515608084015260989190911c1660a082015290565b7f18eb97ecd7366a8be310b7e675d67335c7604d5f47446a54a222473625a27e229080600080516020615d4783398151915255613f7e6147b4565b9061280060405192839283612652565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015613fd4575b613fc3575b50613f43565b6000613fce916104e8565b38613fbd565b613fdc61260f565b613fb8565b6002613ff5670de0b6b3a7640000836131a4565b1461403557807fb2743902575ffdab882dfa43a3501f82fbbefa0d2c637e393aed1e80e2cb840b91600080516020615e0783398151915255613f7e6147b4565b604051632012d38160e11b8152600490fd5b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af1801561408d575b61407c575b50613fe1565b6000614087916104e8565b38614076565b61409561260f565b614071565b60026140ae670de0b6b3a7640000836131a4565b1461403557807f6bf5f38f4e94f47ae7a4d6e56dbf388c856f890b5f0f2808b66914710b0266ca91600080516020615e8783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156141e1575b6141d0575b50614121614833565b6141c7576002614139670de0b6b3a7640000836131a4565b1461403557614146613ebe565b6001600160401b038083116141ae579161419e612800927f5dcd1837ba774ef7f1f06e50ad3f64097201da74055346f26a4c7dea9af9084e948316602082015260018152600080516020615d678339815191526141ee565b6040519081529081906020820190565b60405163477e89e360e01b815260048101849052602490fd5b610a389061409a565b60006141db916104e8565b38614118565b6141e961260f565b614113565b81518154602084015160408501516060860151600160501b600160901b0360509190911b166001600160901b031990931693151560ff1693909317610100600160481b0360089290921b919091161760ff60481b92151560481b9290921691909117178155610a38916142969060a09061428861426e6080830151151590565b855460ff60901b191690151560901b60ff60901b16178555565b01516001600160401b031690565b8154600160981b600160d81b03191660989190911b600160981b600160d81b0316179055565b60026142d0670de0b6b3a7640000836131a4565b1461403557807f8e37539629486a88c6a6083eb90030fb61cb856d56d96f53a326fda0d399ef3291600080516020615ea783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156143dd575b6143cc575b50614343614833565b6143c357600261435b670de0b6b3a7640000836131a4565b1461403557614368613ebe565b6001600160401b038083116141ae579161419e612800927f4024ee9b51b90807c93e46f7e500580ef5b0b8491e1105188a44f62eed26b129948316606082015260016040820152600080516020615d678339815191526141ee565b610a38906142bc565b60006143d7916104e8565b3861433a565b6143e561260f565b614335565b60026143fe670de0b6b3a7640000836131a4565b1461403557807fd07cf37924efa8fca893c372ddfb1614e6fd8c02cfcc9205262535680b77b93491600080516020615e6783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af1801561450b575b6144fa575b50614471614833565b6144f1576002614489670de0b6b3a7640000836131a4565b1461403557614496613ebe565b6001600160401b038083116141ae579161419e612800927f75d77d82706bf877275b9bc542ae4f30aca347d73558e05b56b35a1452f8613294831660a082015260016080820152600080516020615d678339815191526141ee565b610a38906143ea565b6000614505916104e8565b38614468565b61451361260f565b614463565b7fec4e0c10e4e0d362960c0114996546aa9c4d6cc297b00a7577e127b720791beb9080600080516020615f4783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015614599575b614588575b50614518565b6000614593916104e8565b38614582565b6145a161260f565b61457d565b60a07fb08b24c7f4e8b392d39bbaf1f4aa9bbb733ba9a467559eb8d9e2ffb634658e9091805161463860018060801b031991600080516020615f0783398151915261460a8482541660018060801b03938416178083556020870151600f0b90614657565b90556040840151600080516020615ee783398151915293845416908216179081845560608501511690614657565b90556146426147b4565b61464f6040518093611de9565b6080820152a1565b6001600160801b031660809190911b6001600160801b0319161790565b303b1561000e57604051630476982d60e21b8152610a3891613de29160008160048183305af180156146bf575b6146ae575b503690612402565b60006146b9916104e8565b386146a6565b6146c761260f565b6146a1565b6146d4613ebe565b80511590811580926147a7575b801561479a575b156128e657610a389161477e575b6040810151614762575b6080810151614746575b6147328160a06000918281528260208201528260408201528260608201528260808201520152565b600080516020615d678339815191526141ee565b60a081015161475d906001600160401b03166143ea565b61470a565b6060810151614779906001600160401b03166142bc565b614700565b6020810151614795906001600160401b031661409a565b6146f6565b50608081015115156146e8565b50604081015115156146e1565b303b156131b55760405163301fd1f560e21b8152602081600481305afa9081156147fc575b6000916147e4575090565b61055b915060203d81116108965761088781836104e8565b61480461260f565b6147d9565b919082604091031261000e576040516148236040826104e8565b6020808294805184520151910152565b6040516359ea287d60e01b815260a081600481305afa80156148c9575b600090614862575b61055b91506148d6565b60a03d81116148c2575b61487681846104e8565b82019060a08383031261075b5750906148b861055b9260606040519361489c82866104e8565b805185526148ad8360208301614809565b602086015201614809565b6040820152614858565b503d61486c565b6148d161260f565b614850565b6148e360208201516148f7565b90816148ed575090565b61055b9150604001515b8051159081614904575090565b6020915001511590565b61491661261c565b5061491f61261c565b5060405161492e6060826104e8565b600080516020615dc78339815191525460ff811661494b8161040f565b825260ff8160081c1661495d8161040f565b602083015261ffff1916604082015290565b303b151580614a33575b6117b857614992906000906001600160a01b0316614c17565b6149a461499f3683614a54565b614aa7565b15614a21576149b4903690614a54565b8051906149c08261040f565b6149c98261040f565b600080516020615dc78339815191529160ff83549116908160ff198216178455604061ff0060208501516149fc8161040f565b614a058161040f565b60081b1693848461ffff19809516171786550151169117179055565b604051639a51fe8f60e01b8152600490fd5b50600080516020615de78339815191525415614979565b6002111561000e57565b919082606091031261000e57604051614a6e6060826104e8565b604081938035614a7d81614a4a565b83526020810135614a8d81614a4a565b602084015201359061ffff198216820361000e5760400152565b60018151614ab48161040f565b614abd8261040f565b614ac68161040f565b14614ad8576040015161ffff19161590565b6001600160a01b0390614aea90614af1565b163b151590565b60018151614afe8161040f565b614b078261040f565b614b108161040f565b03614b28576040015160101c6001600160a01b031690565b8051604491614b368261040f565b604061ffff1991015116604051916327ada38760e11b8352614b578161040f565b60048301526024820152fd5b9081606091031261000e576040805191614b7e6060846104e8565b80518352602081015160208401520151604082015290565b61055b90614ba261261c565b50600080516020615da783398151915254604051637ece075d60e01b81526004810192909252606090829060249082906001600160a01b03165afa908115614c0a575b600091614bf25750614cd1565b611dcf915060603d8111611dd557611dc781836104e8565b614c1261260f565b614be5565b90813b15614c6a57816040917f41dd56c92c84169d8e89dc293d2649a911f47b357d3012bc88662395e01979d093600080516020615da78339815191525582519160018060a01b031682526020820152a1565b60405163d26af10d60e01b8152600490fd5b614c8461261c565b50600080516020615da78339815191525460405160016209351760e01b0319815261055b91606090829060049082906000906001600160a01b03165af1908115614c0a57600091614bf257505b614cd961261c565b50614ce261490e565b614cf26040830191825190614d1a565b905290565b6040810193929160209190614d0b8161040f565b8152614d168361040f565b0152565b8051614d258161040f565b6020820192835192614d368461040f565b614d40600061040f565b614d498361040f565b82614dd95750925b8051614d5c8161040f565b614d66600061040f565b614d6f8161040f565b614d795750505090565b60019051614d868161040f565b614d8f8261040f565b614d988161040f565b03614dbd57505061055b90614db7670de0b6b3a76400006000196130db565b90613c39565b610830604051928392631fafe5ed60e21b845260048401614cf7565b614de3600161040f565b614dec8361040f565b60018303614e045790614dfe91614e22565b92614d51565b5050610830604051928392631fafe5ed60e21b845260048401614cf7565b6001600160a01b0390614e3490614af1565b16604051906020928383019063d7c7a93560e01b8252602484015260248352614e5e6044846104e8565b614e686025614f59565b92614e7660405194856104e8565b602584527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668585015264185a5b195960da1b6040850152823b15614f08576000614ef39361055b969593829351915afa3d15614f00573d90614ed782614f59565b91614ee560405193846104e8565b82523d60008684013e614f83565b8051810182019101613c8b565b606090614f83565b60405162461bcd60e51b8152600481018690526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e746044820152631c9858dd60e21b6064820152608490fd5b6020906001600160401b038111614f76575b601f01601f19160190565b614f7e6104d1565b614f6b565b90919015614f8f575090565b815115614f9f5750805190602001fd5b60405162461bcd60e51b815290819061083090600483016105d1565b9392919061509190614fcb6131d2565b5061146261504e614fe8614fdf87856150c5565b938954906150c5565b94614ff16131d2565b50602080855195885196600088820398128189128116918913901516176150b8575b015196015195600087820397128188128116918813901516176150ab575b604051936150406040866104e8565b845260208401958652612d3c565b936150576131d2565b50615089602061508161506a885161313b565b95611462670de0b6b3a764000097889251906130db565b96015161313b565b9051906130db565b604051916150a06040846104e8565b825260208201529255565b6150b36128ea565b615031565b6150c06128ea565b615013565b6001916150d06131d2565b506000520160205261055b6040600020604051906150ef6040836104e8565b5480600f0b825260801d600f0b60208201526151096131d2565b5060208151910151604051916151206040846104e8565b600f0b8252600f0b602082015290565b6002916150d06131d2565b815181546001600160801b0319166001600160801b0390911617808255602090920151909161516d91600f0b90614657565b9055565b92949391948080516151839088615c0f565b9284828561518f6131d2565b50615199936153f3565b91906151a686838761561a565b6151af9161538f565b976001016151bc90612d5c565b906151c79185615731565b97906151d29161538f565b968101809111926152456152739361526c61524f61524a61524a9661528b99615300575b9c6151ff6131d2565b966020808d01519181880151808403938085116152f3575b82516152b657505060005b8a52019081511560001461529057505060005b602088015261524585518d6150c5565b61538f565b61530d565b615267895160018c0190600052602052604060002090565b61513b565b5187615130565b61526783516002860190600052602052604060002090565b519055565b6152b1916152a9670de0b6b3a7640000613b8f93613163565b905190613308565b615235565b6152e191613b8f91670de0b6b3a7640000918288029288840414911417156152e6575b835190613308565b615222565b6152ee6128ea565b6152d9565b6152fb6128ea565b615217565b6153086128ea565b6151f6565b6153156131d2565b5061532d6020615325835161533c565b92015161533c565b604051916151206040846104e8565b60016001607f1b0381136153775760016001607f1b0319811261535f57600f0b90565b60249060405190634e02165d60e01b82526004820152fd5b60249060405190632cd75ba360e11b82526004820152fd5b906153986131d2565b50602080835193835194600086820196871291129080158216911516176153e6575b01519101519060008282019283129112908015821691151617613258576040519161324e6040846104e8565b6153ee6128ea565b6153ba565b9391939290926154016131d2565b9460409182519363597e1fb560e01b85526020948581600481305afa9081156155f3575b6000916155d6575b506155c357848701908151156155a2578751156155a25785015185840151615454916132b8565b928482516154619061313b565b91015161546d91613c39565b615476906131c1565b61547f886132c5565b6154889161318d565b935163307648eb60e11b815290858083806154a68c60048301611cff565b0381305afa938415996154f861556098614db76154f2614db7996155279f99615542986155579b615595575b600092615578575b5050614db7613b8f670de0b6b3a7640000809e613163565b9161313b565b90615548600061552d8a61551561550e876131c1565b9788613163565b049e8f61552187615600565b976132b8565b8661310c565b941291821561556e5761554284915b5161313b565b90613c4f565b8d52156155665750915161313b565b916000196130db565b90840152565b90509161553c565b615542859161553c565b61558e9250803d106108965761088781836104e8565b388e6154da565b61559d61260f565b6154d2565b5050505060009294506155b69193506123e6565b9181835282015290600090565b50505060009294506155b69193506123e6565b6155ed9150863d88116107355761072781836104e8565b3861542d565b6155fb61260f565b615425565b6000811361561457600013613c7c57600090565b50600190565b9291926156256131d2565b9360409283519363597e1fb560e01b85526020948581600481305afa908115615724575b600091615707575b506156f457848401928351156156d6578451156156d6576156b46156ae6156a761569b61569161554297876156d09b9a986156c898015191015190613beb565b614db7875161313b565b614db7613b8f896132c5565b955161313b565b85613c4f565b614db7670de0b6b3a76400006000196130db565b87525161313b565b90830152565b509150506000929394506156ea91506123e6565b9181835282015290565b9150506000929394506156ea91506123e6565b61571e9150863d88116107355761072781836104e8565b38615651565b61572c61260f565b615649565b9192909261573d6131d2565b93615747816148d6565b615828579061575591615881565b60405190630dbc9ce160e01b825261579b61579561578e6020948581600481305afa90811561581b575b6000916157fe575b5084615830565b8093613272565b9161586e565b8451909490156157e85782906157b9613b8f83850151835190613308565b87525b018051909190156157d85761556091613b8f9151905190613308565b905061055b929391505190612901565b936157f883918284015190612901565b946157bc565b6158159150863d88116108965761088781836104e8565b38615787565b61582361260f565b61577f565b506000925050565b906158396131d2565b5061585e670de0b6b3a764000091602083615855838751613163565b04940151613163565b046040519161324e6040846104e8565b6020815191015181018091116129305790565b6158896131d2565b506158d46158c76158a560209360408582015191015190613214565b936158cc846150816158c760406158bc8a5161313b565b950194855190613c39565b6131c1565b905190613c39565b604051633f1d071f60e21b815290928282600481305afa9182156159a7575b600092615984575b5061594390615914670de0b6b3a7640000938492613163565b6040516343f0179b60e01b8152919004948482600481305afa918215615977575b600092615958575b50613163565b049061594f60406123e6565b92835282015290565b615970919250853d87116108965761088781836104e8565b903861593d565b61597f61260f565b615935565b6159439192506159a090843d86116108965761088781836104e8565b91906158fb565b6159af61260f565b6158f3565b6004906000926159d8575b8281558260018201558260028201558260038201550155565b6159e0610480565b6159bf565b6020615a086159f383612d3c565b936002840194615a0286612d5c565b90615a34565b815184559101516001830155615a1c575050565b615a2960006007936159b4565b01805460ff19169055565b91615a3d6131d2565b50615a47826148d6565b159081615a6b575b5015615a6457615a5e916131ed565b90600190565b5090600090565b90505181511038615a4f565b6131a0615ac56158c7670de0b6b3a764000093615ac0613b8f60408051634ec4474360e11b8152606081600481305afa908115615b35575b600091615b17575b50015192615b42565b613c39565b604051636c376cc560e01b815290602082600481305afa918215615b0a575b600092615af15750613163565b61597091925060203d81116108965761088781836104e8565b615b1261260f565b615ae4565b615b2f915060603d8111611dd557611dc781836104e8565b38615ab7565b615b3d61260f565b615aaf565b8051602090910151808210613303575090565b80541580615baf575b80615ba3575b6001820154159182615b96575b82615b89575b50159081615b83575090565b90501590565b6006015415915038615b77565b6004810154159250615b71565b50600581015415615b64565b50600381015415615b5e565b615bd9615bc782612d3c565b615bd360038401612d3c565b90613214565b6002615beb60058401548351906131a4565b14918215615bf857505090565b60060154602090910151600292506137ef916131a4565b90615c186131d2565b50600052602052604060002060405190615c336040836104e8565b546001600160801b03808216835260809190911c60208301908152918190615c596131d2565b5051169151166040519161324e6040846104e8565b90615c799082615c0f565b91615d06615c8f826001850195615a0287612d5c565b9390615c996131d2565b50615cb16020615ca98351615d1a565b920151615d1a565b9160405194615cc16040876104e8565b6001600160801b0392831686529282166020808701918252935160009081529190935260409020935184546001600160801b0319169082161780855591511690614657565b9055615d0f5750565b6000610a38916159b4565b6001600160801b0390818111615d2e571690565b60249060405190635385129160e01b82526004820152fdfe968cf792ff9a89745e4746179e93a7b9d7f08b0ff8366fd6f6dbd524ef107464d729c7f2aea8904a802db9fc1939086967cdf7fffe1510c25ccafabfc894614eb9726781b72c53f23217f424d70445b222951f008aeac7eece8139caed71ed2d6c0d5e3cd81753b1b21f67f61d56a97aae7a3e0179486d114788ad4576f53266630ac9ad193fa8d8f5a7207eefdee35934d664003a3d4c286a591e065a62034ead57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398cace7e947336f94057b47a9ab5531b0363e85c8d36c05c7d915ec8e525fd159d863625b85818a29587ee919ee6a968ee0b32f3513f2884b3968001062ba49eb6b1b30fe15febd596dffd21d4da0657732eea42b4b5a9789e3e6daab3d570999d7850062f2c27d17cdf727c8059e0b505bd3a788af62482a56bcede987d8eea5a35a294f9055e9dc7a18078b4e0139086766d723c3cd728bd59cc1f3b589741ed21d7cfd39841edd73967db6350efae442ebd8c6e1bfca55faa52b046d39b7e493bdea2cc426745068386b3804e5b401ae87ffbae9dbf293944b5307f507040c79917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f7917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f6f98b31465ac12e92b5cb136ade913276c267463c4395bb1a3999bc88fb837806897858f7b7d3c8b4e7a700b401ad192a110353a60c809946583c0d62cda7f0b70e555410d8128dff796eab5d29b97dd593ce9cab44a71b64c08244579ea6053339854479080fac0b5e7c0ecedb0fb02308a72a43cd102c6b9f918653d3400367a2646970667358221220c7754a6e80b15d2df75708d6c5c417eb426054257d82eab1d7005bad8acc702364736f6c63430008110033", - "deployedBytecode": "0x60806040526004361015610013575b600080fd5b60003560e01c806305d5c1cb146103fb57806306fdde03146103f25780630dbc9ce1146103e957806311da60b4146103e0578063153261e5146103d757806319377567146103ce5780631cb44dfc146103c55780631e0c6fb9146103bc57806320fe9c3c146103b3578063212e0ad3146103aa5780632131ea4a146103a15780632d2e52be146103985780633a25c1111461038f5780633e17b8c71461038657806343f0179b1461037d578063476fa96d1461037457806354fb39211461036b57806356bc1ad41461036257806358ca6f981461035957806359218fe914610350578063597e1fb51461034757806359ea287d1461033e5780635d16e1201461033557806360ec91d61461032c578063611c71b4146103235780636943b0171461031a5780636c376cc5146103115780636ecffff91461030857806373b88f3b146102ff57806376f37001146102f65780637dc0d1d0146102ed5780637ece075d146102e45780638c94b48f146102db5780638e480b20146102d257806391689024146102c95780639378bf7b146102c057806395d89b41146102b75780639a427d03146102ae5780639d888e86146102a5578063a12e1b331461029c578063ab582f2914610293578063b7648fb91461028a578063c07f47d414610281578063d7d7d6b814610278578063e1c3c98d1461026f578063e503b00714610266578063f667f8971461025d578063f6b3200814610254578063f77c47911461024b5763fc741c7c1461024357600080fd5b61000e6123b0565b5061000e612379565b5061000e6122c2565b5061000e612201565b5061000e6120cc565b5061000e611fc5565b5061000e611f01565b5061000e611ee2565b5061000e611e9d565b5061000e611e47565b5061000e611e1e565b5061000e611d45565b5061000e611d0f565b5061000e611cde565b5061000e611b95565b5061000e611b50565b5061000e611b12565b5061000e611a0b565b5061000e6119dd565b5061000e61197d565b5061000e6118c1565b5061000e6117eb565b5061000e611646565b5061000e61161a565b5061000e611576565b5061000e61146f565b5061000e61140d565b5061000e6113e1565b5061000e6113b9565b5061000e61138b565b5061000e6112db565b5061000e611295565b5061000e61118e565b5061000e611087565b5061000e61105c565b5061000e611030565b5061000e610f29565b5061000e610ebf565b5061000e610d66565b5061000e610bf4565b5061000e610ae2565b5061000e610a90565b5061000e610a3a565b5061000e6108e7565b5061000e6108aa565b5061000e61075e565b5061000e610676565b5061000e61064a565b5061000e61061a565b5061000e61042f565b600091031261000e57565b6002111561041957565b634e487b7160e01b600052602160045260246000fd5b503461000e57600036600319011261000e57606061044b61490e565b60405190805161045a8161040f565b8252602081015161046a8161040f565b6020830152604061ffff19910151166040820152f35b50634e487b7160e01b600052600060045260246000fd5b90600182811c921680156104c7575b60208310146104b157565b634e487b7160e01b600052602260045260246000fd5b91607f16916104a6565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101761050b57604052565b6105136104d1565b604052565b906105c4575b6040519081600082549261053184610497565b9081845260019485811690816000146105a1575060011461055e575b505061055b925003826104e8565b90565b9093915060005260209081600020936000915b81831061058957505061055b9350820101388061054d565b85548784018501529485019486945091830191610571565b91505061055b94506020925060ff191682840152151560051b820101388061054d565b6105cc610480565b61051e565b6020808252825181830181905290939260005b82811061060657505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016105e4565b503461000e57600036600319011261000e5761064661063a600080610518565b604051918291826105d1565b0390f35b503461000e57600036600319011261000e576020600080516020615e6783398151915254604051908152f35b503461000e5760008060031936011261075b57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561073c575b839161070e575b506106fc576001906106f7612663565b505580f35b604051633b3b4caf60e21b8152600490fd5b61072f915060203d8111610735575b61072781836104e8565b8101906125fa565b386106e7565b503d61071d565b61074461260f565b6106e0565b604051637990191b60e11b8152600490fd5b80fd5b503461000e57608036600319011261000e5761079061078b600080516020615f6783398151915254611971565b611971565b604051633e92a73360e11b8152906020908183806107b13060048301613d24565b0381845afa92831561089d575b60009361086e575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610861575b600092610834575b5050336001600160a01b0390911603610816576108146004614674565b005b60405163123d8bcf60e21b81526004810191909152602490fd5b0390fd5b6108539250803d1061085a575b61084b81836104e8565b81019061263d565b38806107f7565b503d610841565b61086961260f565b6107ef565b61088f919350823d8411610896575b61088781836104e8565b810190613c8b565b91386107c6565b503d61087d565b6108a561260f565b6107be565b503461000e57600036600319011261000e576020600080516020615f4783398151915254604051908152f35b6001600160a01b0381160361000e57565b503461000e5760208060031936011261000e5760043590610907826108d6565b61092261078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806109413060048301613d24565b0381845afa9283156109ec575b6000936109cd575b50604051635091e19f60e11b815260048101849052908290829060249082905afa9182156109c0575b6000926109a3575b5050336001600160a01b03909116036108165761081482613d81565b6109b99250803d1061085a5761084b81836104e8565b3880610987565b6109c861260f565b61097f565b6109e5919350823d84116108965761088781836104e8565b9138610956565b6109f461260f565b61094e565b60208091805184520151910152565b610a38909291926060604060a083019580518452610a2e602082015160208601906109f9565b01519101906109f9565b565b503461000e57602036600319011261000e57600435610a58816108d6565b610a60613a70565b5060018060a01b03166000526002602052610646610a846002604060002001612d5c565b60405191829182610a08565b503461000e57602036600319011261000e57610aaa6131d2565b50610646610abb600435600a6150c5565b604051918291829190916020806040830194805184520151910152565b8015150361000e57565b503461000e5760208060031936011261000e5760043590610b0282610ad8565b610b1d61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380610b3c3060048301613d24565b0381845afa928315610be7575b600093610bc8575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610bbb575b600092610b9e575b5050336001600160a01b03909116036108165761081482613d37565b610bb49250803d1061085a5761084b81836104e8565b3880610b82565b610bc361260f565b610b7a565b610be0919350823d84116108965761088781836104e8565b9138610b51565b610bef61260f565b610b49565b503461000e5760408060031936011261000e576004803590610c15826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610d4c575b600091610d2f575b50610d1f57808616331491858315610cc0575b505050905015610ca357600184610ca060243586613364565b55005b51636dc3a3c360e01b815290819061083090339085908401612d07565b9193819350855192838092630479e58f60e41b82525afa918215610d12575b600092610cf5575b505016331480388085610c87565b610d0b9250803d1061085a5761084b81836104e8565b3880610ce7565b610d1a61260f565b610cdf565b50505051633b3b4caf60e21b8152fd5b610d469150833d85116107355761072781836104e8565b38610c74565b610d5461260f565b610c6c565b51637990191b60e11b8152fd5b503461000e5760408060031936011261000e576004803590610d87826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610eb2575b600091610e95575b50610d1f57600080516020615ec783398151915254610e8557808616331491858315610e26575b505050905015610ca357600184610ca060243586613504565b9193819350855192838092630479e58f60e41b82525afa918215610e78575b600092610e5b575b505016331480388085610e0d565b610e719250803d1061085a5761084b81836104e8565b3880610e4d565b610e8061260f565b610e45565b5050505163ded15dbf60e01b8152fd5b610eac9150833d85116107355761072781836104e8565b38610de6565b610eba61260f565b610dde565b503461000e57600036600319011261000e5760c0610edb613ebe565b6040519080511515825260a060018060401b039182602082015116602085015260408101511515604085015282606082015116606085015260808101511515608085015201511660a0820152f35b503461000e5760208060031936011261000e57610f5761078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380610f763060048301613d24565b0381845afa928315611023575b600093611004575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610ff7575b600092610fda575b5050336001600160a01b0390911603610816576108146004356140ee565b610ff09250803d1061085a5761084b81836104e8565b3880610fbc565b610fff61260f565b610fb4565b61101c919350823d84116108965761088781836104e8565b9138610f8b565b61102b61260f565b610f83565b503461000e57600036600319011261000e576020600080516020615ea783398151915254604051908152f35b503461000e57602036600319011261000e576110766131d2565b50610646610abb600435600a615130565b503461000e5760208060031936011261000e576110b561078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806110d43060048301613d24565b0381845afa928315611181575b600093611162575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611155575b600092611138575b5050336001600160a01b03909116036108165761081460043561443e565b61114e9250803d1061085a5761084b81836104e8565b388061111a565b61115d61260f565b611112565b61117a919350823d84116108965761088781836104e8565b91386110e9565b61118961260f565b6110e1565b503461000e5760208060031936011261000e576111bc61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806111db3060048301613d24565b0381845afa928315611288575b600093611269575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561125c575b60009261123f575b5050336001600160a01b039091160361081657610814600435613f8e565b6112559250803d1061085a5761084b81836104e8565b3880611221565b61126461260f565b611219565b611281919350823d84116108965761088781836104e8565b91386111f0565b61129061260f565b6111e8565b503461000e57602036600319011261000e576004356112b3816108d6565b60018060a01b03166000526002602052602060ff600760406000200154166040519015158152f35b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561137e575b600091611360575b506106fc57600190610ca060043533613809565b611378915060203d81116107355761072781836104e8565b3861134c565b61138661260f565b611344565b503461000e57600036600319011261000e576020600080516020615ec7833981519152546040519015158152f35b503461000e57600036600319011261000e576113d3613a70565b50610646610a846004612d5c565b503461000e57600036600319011261000e576020600080516020615e0783398151915254604051908152f35b503461000e57604036600319011261000e576020611467611442611435600435602435613c65565b61143d613e25565b613aaf565b611462670de0b6b3a764000061145c816301e133806130db565b926130db565b613c04565b604051908152f35b503461000e5760208060031936011261000e5761149d61078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806114bc3060048301613d24565b0381845afa928315611569575b60009361154a575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561153d575b600092611520575b5050336001600160a01b039091160361081657610814600435614310565b6115369250803d1061085a5761084b81836104e8565b3880611502565b61154561260f565b6114fa565b611562919350823d84116108965761088781836104e8565b91386114d1565b61157161260f565b6114c9565b503461000e57602036600319011261000e57600435611594816108d6565b60018060a01b0316600052600260205261064660406000206115ef604051916115be6060846104e8565b6115c781612d3c565b835260ff60076115d960028401612d5c565b92836020870152015416151560408401526148d6565b9081611609575b5060405190151581529081906020820190565b6116149150516148f7565b386115f6565b503461000e57600036600319011261000e576020600080516020615d4783398151915254604051908152f35b503461000e5760031960203682011261000e57600435906001600160401b03821161000e576102008260040191833603011261000e5760017f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b81815410156117d257819055600080516020615de783398151915292818455303b1515806117ca575b6117b857333b156117a6577fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f32936117906117896117a195602460009533600080516020615f678339815191525561172e61172460a483016123dc565b604483019061496f565b6117366125c1565b61176e611747366101848401612402565b61016483013561014484013561012485013561010486013560e487013560c4880135613d96565b61178261177b8480612466565b90896124ec565b0190612466565b90856124ec565b556040519081529081906020820190565b0390a1005b6040516314878b6960e01b8152600490fd5b604051631a27c4a960e21b8152600490fd5b5060006116c8565b604051631e7a9d9560e01b815260048101839052602490fd5b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156118b4575b600091611896575b506106fc57600080516020615ec78339815191525461188457600190610ca060043533612d21565b60405163ded15dbf60e01b8152600490fd5b6118ae915060203d81116107355761072781836104e8565b3861185c565b6118bc61260f565b611854565b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611964575b600091611946575b506106fc57600190610ca060043533613364565b61195e915060203d81116107355761072781836104e8565b38611932565b61196c61260f565b61192a565b6001600160a01b031690565b503461000e57600036600319011261000e57600080516020615da7833981519152546040516001600160a01b039091168152602090f35b6040809180518452602081015160208501520151910152565b606081019291610a3891906119b4565b503461000e57602036600319011261000e5760606119fc600435614b96565b611a0960405180926119b4565bf35b503461000e5760208060031936011261000e57611a3961078b600080516020615f6783398151915254611971565b604051633e92a73360e11b81529190818380611a583060048301613d24565b0381845afa928315611b05575b600093611ae6575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611ad9575b600092611abc575b5050336001600160a01b039091160361081657610814600435614553565b611ad29250803d1061085a5761084b81836104e8565b3880611a9e565b611ae161260f565b611a96565b611afe919350823d84116108965761088781836104e8565b9138611a6d565b611b0d61260f565b611a65565b503461000e57602036600319011261000e57600435611b30816108d6565b60018060a01b031660005260096020526020604060002054604051908152f35b503461000e57602036600319011261000e57600435611b6e816108d6565b60018060a01b031660005260026020526020611467611b906040600020612d3c565b615a77565b503461000e5760408060031936011261000e576004803590611bb6826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115611cd1575b600091611cb4575b50610d1f57600080516020615ec783398151915254610e8557808616331491858315611c55575b505050905015610ca357600184610ca060243586612d21565b9193819350855192838092630479e58f60e41b82525afa918215611ca7575b600092611c8a575b505016331480388085611c3c565b611ca09250803d1061085a5761084b81836104e8565b3880611c7c565b611caf61260f565b611c74565b611ccb9150833d85116107355761072781836104e8565b38611c15565b611cd961260f565b611c0d565b503461000e57600036600319011261000e5761064661063a60006001610518565b604081019291610a3891906109f9565b503461000e57602036600319011261000e57611d296131d2565b506040611d396004356003615c0f565b611a09825180926109f9565b503461000e57600036600319011261000e57611d5f61261c565b50600080516020615da783398151915254604051634ec4474360e11b81526060916119fc91908390829060049082906001600160a01b03165afa908115611ddc575b600091611daf575b50614cd1565b611dcf9150833d8111611dd5575b611dc781836104e8565b810190614b63565b38611da9565b503d611dbd565b611de461260f565b611da1565b6060908051600f0b83526020810151600f0b60208401526040810151600f0b60408401528160018060801b0391015116910152565b503461000e57600036600319011261000e576080611e3a613e25565b611a096040518092611de9565b503461000e57602036600319011261000e57600435611e65816108d6565b60018060a01b031660005260026020526020611467611b906040600020611e976002611e9083612d3c565b9201612d5c565b906131ed565b503461000e57602036600319011261000e57600435611ebb816108d6565b611ec36131d2565b5060018060a01b031660005260026020526040611d3981600020612d3c565b503461000e57600036600319011261000e576020600a54604051908152f35b503461000e57602036600319011261000e57600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611fb8575b600091611f9a575b506106fc57600080516020615ec78339815191525461188457600190610ca060043533613504565b611fb2915060203d81116107355761072781836104e8565b38611f72565b611fc061260f565b611f6a565b503461000e5760208060031936011261000e57611ff361078b600080516020615f6783398151915254611971565b604051633e92a73360e11b815291908183806120123060048301613d24565b0381845afa9283156120bf575b6000936120a0575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215612093575b600092612076575b5050336001600160a01b039091160361081657610814600435614047565b61208c9250803d1061085a5761084b81836104e8565b3880612058565b61209b61260f565b612050565b6120b8919350823d84116108965761088781836104e8565b9138612027565b6120c761260f565b61201f565b503461000e5760408060031936011261000e5760048035906120ed826108d6565b600080516020615e47833981519152926002845414610d595760028455600080516020615f67833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa9081156121f4575b6000916121d7575b50610d1f57808616331491858315612178575b505050905015610ca357600184610ca060243586613809565b9193819350855192838092630479e58f60e41b82525afa9182156121ca575b6000926121ad575b50501633148038808561215f565b6121c39250803d1061085a5761084b81836104e8565b388061219f565b6121d261260f565b612197565b6121ee9150833d85116107355761072781836104e8565b3861214c565b6121fc61260f565b612144565b503461000e57602036600319011261000e5760043561221f816108d6565b600080516020615e4783398151915260028154146107495760028155600080516020615f6783398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156122b5575b600091612297575b506106fc57610ca0600192612291612663565b9061298a565b6122af915060203d81116107355761072781836104e8565b3861227e565b6122bd61260f565b612276565b503461000e57602036600319011261000e576004356122e0816108d6565b600460206122ff61078b600080516020615f6783398151915254611971565b60405163d8dfeb4560e01b815292839182905afa90811561236c575b60009161234e575b506001600160a01b0316330361233c57610814906139eb565b6040516340cbe9b160e01b8152600490fd5b612366915060203d811161085a5761084b81836104e8565b38612323565b61237461260f565b61231b565b503461000e57600036600319011261000e57600080516020615f67833981519152546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600080516020615e8783398151915254604051908152f35b3561055b816108d6565b90610a3860405192836104e8565b359081600f0b820361000e57565b919082608091031261000e5760405161241c6080826104e8565b60608193612429816123f4565b8352612437602082016123f4565b6020840152612448604082016123f4565b60408401520135906001600160801b038216820361000e5760600152565b903590601e198136030182121561000e57018035906001600160401b03821161000e5760200191813603831361000e57565b90601f81116124a657505050565b600091825260208220906020601f850160051c830194106124e2575b601f0160051c01915b8281106124d757505050565b8181556001016124cb565b90925082906124c2565b9092916001600160401b0381116125b4575b6125128161250c8454610497565b84612498565b6000601f821160011461254c5781929394600092612541575b50508160011b916000199060031b1c1916179055565b01359050388061252b565b601f1982169461256184600052602060002090565b91805b87811061259c575083600195969710612582575b505050811b019055565b0135600019600384901b60f8161c19169055388080612578565b90926020600181928686013581550194019101612564565b6125bc6104d1565b6124fe565b303b1515806125e3575b6117b8576001600080516020615e4783398151915255565b50600080516020615de783398151915254156125cb565b9081602091031261000e575161055b81610ad8565b506040513d6000823e3d90fd5b6040519061262b6060836104e8565b60006040838281528260208201520152565b9081602091031261000e575161055b816108d6565b908152602081019190915260400190565b61266b61261c565b50612684600080516020615f6783398151915254611971565b9061268d614c7c565b91600a5490835182146128e6576126a382614b96565b906126b085516004612916565b855181036128d7575084915b604051631bf1901f60e21b81526001600160a01b03926020929084169184908481600481875afa9081156128ca575b6000916128ad575b501690813b1561000e5760405163a55ff01d60e01b81528992600090829081838161272189600483016119cd565b03925af180156128a0575b61288b575b506127558661274d81612742613c9a565b94600386600a615171565b986003615c6e565b61275d6146cc565b8551825103612857575b5050816004916040519283809263d8dfeb4560e01b82525afa91821561284a575b60009261282d575b50501691823b1561000e57604051637f3dd53b60e01b815260048101919091527f88a84ea6dd274b386afd27dbbe11b6192b25017f5e60bb8c4053dfddb45c294d926000908290602490829084905af18015612820575b612805575b505183519061280060405192839283612652565b0390a1565b80612814600061281a936104e8565b80610404565b386127ec565b61282861260f565b6127e7565b6128439250803d1061085a5761084b81836104e8565b3880612790565b61285261260f565b612788565b6004929661286e859388600361287495600a615171565b90612901565b956128828987516003615c6e565b91889150612767565b80612814600061289a936104e8565b38612731565b6128a861260f565b61272c565b6128c49150853d871161085a5761084b81836104e8565b386126f3565b6128d261260f565b6126eb565b6128e090614b96565b916126bc565b5050565b50634e487b7160e01b600052601160045260246000fd5b9190820180921161290e57565b610a386128ea565b5480612920575090565b9050600181018091116129305790565b61055b6128ea565b9060018060a01b0316600052602052604060002090565b6001600160a01b039091168152608081019291610a3891602001906119b4565b6001600160a01b039091168152602081019190915260400190565b6129a2600080516020615f6783398151915254611971565b6129ad826009612938565b54835114612cc4576129cd60026129c48482612938565b01845190612916565b83518103612cb5575082915b60018060a01b038092166040805194631bf1901f60e21b9283875260208660049882818b81875afa908115612ca8575b600091612c8b575b5016803b1561000e578792878a92600088518092818381612a408d63060c0d2760e21b998a84528c840161294f565b03925af18015612c7e575b612c69575b50612a7c612a77612a628b6009612938565b612a6d8c6002612938565b600a8a5192614fbb565b612ce5565b97612a9187612a8c8c6002612938565b6159e5565b86518d5103612b85575b5050829086519283809263d8dfeb4560e01b82525afa918215612b78575b600092612b5b575b505016803b1561000e576000612b3494612b139287837f9d7055d24918d8c2fd08660a27bf31d4086fa71a51cd07874276470223aa480f9b8851968795869485936364e5a46f60e11b8552840161296f565b03925af18015612b4e575b612b39575b505195519051938493169583612652565b0390a2565b806128146000612b48936104e8565b38612b23565b612b5661260f565b612b1e565b612b719250803d1061085a5761084b81836104e8565b3880612ac1565b612b8061260f565b612ab9565b909491979250865190815283818c818b5afa908115612c5c575b600091612c3f575b5016803b1561000e57612c158a92612c0f612a778b8f808f9a838b998f60008094612bde8f9351978896879586948552840161294f565b03925af18015612c32575b612c1d575b50600a612c07612bff846009612938565b936002612938565b915192614fbb565b90612cc9565b969038612a9b565b806128146000612c2c936104e8565b38612bee565b612c3a61260f565b612be9565b612c569150843d861161085a5761084b81836104e8565b38612ba7565b612c6461260f565b612b9f565b806128146000612c78936104e8565b38612a50565b612c8661260f565b612a4b565b612ca29150833d851161085a5761084b81836104e8565b38612a11565b612cb061260f565b612a09565b612cbe90614b96565b916129d9565b505050565b9190916000838201938412911290801582169115161761290e57565b6020815191015190600082820192831291129080158216911516176129305790565b6001600160a01b0391821681529116602082015260400190565b90610a3891612d37612d31612663565b8261298a565b612d94565b90604051612d4b6040826104e8565b602060018294805484520154910152565b90604051612d6b6060826104e8565b6040612d8f6003839580548552612d8460018201612d3c565b602086015201612d3c565b910152565b60018060a01b03908181166000526020916002835260409360ff600786600020015416612f3b5790612dc7849284612f4c565b81612de361078b600080516020615f6783398151915254611971565b9186519586809463d8dfeb4560e01b825260049889915afa928315612f2e575b600093612f0f575b5086516301c8232360e71b8152928391829081612e2b308a8c8401612d07565b0392165afa918215612f02575b600092612ee5575b5050612ed657612e54612e59916002612938565b615b55565b612ec857600080516020615ec7833981519152546128e657612e90612e8b612e82600a54613a9b565b611e9784612d5c565b6132c5565b91612ea3670de0b6b3a7640000846131a4565b15612ead57505050565b5163d8b8b95160e01b81529081019182529081906020010390fd5b90516390898fd160e01b8152fd5b5090516324a21d2960e01b8152fd5b612efb9250803d106107355761072781836104e8565b3880612e40565b612f0a61260f565b612e38565b612f27919350823d841161085a5761084b81836104e8565b9138612e0b565b612f3661260f565b612e03565b8451636830d4d760e01b8152600490fd5b90612f58600a54614b96565b90612f72816002612f698682612938565b01845190613342565b612f7f8183516004613342565b612fae612f98612f9260408501516131c1565b8361318d565b600080516020615ea7833981519152549061318d565b9182612fe4575b516040516001600160a01b0390941693600080516020615d878339815191529350918291612b34919083612652565b61303d6004602061300661078b600080516020615f6783398151915254611971565b60405163d8dfeb4560e01b815292839182905afa9081156130ce575b6000916130b0575b506001600160a01b03169360001961310c565b833b1561000e576000613078600080516020615d878339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156130a3575b61308e575b50612fb5565b80612814600061309d936104e8565b38613088565b6130ab61260f565b613083565b6130c8915060203d811161085a5761084b81836104e8565b3861302a565b6130d661260f565b613022565b818102929160008212600160ff1b8214166130ff575b818405149015171561290e57565b6131076128ea565b6130f1565b60008113613135576000136131215750600090565b61312d61055b9161313b565b6000196130db565b5061055b905b6001600160ff1b03811161314c5790565b6024906040519062a07eb560e01b82526004820152fd5b8181029291811591840414171561290e57565b50634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916131a091613163565b0490565b8181116131ba57106131b557600190565b600090565b5050600290565b60008082126131ce575090565b0390565b604051906131e16040836104e8565b60006020838281520152565b90604061320b61055b936131ff6131d2565b50602084015190613214565b91015190613272565b9061321d6131d2565b5060208083519383518501809511613265575b01519101518101809111613258575b6040519161324e6040846104e8565b8252602082015290565b6132606128ea565b61323f565b61326d6128ea565b613230565b9061327b6131d2565b50602080835193835185039485116132ab575b01519101518103908111613258576040519161324e6040846104e8565b6132b36128ea565b61328e565b9190820391821161290e57565b602081015160009190806132e257505050670de0b6b3a764000090565b6132ec9151613308565b670de0b6b3a7640000915080821015613303575090565b905090565b670de0b6b3a764000090818102918183041490151715613335575b811561332d570490565b6131a0613176565b61333d6128ea565b613323565b9091600282018054918201809211613358575555565b6133606128ea565b5555565b61336f612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb5761339e916133dd565b60005260026020526133b36040600020615bbb565b6133b957565b604051633975ab9360e01b8152600490fd5b604051636830d4d760e01b8152600490fd5b906133e9600a54614b96565b906134038160026133fa8682612938565b018451906134ee565b61341081835160046134ee565b613423612f98612f9260408501516131c1565b9182613459575b516040516001600160a01b0390941693600080516020615e278339815191529350918291612b34919083612652565b61347b6004602061300661078b600080516020615f6783398151915254611971565b833b1561000e5760006134b6600080516020615e278339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156134e1575b6134cc575b5061342a565b8061281460006134db936104e8565b386134c6565b6134e961260f565b6134c1565b9091600482018054918201809211613358575555565b90613516613510612663565b8361298a565b600a54156136aa5760018060a01b03918281166000526020926002845260409260ff60078560002001541661369957906135518592846136bc565b8161356d61078b600080516020615f6783398151915254611971565b9185519687809463d8dfeb4560e01b82526004998a915afa92831561368c575b60009361366d575b5085516301c8232360e71b81529283918290816135b5308a8d8401612d07565b0392165afa918215613660575b600092613643575b505061363557612e546135de916002612938565b613628576136136135fc6135f3600a54613a9b565b611e9785612d5c565b51600080516020615f4783398151915254906137e3565b61361b575050565b5163677e872f60e11b8152fd5b516390898fd160e01b8152fd5b50516324a21d2960e01b8152fd5b6136599250803d106107355761072781836104e8565b38806135ca565b61366861260f565b6135c2565b613685919350823d841161085a5761084b81836104e8565b9138613595565b61369461260f565b61358d565b8351636830d4d760e01b8152600490fd5b60405163c25d67ab60e01b8152600490fd5b906136c8600a54614b96565b906136e28160026136d98682612938565b018451906137f3565b6136ef81835160046137f3565b613718613702612f9260408501516131c1565b600080516020615e87833981519152549061318d565b918261374e575b516040516001600160a01b0390941693600080516020615f278339815191529350918291612b34919083612652565b6137706004602061300661078b600080516020615f6783398151915254611971565b833b1561000e5760006137ab600080516020615f278339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156137d6575b6137c1575b5061371f565b8061281460006137d0936104e8565b386137bb565b6137de61260f565b6137b6565b6002916137ef916131a4565b1490565b9091600182018054918201809211613358575555565b90610a3891613819612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb57613848916138c4565b600052600260205261385d6040600020615bbb565b6133b957600080516020615ec783398151915254610a3857613890612e8b613886600a54613a9b565b611e976004612d5c565b6138a2670de0b6b3a7640000826131a4565b156138aa5750565b60405163d8b8b95160e01b81526004810191909152602490fd5b906138d0600a54614b96565b906138ea8160026138e18682612938565b018451906139d5565b6138f781835160046139d5565b61390a613702612f9260408501516131c1565b9182613940575b516040516001600160a01b0390941693600080516020615f878339815191529350918291612b34919083612652565b6139626004602061300661078b600080516020615f6783398151915254611971565b833b1561000e57600061399d600080516020615f878339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156139c8575b6139b3575b50613911565b8061281460006139c2936104e8565b386139ad565b6139d061260f565b6139a8565b9091600382018054918201809211613358575555565b600080516020615ec78339815191525461188457600790613a0d612d31612663565b613a6260018060a01b038216918260005260026020526020613a4f604060002094613a3786612d3c565b9060005260028352611e976002604060002001612d5c565b613a5a8151846138c4565b0151906133dd565b01805460ff19166001179055565b60405190613a7f6060836104e8565b8160008152613a8c6131d2565b60208201526040612d8f6131d2565b61055b90613aa76131d2565b506003615c0f565b60608101519091906001600160801b0316613aca81836131a4565b15613b1257670de0b6b3a764000090613ae382846131a4565b15613af55750505060200151600f0b90565b9083916020604061055b960151930151600f0b92600f0b90613b28565b9161055b9260408251920151600f0b91600f0b60005b90929391613b3682846131a4565b158015613bd8575b613bc65761055b94613b94613b8f83613b9a9686670de0b6b3a7640000976114629703928311613bb9575b8986039560008b128015828913169188121617613bac575b8103908111613b9f57613308565b61313b565b906130db565b612cc9565b613ba76128ea565b613308565b613bb46128ea565b613b81565b613bc16128ea565b613b69565b604051630db0f7cb60e01b8152600490fd5b506002613be582856131a4565b14613b3e565b8181039291600013801582851316918412161761290e57565b8115613c2c575b600160ff1b8114600019831416613c20570590565b613c286128ea565b0590565b613c34613176565b613c0b565b61146261055b92670de0b6b3a7640000926130db565b90611462670de0b6b3a764000061055b936130db565b9080613c825750613c7c57670de0b6b3a764000090565b60001990565b61055b91613308565b9081602091031261000e575190565b600080516020615e0783398151915254600080516020615f678339815191525460405163e975c0c360e01b815290602090829060049082906001600160a01b03165afa908115613d17575b600091613cf9575b50808210613303575090565b613d11915060203d81116108965761088781836104e8565b38613ced565b613d1f61260f565b613ce5565b6001600160a01b03909116815260200190565b7f482763b305ee10cd21c16c0cbeed259f2e4fcacdc9767cef16dc1fbe483d34886020613d62612663565b83600080516020615ec7833981519152555192604051938452151592a2565b600a54610a38916001600160a01b0316614c17565b95949295939093303b151580613de7575b6117b857610a3896613dd3613ddd94613dce613de298613dc9613dd896613f43565b613fe1565b61409a565b6142bc565b6143ea565b614518565b6145a6565b50600080516020615de78339815191525415613da7565b60405190613e0d6080836104e8565b60006060838281528260208201528260408201520152565b613e2d613dfe565b50613e36613dfe565b50604051613e456080826104e8565b600080516020615f078339815191525480600f0b825260801d600f0b6020820152600080516020615ee78339815191525480600f0b604083015260801c606082015290565b60405190613e9960c0836104e8565b8160a06000918281528260208201528260408201528260608201528260808201520152565b613ec6613e8a565b50613ecf613e8a565b50604051613ede60c0826104e8565b600080516020615d678339815191525460ff808216151583526001600160401b03600883901c81166020850152604883901c821615156040850152605083901c81166060850152609083901c9091161515608084015260989190911c1660a082015290565b7f18eb97ecd7366a8be310b7e675d67335c7604d5f47446a54a222473625a27e229080600080516020615d4783398151915255613f7e6147b4565b9061280060405192839283612652565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015613fd4575b613fc3575b50613f43565b6000613fce916104e8565b38613fbd565b613fdc61260f565b613fb8565b6002613ff5670de0b6b3a7640000836131a4565b1461403557807fb2743902575ffdab882dfa43a3501f82fbbefa0d2c637e393aed1e80e2cb840b91600080516020615e0783398151915255613f7e6147b4565b604051632012d38160e11b8152600490fd5b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af1801561408d575b61407c575b50613fe1565b6000614087916104e8565b38614076565b61409561260f565b614071565b60026140ae670de0b6b3a7640000836131a4565b1461403557807f6bf5f38f4e94f47ae7a4d6e56dbf388c856f890b5f0f2808b66914710b0266ca91600080516020615e8783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156141e1575b6141d0575b50614121614833565b6141c7576002614139670de0b6b3a7640000836131a4565b1461403557614146613ebe565b6001600160401b038083116141ae579161419e612800927f5dcd1837ba774ef7f1f06e50ad3f64097201da74055346f26a4c7dea9af9084e948316602082015260018152600080516020615d678339815191526141ee565b6040519081529081906020820190565b60405163477e89e360e01b815260048101849052602490fd5b610a389061409a565b60006141db916104e8565b38614118565b6141e961260f565b614113565b81518154602084015160408501516060860151600160501b600160901b0360509190911b166001600160901b031990931693151560ff1693909317610100600160481b0360089290921b919091161760ff60481b92151560481b9290921691909117178155610a38916142969060a09061428861426e6080830151151590565b855460ff60901b191690151560901b60ff60901b16178555565b01516001600160401b031690565b8154600160981b600160d81b03191660989190911b600160981b600160d81b0316179055565b60026142d0670de0b6b3a7640000836131a4565b1461403557807f8e37539629486a88c6a6083eb90030fb61cb856d56d96f53a326fda0d399ef3291600080516020615ea783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156143dd575b6143cc575b50614343614833565b6143c357600261435b670de0b6b3a7640000836131a4565b1461403557614368613ebe565b6001600160401b038083116141ae579161419e612800927f4024ee9b51b90807c93e46f7e500580ef5b0b8491e1105188a44f62eed26b129948316606082015260016040820152600080516020615d678339815191526141ee565b610a38906142bc565b60006143d7916104e8565b3861433a565b6143e561260f565b614335565b60026143fe670de0b6b3a7640000836131a4565b1461403557807fd07cf37924efa8fca893c372ddfb1614e6fd8c02cfcc9205262535680b77b93491600080516020615e6783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af1801561450b575b6144fa575b50614471614833565b6144f1576002614489670de0b6b3a7640000836131a4565b1461403557614496613ebe565b6001600160401b038083116141ae579161419e612800927f75d77d82706bf877275b9bc542ae4f30aca347d73558e05b56b35a1452f8613294831660a082015260016080820152600080516020615d678339815191526141ee565b610a38906143ea565b6000614505916104e8565b38614468565b61451361260f565b614463565b7fec4e0c10e4e0d362960c0114996546aa9c4d6cc297b00a7577e127b720791beb9080600080516020615f4783398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015614599575b614588575b50614518565b6000614593916104e8565b38614582565b6145a161260f565b61457d565b60a07fb08b24c7f4e8b392d39bbaf1f4aa9bbb733ba9a467559eb8d9e2ffb634658e9091805161463860018060801b031991600080516020615f0783398151915261460a8482541660018060801b03938416178083556020870151600f0b90614657565b90556040840151600080516020615ee783398151915293845416908216179081845560608501511690614657565b90556146426147b4565b61464f6040518093611de9565b6080820152a1565b6001600160801b031660809190911b6001600160801b0319161790565b303b1561000e57604051630476982d60e21b8152610a3891613de29160008160048183305af180156146bf575b6146ae575b503690612402565b60006146b9916104e8565b386146a6565b6146c761260f565b6146a1565b6146d4613ebe565b80511590811580926147a7575b801561479a575b156128e657610a389161477e575b6040810151614762575b6080810151614746575b6147328160a06000918281528260208201528260408201528260608201528260808201520152565b600080516020615d678339815191526141ee565b60a081015161475d906001600160401b03166143ea565b61470a565b6060810151614779906001600160401b03166142bc565b614700565b6020810151614795906001600160401b031661409a565b6146f6565b50608081015115156146e8565b50604081015115156146e1565b303b156131b55760405163301fd1f560e21b8152602081600481305afa9081156147fc575b6000916147e4575090565b61055b915060203d81116108965761088781836104e8565b61480461260f565b6147d9565b919082604091031261000e576040516148236040826104e8565b6020808294805184520151910152565b6040516359ea287d60e01b815260a081600481305afa80156148c9575b600090614862575b61055b91506148d6565b60a03d81116148c2575b61487681846104e8565b82019060a08383031261075b5750906148b861055b9260606040519361489c82866104e8565b805185526148ad8360208301614809565b602086015201614809565b6040820152614858565b503d61486c565b6148d161260f565b614850565b6148e360208201516148f7565b90816148ed575090565b61055b9150604001515b8051159081614904575090565b6020915001511590565b61491661261c565b5061491f61261c565b5060405161492e6060826104e8565b600080516020615dc78339815191525460ff811661494b8161040f565b825260ff8160081c1661495d8161040f565b602083015261ffff1916604082015290565b303b151580614a33575b6117b857614992906000906001600160a01b0316614c17565b6149a461499f3683614a54565b614aa7565b15614a21576149b4903690614a54565b8051906149c08261040f565b6149c98261040f565b600080516020615dc78339815191529160ff83549116908160ff198216178455604061ff0060208501516149fc8161040f565b614a058161040f565b60081b1693848461ffff19809516171786550151169117179055565b604051639a51fe8f60e01b8152600490fd5b50600080516020615de78339815191525415614979565b6002111561000e57565b919082606091031261000e57604051614a6e6060826104e8565b604081938035614a7d81614a4a565b83526020810135614a8d81614a4a565b602084015201359061ffff198216820361000e5760400152565b60018151614ab48161040f565b614abd8261040f565b614ac68161040f565b14614ad8576040015161ffff19161590565b6001600160a01b0390614aea90614af1565b163b151590565b60018151614afe8161040f565b614b078261040f565b614b108161040f565b03614b28576040015160101c6001600160a01b031690565b8051604491614b368261040f565b604061ffff1991015116604051916327ada38760e11b8352614b578161040f565b60048301526024820152fd5b9081606091031261000e576040805191614b7e6060846104e8565b80518352602081015160208401520151604082015290565b61055b90614ba261261c565b50600080516020615da783398151915254604051637ece075d60e01b81526004810192909252606090829060249082906001600160a01b03165afa908115614c0a575b600091614bf25750614cd1565b611dcf915060603d8111611dd557611dc781836104e8565b614c1261260f565b614be5565b90813b15614c6a57816040917f41dd56c92c84169d8e89dc293d2649a911f47b357d3012bc88662395e01979d093600080516020615da78339815191525582519160018060a01b031682526020820152a1565b60405163d26af10d60e01b8152600490fd5b614c8461261c565b50600080516020615da78339815191525460405160016209351760e01b0319815261055b91606090829060049082906000906001600160a01b03165af1908115614c0a57600091614bf257505b614cd961261c565b50614ce261490e565b614cf26040830191825190614d1a565b905290565b6040810193929160209190614d0b8161040f565b8152614d168361040f565b0152565b8051614d258161040f565b6020820192835192614d368461040f565b614d40600061040f565b614d498361040f565b82614dd95750925b8051614d5c8161040f565b614d66600061040f565b614d6f8161040f565b614d795750505090565b60019051614d868161040f565b614d8f8261040f565b614d988161040f565b03614dbd57505061055b90614db7670de0b6b3a76400006000196130db565b90613c39565b610830604051928392631fafe5ed60e21b845260048401614cf7565b614de3600161040f565b614dec8361040f565b60018303614e045790614dfe91614e22565b92614d51565b5050610830604051928392631fafe5ed60e21b845260048401614cf7565b6001600160a01b0390614e3490614af1565b16604051906020928383019063d7c7a93560e01b8252602484015260248352614e5e6044846104e8565b614e686025614f59565b92614e7660405194856104e8565b602584527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668585015264185a5b195960da1b6040850152823b15614f08576000614ef39361055b969593829351915afa3d15614f00573d90614ed782614f59565b91614ee560405193846104e8565b82523d60008684013e614f83565b8051810182019101613c8b565b606090614f83565b60405162461bcd60e51b8152600481018690526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e746044820152631c9858dd60e21b6064820152608490fd5b6020906001600160401b038111614f76575b601f01601f19160190565b614f7e6104d1565b614f6b565b90919015614f8f575090565b815115614f9f5750805190602001fd5b60405162461bcd60e51b815290819061083090600483016105d1565b9392919061509190614fcb6131d2565b5061146261504e614fe8614fdf87856150c5565b938954906150c5565b94614ff16131d2565b50602080855195885196600088820398128189128116918913901516176150b8575b015196015195600087820397128188128116918813901516176150ab575b604051936150406040866104e8565b845260208401958652612d3c565b936150576131d2565b50615089602061508161506a885161313b565b95611462670de0b6b3a764000097889251906130db565b96015161313b565b9051906130db565b604051916150a06040846104e8565b825260208201529255565b6150b36128ea565b615031565b6150c06128ea565b615013565b6001916150d06131d2565b506000520160205261055b6040600020604051906150ef6040836104e8565b5480600f0b825260801d600f0b60208201526151096131d2565b5060208151910151604051916151206040846104e8565b600f0b8252600f0b602082015290565b6002916150d06131d2565b815181546001600160801b0319166001600160801b0390911617808255602090920151909161516d91600f0b90614657565b9055565b92949391948080516151839088615c0f565b9284828561518f6131d2565b50615199936153f3565b91906151a686838761561a565b6151af9161538f565b976001016151bc90612d5c565b906151c79185615731565b97906151d29161538f565b968101809111926152456152739361526c61524f61524a61524a9661528b99615300575b9c6151ff6131d2565b966020808d01519181880151808403938085116152f3575b82516152b657505060005b8a52019081511560001461529057505060005b602088015261524585518d6150c5565b61538f565b61530d565b615267895160018c0190600052602052604060002090565b61513b565b5187615130565b61526783516002860190600052602052604060002090565b519055565b6152b1916152a9670de0b6b3a7640000613b8f93613163565b905190613308565b615235565b6152e191613b8f91670de0b6b3a7640000918288029288840414911417156152e6575b835190613308565b615222565b6152ee6128ea565b6152d9565b6152fb6128ea565b615217565b6153086128ea565b6151f6565b6153156131d2565b5061532d6020615325835161533c565b92015161533c565b604051916151206040846104e8565b60016001607f1b0381136153775760016001607f1b0319811261535f57600f0b90565b60249060405190634e02165d60e01b82526004820152fd5b60249060405190632cd75ba360e11b82526004820152fd5b906153986131d2565b50602080835193835194600086820196871291129080158216911516176153e6575b01519101519060008282019283129112908015821691151617613258576040519161324e6040846104e8565b6153ee6128ea565b6153ba565b9391939290926154016131d2565b9460409182519363597e1fb560e01b85526020948581600481305afa9081156155f3575b6000916155d6575b506155c357848701908151156155a2578751156155a25785015185840151615454916132b8565b928482516154619061313b565b91015161546d91613c39565b615476906131c1565b61547f886132c5565b6154889161318d565b935163307648eb60e11b815290858083806154a68c60048301611cff565b0381305afa938415996154f861556098614db76154f2614db7996155279f99615542986155579b615595575b600092615578575b5050614db7613b8f670de0b6b3a7640000809e613163565b9161313b565b90615548600061552d8a61551561550e876131c1565b9788613163565b049e8f61552187615600565b976132b8565b8661310c565b941291821561556e5761554284915b5161313b565b90613c4f565b8d52156155665750915161313b565b916000196130db565b90840152565b90509161553c565b615542859161553c565b61558e9250803d106108965761088781836104e8565b388e6154da565b61559d61260f565b6154d2565b5050505060009294506155b69193506123e6565b9181835282015290600090565b50505060009294506155b69193506123e6565b6155ed9150863d88116107355761072781836104e8565b3861542d565b6155fb61260f565b615425565b6000811361561457600013613c7c57600090565b50600190565b9291926156256131d2565b9360409283519363597e1fb560e01b85526020948581600481305afa908115615724575b600091615707575b506156f457848401928351156156d6578451156156d6576156b46156ae6156a761569b61569161554297876156d09b9a986156c898015191015190613beb565b614db7875161313b565b614db7613b8f896132c5565b955161313b565b85613c4f565b614db7670de0b6b3a76400006000196130db565b87525161313b565b90830152565b509150506000929394506156ea91506123e6565b9181835282015290565b9150506000929394506156ea91506123e6565b61571e9150863d88116107355761072781836104e8565b38615651565b61572c61260f565b615649565b9192909261573d6131d2565b93615747816148d6565b615828579061575591615881565b60405190630dbc9ce160e01b825261579b61579561578e6020948581600481305afa90811561581b575b6000916157fe575b5084615830565b8093613272565b9161586e565b8451909490156157e85782906157b9613b8f83850151835190613308565b87525b018051909190156157d85761556091613b8f9151905190613308565b905061055b929391505190612901565b936157f883918284015190612901565b946157bc565b6158159150863d88116108965761088781836104e8565b38615787565b61582361260f565b61577f565b506000925050565b906158396131d2565b5061585e670de0b6b3a764000091602083615855838751613163565b04940151613163565b046040519161324e6040846104e8565b6020815191015181018091116129305790565b6158896131d2565b506158d46158c76158a560209360408582015191015190613214565b936158cc846150816158c760406158bc8a5161313b565b950194855190613c39565b6131c1565b905190613c39565b604051633f1d071f60e21b815290928282600481305afa9182156159a7575b600092615984575b5061594390615914670de0b6b3a7640000938492613163565b6040516343f0179b60e01b8152919004948482600481305afa918215615977575b600092615958575b50613163565b049061594f60406123e6565b92835282015290565b615970919250853d87116108965761088781836104e8565b903861593d565b61597f61260f565b615935565b6159439192506159a090843d86116108965761088781836104e8565b91906158fb565b6159af61260f565b6158f3565b6004906000926159d8575b8281558260018201558260028201558260038201550155565b6159e0610480565b6159bf565b6020615a086159f383612d3c565b936002840194615a0286612d5c565b90615a34565b815184559101516001830155615a1c575050565b615a2960006007936159b4565b01805460ff19169055565b91615a3d6131d2565b50615a47826148d6565b159081615a6b575b5015615a6457615a5e916131ed565b90600190565b5090600090565b90505181511038615a4f565b6131a0615ac56158c7670de0b6b3a764000093615ac0613b8f60408051634ec4474360e11b8152606081600481305afa908115615b35575b600091615b17575b50015192615b42565b613c39565b604051636c376cc560e01b815290602082600481305afa918215615b0a575b600092615af15750613163565b61597091925060203d81116108965761088781836104e8565b615b1261260f565b615ae4565b615b2f915060603d8111611dd557611dc781836104e8565b38615ab7565b615b3d61260f565b615aaf565b8051602090910151808210613303575090565b80541580615baf575b80615ba3575b6001820154159182615b96575b82615b89575b50159081615b83575090565b90501590565b6006015415915038615b77565b6004810154159250615b71565b50600581015415615b64565b50600381015415615b5e565b615bd9615bc782612d3c565b615bd360038401612d3c565b90613214565b6002615beb60058401548351906131a4565b14918215615bf857505090565b60060154602090910151600292506137ef916131a4565b90615c186131d2565b50600052602052604060002060405190615c336040836104e8565b546001600160801b03808216835260809190911c60208301908152918190615c596131d2565b5051169151166040519161324e6040846104e8565b90615c799082615c0f565b91615d06615c8f826001850195615a0287612d5c565b9390615c996131d2565b50615cb16020615ca98351615d1a565b920151615d1a565b9160405194615cc16040876104e8565b6001600160801b0392831686529282166020808701918252935160009081529190935260409020935184546001600160801b0319169082161780855591511690614657565b9055615d0f5750565b6000610a38916159b4565b6001600160801b0390818111615d2e571690565b60249060405190635385129160e01b82526004820152fdfe968cf792ff9a89745e4746179e93a7b9d7f08b0ff8366fd6f6dbd524ef107464d729c7f2aea8904a802db9fc1939086967cdf7fffe1510c25ccafabfc894614eb9726781b72c53f23217f424d70445b222951f008aeac7eece8139caed71ed2d6c0d5e3cd81753b1b21f67f61d56a97aae7a3e0179486d114788ad4576f53266630ac9ad193fa8d8f5a7207eefdee35934d664003a3d4c286a591e065a62034ead57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398cace7e947336f94057b47a9ab5531b0363e85c8d36c05c7d915ec8e525fd159d863625b85818a29587ee919ee6a968ee0b32f3513f2884b3968001062ba49eb6b1b30fe15febd596dffd21d4da0657732eea42b4b5a9789e3e6daab3d570999d7850062f2c27d17cdf727c8059e0b505bd3a788af62482a56bcede987d8eea5a35a294f9055e9dc7a18078b4e0139086766d723c3cd728bd59cc1f3b589741ed21d7cfd39841edd73967db6350efae442ebd8c6e1bfca55faa52b046d39b7e493bdea2cc426745068386b3804e5b401ae87ffbae9dbf293944b5307f507040c79917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f7917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f6f98b31465ac12e92b5cb136ade913276c267463c4395bb1a3999bc88fb837806897858f7b7d3c8b4e7a700b401ad192a110353a60c809946583c0d62cda7f0b70e555410d8128dff796eab5d29b97dd593ce9cab44a71b64c08244579ea6053339854479080fac0b5e7c0ecedb0fb02308a72a43cd102c6b9f918653d3400367a2646970667358221220c7754a6e80b15d2df75708d6c5c417eb426054257d82eab1d7005bad8acc702364736f6c63430008110033" + "numDeployments": 3, + "solcInputHash": "008bd4aa82b76d91af7a1bfbf9fddc30", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CurveMathOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Fixed18OverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"}],\"name\":\"Fixed18PackingOverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"}],\"name\":\"Fixed18PackingUnderflowError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidControllerError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"NotAccountOrMultiInvokerError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotCollateralError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"NotOwnerError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"}],\"name\":\"NotProductError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParamProviderInvalidParamValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PausedError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"name\":\"PayoffDefinitionNotContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"}],\"name\":\"PayoffDefinitionUnsupportedTransform\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PayoffProviderInvalidOracle\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PayoffProviderInvalidPayoffDefinitionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PendingFeeUpdatesUnsupportedValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductClosedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductDoubleSidedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductInLiquidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductInsufficientCollateralError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"socializationFactor\",\"type\":\"uint256\"}],\"name\":\"ProductInsufficientLiquidityError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductMakerOverLimitError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductOracleBootstrappingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProductOverClosedError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"UFixed18PackingOverflowError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UInitializableAlreadyInitializedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableNotInitializingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableZeroVersionError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UReentrancyGuardReentrantCallError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toVersion\",\"type\":\"uint256\"}],\"name\":\"AccountSettle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"newClosed\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"ClosedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newFundingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"FundingFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"JumpRateUtilizationCurveUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMaintenance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MaintenanceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MakeClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MakeOpened\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"MakerLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"OracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"}],\"name\":\"PendingMakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"}],\"name\":\"PendingPositionFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"}],\"name\":\"PendingTakerFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"PositionFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toVersion\",\"type\":\"uint256\"}],\"name\":\"Settle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TakeClosed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TakeOpened\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"TakerFeeUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"atVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"Fixed18\",\"name\":\"price\",\"type\":\"int256\"}],\"internalType\":\"struct IOracleProvider.OracleVersion\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"closeAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeMake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeMakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeTake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"closeTakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"Fixed18\",\"name\":\"price\",\"type\":\"int256\"}],\"internalType\":\"struct IOracleProvider.OracleVersion\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"internalType\":\"struct PayoffDefinition\",\"name\":\"payoffDefinition\",\"type\":\"tuple\"},{\"internalType\":\"contract IOracleProvider\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"maintenance\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"fundingFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"makerFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"takerFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"positionFee\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"makerLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"utilizationCurve\",\"type\":\"tuple\"}],\"internalType\":\"struct IProduct.ProductInfo\",\"name\":\"productInfo_\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isClosed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isLiquidating\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"latestVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maintenance\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"maintenance\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"maintenanceNext\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makerFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"makerLimit\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openMake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openMakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openTake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"UFixed18\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"openTakeFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IOracleProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoffDefinition\",\"outputs\":[{\"components\":[{\"internalType\":\"enum PayoffDefinitionLib.PayoffType\",\"name\":\"payoffType\",\"type\":\"uint8\"},{\"internalType\":\"enum PayoffDefinitionLib.PayoffDirection\",\"name\":\"payoffDirection\",\"type\":\"uint8\"},{\"internalType\":\"bytes30\",\"name\":\"data\",\"type\":\"bytes30\"}],\"internalType\":\"struct PayoffDefinition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingFeeUpdates\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"makerFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingMakerFee\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"takerFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingTakerFee\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"positionFeeUpdated\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"pendingPositionFee\",\"type\":\"uint64\"}],\"internalType\":\"struct PendingFeeUpdates\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"position\",\"outputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"positionAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"positionFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"pre\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"openPosition\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"closePosition\",\"type\":\"tuple\"}],\"internalType\":\"struct PrePosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pre\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"openPosition\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"closePosition\",\"type\":\"tuple\"}],\"internalType\":\"struct PrePosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"UFixed18\",\"name\":\"maker\",\"type\":\"uint256\"},{\"internalType\":\"UFixed18\",\"name\":\"taker\",\"type\":\"uint256\"}],\"internalType\":\"struct Position\",\"name\":\"position_\",\"type\":\"tuple\"}],\"name\":\"rate\",\"outputs\":[{\"internalType\":\"Fixed18\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"settleAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"shareAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"Fixed18\",\"name\":\"maker\",\"type\":\"int256\"},{\"internalType\":\"Fixed18\",\"name\":\"taker\",\"type\":\"int256\"}],\"internalType\":\"struct Accumulator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"takerFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"newClosed\",\"type\":\"bool\"}],\"name\":\"updateClosed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newFundingFee\",\"type\":\"uint256\"}],\"name\":\"updateFundingFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMaintenance\",\"type\":\"uint256\"}],\"name\":\"updateMaintenance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMakerFee\",\"type\":\"uint256\"}],\"name\":\"updateMakerFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMakerLimit\",\"type\":\"uint256\"}],\"name\":\"updateMakerLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IOracleProvider\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"updateOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newPositionFee\",\"type\":\"uint256\"}],\"name\":\"updatePositionFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newTakerFee\",\"type\":\"uint256\"}],\"name\":\"updateTakerFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"newUtilizationCurve\",\"type\":\"tuple\"}],\"name\":\"updateUtilizationCurve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"utilizationCurve\",\"outputs\":[{\"components\":[{\"internalType\":\"PackedFixed18\",\"name\":\"minRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"maxRate\",\"type\":\"int128\"},{\"internalType\":\"PackedFixed18\",\"name\":\"targetRate\",\"type\":\"int128\"},{\"internalType\":\"PackedUFixed18\",\"name\":\"targetUtilization\",\"type\":\"uint128\"}],\"internalType\":\"struct JumpRateUtilizationCurve\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"oracleVersion\",\"type\":\"uint256\"}],\"name\":\"valueAtVersion\",\"outputs\":[{\"components\":[{\"internalType\":\"Fixed18\",\"name\":\"maker\",\"type\":\"int256\"},{\"internalType\":\"Fixed18\",\"name\":\"taker\",\"type\":\"int256\"}],\"internalType\":\"struct Accumulator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Cloned by the Controller contract to launch new product markets.\",\"kind\":\"dev\",\"methods\":{\"atVersion(uint256)\":{\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Oracle version at `oracleVersion` with price transformed by payoff function\"}},\"closeAll(address)\":{\"details\":\"Only callable by the Collateral contract as part of the liquidation flow\",\"params\":{\"account\":\"Account to close out\"}},\"closeMake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to close\"}},\"closeMakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to close the position for\",\"amount\":\"Amount of the position to close\"}},\"closeTake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to close\"}},\"closeTakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to close the position for\",\"amount\":\"Amount of the position to close\"}},\"currentVersion()\":{\"returns\":{\"_0\":\"Current oracle version transformed by the payoff definition\"}},\"initialize((string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"params\":{\"productInfo_\":\"Product initialization params\"}},\"isClosed(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The the account is closed\"}},\"isLiquidating(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Whether the account is in liquidation\"}},\"latestVersion()\":{\"returns\":{\"_0\":\"Latest settled oracle version of the product\"}},\"latestVersion(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Latest settled oracle version of the account\"}},\"maintenance(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The current maintenance requirement\"}},\"maintenanceNext(address)\":{\"details\":\"Assumes no price change and no funding, used to protect user from over-opening\",\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"The next maintenance requirement\"}},\"openMake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to open\"}},\"openMakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to open position for\",\"amount\":\"Amount of the position to open\"}},\"openTake(uint256)\":{\"params\":{\"amount\":\"Amount of the position to open\"}},\"openTakeFor(address,uint256)\":{\"params\":{\"account\":\"Account to open the position for\",\"amount\":\"Amount of the position to open\"}},\"position(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Current position of the account\"}},\"positionAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global position at oracle version\"}},\"pre()\":{\"returns\":{\"_0\":\"Global pending-settlement position\"}},\"pre(address)\":{\"params\":{\"account\":\"Account to return for\"},\"returns\":{\"_0\":\"Current pre-position of the account\"}},\"rate((uint256,uint256))\":{\"details\":\"Handles 0-maker/taker edge cases\",\"params\":{\"position_\":\"Position to base utilization on\"},\"returns\":{\"_0\":\"The per-second rate\"}},\"settleAccount(address)\":{\"params\":{\"account\":\"Account to settle\"}},\"shareAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global accumulator share at oracle version\"}},\"updateClosed(bool)\":{\"details\":\"only callable by product owner. Settles the product before flipping the flag\",\"params\":{\"newClosed\":\"new closed value\"}},\"updateFundingFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newFundingFee\":\"new funding fee value\"}},\"updateMaintenance(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMaintenance\":\"new maintenance value\"}},\"updateMakerFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMakerFee\":\"new maker fee value\"}},\"updateMakerLimit(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newMakerLimit\":\"new maker limit value\"}},\"updateOracle(address)\":{\"details\":\"only callable by product owner\",\"params\":{\"newOracle\":\"new oracle address\"}},\"updatePositionFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newPositionFee\":\"new position fee value\"}},\"updateTakerFee(uint256)\":{\"details\":\"only callable by product owner\",\"params\":{\"newTakerFee\":\"new taker fee value\"}},\"updateUtilizationCurve((int128,int128,int128,uint128))\":{\"details\":\"only callable by product owner\",\"params\":{\"newUtilizationCurve\":\"new utilization curve value\"}},\"valueAtVersion(uint256)\":{\"details\":\"Only valid for the version at which a global settlement occurred\",\"params\":{\"oracleVersion\":\"Oracle version to return for\"},\"returns\":{\"_0\":\"Global accumulator value at oracle version\"}}},\"stateVariables\":{\"_accumulator\":{\"details\":\"The global accumulator state for the product\"},\"_accumulators\":{\"details\":\"The individual accumulator state for each account\"},\"_closed\":{\"details\":\"Whether or not the product is closed\"},\"_position\":{\"details\":\"The global position state for the product\"},\"_positions\":{\"details\":\"The individual position state for each account\"},\"name\":{\"details\":\"The name of the product\"},\"symbol\":{\"details\":\"The symbol of the product\"}},\"title\":\"Product\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"atVersion(uint256)\":{\"notice\":\"Returns the oracle version at `oracleVersion` transformed by the payoff definition\"},\"closeAll(address)\":{\"notice\":\"Closes all open and pending positions, locking for liquidation\"},\"closeMake(uint256)\":{\"notice\":\"Closes a maker position for `msg.sender`\"},\"closeMakeFor(address,uint256)\":{\"notice\":\"Closes a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"closeTake(uint256)\":{\"notice\":\"Closes a taker position for `msg.sender`\"},\"closeTakeFor(address,uint256)\":{\"notice\":\"Closes a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"currentVersion()\":{\"notice\":\"Returns the current oracle version transformed by the payoff definition\"},\"initialize((string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"notice\":\"Initializes the contract state\"},\"isClosed(address)\":{\"notice\":\"Returns whether `account` has a completely zero'd position\"},\"isLiquidating(address)\":{\"notice\":\"Returns whether `account` is currently locked for an in-progress liquidation\"},\"latestVersion()\":{\"notice\":\"Returns the global latest settled oracle version\"},\"latestVersion(address)\":{\"notice\":\"Returns `account`'s latest settled oracle version\"},\"maintenance(address)\":{\"notice\":\"Returns the maintenance requirement for `account`\"},\"maintenanceNext(address)\":{\"notice\":\"Returns the maintenance requirement for `account` after next settlement\"},\"openMake(uint256)\":{\"notice\":\"Opens a maker position for `msg.sender`\"},\"openMakeFor(address,uint256)\":{\"notice\":\"Opens a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"openTake(uint256)\":{\"notice\":\"Opens a taker position for `msg.sender`\"},\"openTakeFor(address,uint256)\":{\"notice\":\"Opens a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\"},\"position(address)\":{\"notice\":\"Returns `account`'s current position\"},\"positionAtVersion(uint256)\":{\"notice\":\"Returns the global position at oracleVersion `oracleVersion`\"},\"pre()\":{\"notice\":\"Returns the current global pending-settlement position\"},\"pre(address)\":{\"notice\":\"Returns `account`'s current pending-settlement position\"},\"rate((uint256,uint256))\":{\"notice\":\"Returns The per-second rate based on the provided `position`\"},\"settle()\":{\"notice\":\"Surfaces global settlement externally\"},\"settleAccount(address)\":{\"notice\":\"Surfaces account settlement externally\"},\"shareAtVersion(uint256)\":{\"notice\":\"Returns the global accumulator share at oracleVersion `oracleVersion`\"},\"updateClosed(bool)\":{\"notice\":\"Updates product closed state\"},\"updateFundingFee(uint256)\":{\"notice\":\"Updates the funding fee to `newFundingFee`\"},\"updateMaintenance(uint256)\":{\"notice\":\"Updates the maintenance to `newMaintenance`\"},\"updateMakerFee(uint256)\":{\"notice\":\"Updates the maker fee to `newMakerFee`\"},\"updateMakerLimit(uint256)\":{\"notice\":\"Updates the maker limit to `newMakerLimit`\"},\"updateOracle(address)\":{\"notice\":\"Updates underlying product oracle\"},\"updatePositionFee(uint256)\":{\"notice\":\"Updates the position fee to `newPositionFee`\"},\"updateTakerFee(uint256)\":{\"notice\":\"Updates the taker fee to `newTakerFee`\"},\"updateUtilizationCurve((int128,int128,int128,uint128))\":{\"notice\":\"Updates the utilization curve to `newUtilizationCurve`\"},\"valueAtVersion(uint256)\":{\"notice\":\"Returns the global accumulator value at oracleVersion `oracleVersion`\"}},\"notice\":\"Manages logic and state for a single product market.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/product/Product.sol\":\"Product\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":true,\"cse\":true,\"deduplicate\":true,\"inliner\":true,\"jumpdestRemover\":true,\"orderLiterals\":true,\"peephole\":true,\"yul\":true,\"yulDetails\":{\"optimizerSteps\":\"dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul\",\"stackAllocation\":true}},\"runs\":1},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\":{\"keccak256\":\"0xb9c0b0fc0dfcd44492b029ede04d304f6906b030cb925dc0fc2579e8c58d9734\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://a013a45803a911ea2e797ffd54c457ccd4d6250680c1bec9931b4ea97a6665ad\",\"dweb:/ipfs/QmWy6PxqoFBnHF5oHnn9pmrthz2ktHnaobw8WzYgQ6TrbC\"]},\"@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol\":{\"keccak256\":\"0xdb96e26082a471c7803e892ecd8d2877f23cd9e31f13a3e407dd5f8909078864\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e347199f4798f8310f24fc4099f8ffd68d7a89273381198a70c89d91368ec8b5\",\"dweb:/ipfs/Qmb16jC83BBpseaWY6vMMEL1fkkSPTiuez86SAP6Vb25dx\"]},\"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\":{\"keccak256\":\"0x11e8ebb40917dcce08a6366e6fa8d25b037552d4ea66b96c13e6f45b1f817c52\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://48167543bd2b36b513aa5d637d831cb5053bbdec63e1cb901954a935aac7b74d\",\"dweb:/ipfs/QmVJrtmW44o6hcbV2EVd1mqcsKAFoiRs7XmLiGRBrxqHha\"]},\"@equilibria/root/control/unstructured/UInitializable.sol\":{\"keccak256\":\"0xd2743d8fcc220ed2ccdc0bba1db0a3e107741bd5c0cac47ca8c0b5a00ba2fd7f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://56aadd6e4d60dde940c2d1dd0f4d39aaca7666850a8af9f288c81cb36ef780d3\",\"dweb:/ipfs/QmSFeJURqupzavfsCTZJHQKDYDnzQnyGAA24oeDCDHpJz4\"]},\"@equilibria/root/control/unstructured/UReentrancyGuard.sol\":{\"keccak256\":\"0x4962245ca8fdda3dc40c0f942a3568d90fb69428a6927b058018b01c90eb9fc9\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://2fc71fcb0176819e0266d3e9ffc9f02548b8513d360d29aeb951577b997caed7\",\"dweb:/ipfs/QmQtdTj4akRn6ZNzQYB1KsxzgdewJGrZNaZp4WYGqbquZA\"]},\"@equilibria/root/curve/CurveMath.sol\":{\"keccak256\":\"0x60d159f9ddf0dbe81124ecad58bba734b4cf82877637ff8d9d7f3e92f2da4ded\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://21ec7d55c7edb5e33a8448f90f8229a69e3ad88ce36f174515008ef6a01aa6d3\",\"dweb:/ipfs/QmNR72iJ8ayUBg8KiwDEdU5bsPf2UU9APPXG4bU1Ehq6zk\"]},\"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\":{\"keccak256\":\"0xae202813874bc306d51b3dab8194c86f6483bb20bf1f673ddaee16aa8de567ff\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://078af55f041677c10be7eb87c4c4d7683288b2c04b936bccca9929315b4e7b45\",\"dweb:/ipfs/QmbmQsXNmfVxL95qHFQiaEQpt8PHohnpLdd94T3THYFubF\"]},\"@equilibria/root/number/types/Fixed18.sol\":{\"keccak256\":\"0x613587461ef3437ef33229cdda7d34ea746278721baf06e20b2e43977f43174d\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://630392f0e52d45747543e562ed58962bfa70c867031bdc2f304193072afbd618\",\"dweb:/ipfs/QmT1Zrvart6MYLvf4XqZUjm99L5AfuBcczV27ed3V4AvbW\"]},\"@equilibria/root/number/types/PackedFixed18.sol\":{\"keccak256\":\"0xb52960cc8e3132e45d342bbbb1c6a96219022cd8557997933bd8250170268b64\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d3dde781dcb4cd5b7aff0d1a2b5d38bd9a321afd371aed6f88e4b4b2bc2a5984\",\"dweb:/ipfs/QmYaAukn1c8tE21HC2N415XZxT1H8zMQeoUoxh3iJTgxyA\"]},\"@equilibria/root/number/types/PackedUFixed18.sol\":{\"keccak256\":\"0xb5c5cd32d6530b2fe75228b6be32ebcb7762f6d7988b85a6b85a289ce8256d51\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://162ccf052216233008e732f0059d7cfde5c0aa70a5d4cf6549b1840f2ea791cc\",\"dweb:/ipfs/QmT95S1UHQbsT2ehAG42tLw4RUwCGijQ4fTkndL126yJmE\"]},\"@equilibria/root/number/types/UFixed18.sol\":{\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://eb72bd190425ef3165df4c255617dfccb494563b3f9953c91aa8c4619cce779f\",\"dweb:/ipfs/QmZdmxTZh8DtGZeE1xzrPxSDNnicRTXpPgG97AsbE3TA3C\"]},\"@equilibria/root/storage/UStorage.sol\":{\"keccak256\":\"0xe2b8491d1b5aa93f7e059e1a8f156b0ab37fef9ed973be97a64f2eabfc2cc172\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://67fd3b83c6e94369d5a75c8fbd15341c4f0c12d6612dc222bc4d82882c1c0f93\",\"dweb:/ipfs/QmNj8i2c5mZysTxoQWg2A21iWyYna6okSHQjHvp6ycQ1Mh\"]},\"@equilibria/root/token/types/Token18.sol\":{\"keccak256\":\"0x6b12afaece814f0ab186200a4729e93eb685a21d3e9b5a3372ff283a7ad5dc23\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e0118aeb6adc917b2ceadb82cc3a7a56d144ce4c8479296a4b288998c95e23e8\",\"dweb:/ipfs/QmcuREZS6RQU4brXKJ6cYE9dadqMJkrSrRDS7uEVau9eLJ\"]},\"@equilibria/root/token/types/Token6.sol\":{\"keccak256\":\"0x5ec7bee45a0e13f91ab2399472cf11136496073ad470cd70244855e12a7b6e65\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1aa85b4f3e8c72530bd1ef51445400ca646e1c809b9519f7ad8da588632a43b2\",\"dweb:/ipfs/QmS43PEuLdSaGrELtQ7wVg9wZB3NN2HbaSdDSy2GMxuofT\"]},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4632c341a06ba5c079b51ca5a915efab4e6ab57735b37839b3e8365ff806a43e\",\"dweb:/ipfs/QmTHT3xHYed2wajEoA5qu7ii2BxLpPhQZHwAhtLK5Z7ANK\"]},\"@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b3a57d0854b2fdce6ebff933a48dca2445643d1eccfc27f00292e937f26c6a58\",\"dweb:/ipfs/QmW45rZooS9TqR4YXUbjRbtf2Bpb5ouSarBvfW1LdGprvV\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ab84f13e6e6e0823854a0cddd49e96df052092d5919f95587607f0ed28a64cb6\",\"dweb:/ipfs/QmbNtqAq23ZDjCzHukQaa7B3y6rcobscm6FZF5PMQXcnVr\"]},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"contracts/controller/UControllerProvider.sol\":{\"keccak256\":\"0xf1563a6a8849193342e759b942b7c85b97d4c96fae03c3d09d8f4f32d1933593\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b897a1523ac1c779810260b01e77f7d2293707e3ff0685f3997f831de53cc087\",\"dweb:/ipfs/QmafCuN5GtmTerFR7JVp4qQipnF6sZ5kLkP1NvFv398TCZ\"]},\"contracts/interfaces/ICollateral.sol\":{\"keccak256\":\"0x6fb67eb5fc3ed4a74522677da3349d75105389369892756a60fcab4c901d352b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://af5a9b9bf3c72cb88230413966455cfcb0d43f88f1eeb52f8f083ca8cd46d55f\",\"dweb:/ipfs/Qmd8VjEoZpuY7CcDD942adQkwa9QVfyX6kEgBQ5gRymaMh\"]},\"contracts/interfaces/IContractPayoffProvider.sol\":{\"keccak256\":\"0xd73df106d032e976fd959ee6713240e36f54277ce5f215eaec8d5a2c6720a86b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b7932019acd64c5310eb266645d9bf9d13ba414ad4cbb8399b5c5fd5702d5d14\",\"dweb:/ipfs/QmVCXi3HXbGxm3kd6MsMULEFjtq8ecWvtREXnkgPgQFNnr\"]},\"contracts/interfaces/IController.sol\":{\"keccak256\":\"0xb6798b45b76edb91f6e56380eeeacdcfb37bbeb620a2d9c3e9993c39675bbd48\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://734265e658ee8f87a0a08471fcdc65d882f7dd49ee3efc5559b7c7282f619771\",\"dweb:/ipfs/QmYvK4xyECRyPtNhPybtMv3BKRuSZRi47WtaFruosn3Wfc\"]},\"contracts/interfaces/IIncentivizer.sol\":{\"keccak256\":\"0xd9d65d1190d830c8b797829f94194db86bb712e51f404e8c3e2c9b1df5645649\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d248dc35209163884a17bcd7c0b31cf2d2281937f1010b30a42cfad0a2e12b68\",\"dweb:/ipfs/QmWkBSxtdPt3NPMMfBe3z4xhARXR5X4yCXPzCddYwxqEcy\"]},\"contracts/interfaces/IMultiInvoker.sol\":{\"keccak256\":\"0xf54645562fc10f688ac76328858ed1299e8f30eb1be4f4196f016f9851c6c3c9\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://21d08c2d2034a39aea1013a091c060bbb9746e359a9354698c048591fd2cc3c1\",\"dweb:/ipfs/QmckeJMLvf7feXVXijVZqyTY8ohHW3XhnZ3Lms8y5TtrDC\"]},\"contracts/interfaces/IParamProvider.sol\":{\"keccak256\":\"0x21584bd07296eb4e8bd6076fd20afad320e781c19c60b479c9340c69b0f37517\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://2f2383b1730f8cd24391e0fb0beb4bbac4b61a40c6cffbae896dcc76b1db082e\",\"dweb:/ipfs/QmbvpuozfVnqU9nfTcEjpspDkrQVHW1mQHGiwiH8ukdoNM\"]},\"contracts/interfaces/IPayoffProvider.sol\":{\"keccak256\":\"0x803d22f7513c2c5186f77f6bc7cc34673ed762e40f106f9aef512eb9b57018af\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1403986623f860afabf115596051af425c80cc249fb148253a5e87dfd455aed2\",\"dweb:/ipfs/QmUhBNs3KpUEA4KenAcpd5oVQJBGTR5V1u8mX6F8bAg8kc\"]},\"contracts/interfaces/IProduct.sol\":{\"keccak256\":\"0x8e53ea97d8d59519adcbc2aa3600b5e51de1d59efec485a88eca8b574a35a00f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://7da1edcd8f7dc5da9c8ecf338e937499819fb17603909b7d581f6a06286fe6c2\",\"dweb:/ipfs/QmaRHxZToKkQPihgegwv5F9jZTf4Q78WVSPmLNa2wLQoZ8\"]},\"contracts/interfaces/types/Accumulator.sol\":{\"keccak256\":\"0x7ccd0a72aa593cefb9f4337cf312799f357b82fcb3f0379de0dc503d1cb7e387\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://884ee8101d531f8f596620dbe6f513bdaea06c5d113865fabb26131320286341\",\"dweb:/ipfs/QmRKjXfdTPqErTBz4xFvZMTVX88jxKKw14f1rcfAF7Z2Mr\"]},\"contracts/interfaces/types/PackedAccumulator.sol\":{\"keccak256\":\"0xd83f2822d4f6c818087a232b54007730992c34ff77377fc307a282f886e7cf65\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://0c9c635aa32e6feac02cd3d979f21dd01d70fce677da803958a5f7bf8262177d\",\"dweb:/ipfs/QmQnYbmci8WqyBNzvY7cer56Kwf9PU2Rt3GNn5rdzDQzRa\"]},\"contracts/interfaces/types/PackedPosition.sol\":{\"keccak256\":\"0x04968e6794f6244cb3415cea111d640273a81faea957872988d0cb580f45df1e\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://86c7a1c999d14ef22410bca74c51d3fbdf5ad0160a38eaad89c5e38361b981d0\",\"dweb:/ipfs/QmehdLThnFyoEv79C5xoSPmGFPxjmFvMjcCY94BD2iYmKN\"]},\"contracts/interfaces/types/PayoffDefinition.sol\":{\"keccak256\":\"0x99f9b5d5facba16885a375beac2a05129e7b23a8cceee048a7affd7f12a18a8f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://dfaffcac92ebc04fef807ccfae17db0351915e7adb1773ee26334e0587618816\",\"dweb:/ipfs/QmPSDaVSM2z5MrMhUiMFs87irR9kNhhhSQJ1UMLXSkvjPE\"]},\"contracts/interfaces/types/PendingFeeUpdates.sol\":{\"keccak256\":\"0xd98c681bdd6e1808e311615b3c4ac3b557ce5ec461f7b1cc645a51590eaf6f93\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://a59012b0fa282b06a97dec9e0df0523257252284ea34d0b4400af7de70838577\",\"dweb:/ipfs/QmTfNDGMoanmh2znjkqdVR3YgRqZdgPAhQ11c8xaPMLQkw\"]},\"contracts/interfaces/types/Position.sol\":{\"keccak256\":\"0x367918730021f3d6b7035f40c53b00b4316eb5e7fa409ed6285ba6d49971aab1\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://46483854393228b729c6f0aafc419b3971e585e576d1493051fd1f276f14452d\",\"dweb:/ipfs/QmU7PMGN4WZftsQVUzPyucrCFELKhguHVTSTdFbuPwcoZd\"]},\"contracts/interfaces/types/PrePosition.sol\":{\"keccak256\":\"0x0c9d701afdb67f0e134a5a0ba33ebb031fa146cb52b5871cbcd6522d9579264b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://c89b52094d0d37910f312d39aa551e689ee5c9727ba6e7c3dafc0a4ddac1eef4\",\"dweb:/ipfs/QmP5dtztRhJMXE3nGHp87vtAC93Er949cJuPP1HuWJjjSr\"]},\"contracts/interfaces/types/ProgramInfo.sol\":{\"keccak256\":\"0x280fcaf931b49abaec46b95ccbabaaf856a4b8e8d036413c9c3b3af25585d161\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e755bb9bb2fa8c2f2b20226c214cf7306dfa3d84c7cfc275104b7c546d86334b\",\"dweb:/ipfs/QmbFuHfUek97FYpVQF9hP9pUZUVyTaqejvpZAzbikFWVxn\"]},\"contracts/product/Product.sol\":{\"keccak256\":\"0xfbbfc54072d91f1772df60c6fac94eb801baa3ca5e3481a080dca17244c4ae09\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://3dda50de0595b6d38431c954d341948e818c950e1047dee7aab5b1daa3d9ac7e\",\"dweb:/ipfs/QmNzhMa79qTbt2dTXjoizHSdR1pPXbQz4jDxfWadnJ9yuG\"]},\"contracts/product/UParamProvider.sol\":{\"keccak256\":\"0xdd346fdc4c1e10c093265a811c035f7878e852b104bde73edacc3911f82337ab\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://e691f72f5006faea191846f5948b5dd1bc45ed45726484ceed20efc826151708\",\"dweb:/ipfs/QmdYcRWWTyGcj3idLCkeGL8AnHFAUPBJCH3ssr8dZ2WDHN\"]},\"contracts/product/UPayoffProvider.sol\":{\"keccak256\":\"0xb2be54ef6cf8444780f183a32d0ba44618b9868697d7eb0344359bd1ceefa3b8\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://d84febed6661f3cf3e8ec5baa6e83604dae7b1c492346a9b2ecb5564e9084d7c\",\"dweb:/ipfs/QmWdHHYqHWiX7STg8xW27gSR43Fg74T1XASn9XteiSXi48\"]},\"contracts/product/types/accumulator/AccountAccumulator.sol\":{\"keccak256\":\"0xda7efcfb641583cc1c7577f4348d97abe9e59989274d7bb166da2b19ebffd67a\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b0e5c9c2b8d7297cf3becea46412fc4adde42ddda3500944a8f75c8d004d1e34\",\"dweb:/ipfs/QmP2KQwbixuSCwZFdQX2uXBL9oXYBQQefbXvofZ3JX6PTx\"]},\"contracts/product/types/accumulator/VersionedAccumulator.sol\":{\"keccak256\":\"0xfa6c397bf064a7a7767c30f1c9be017a92b0a5f24f59ff1a132b81cd69f5c60a\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://c06c04121938bc5ccc53482eb9c5eb510ccf833d1e99f47dd72c51ee6fd9a1d3\",\"dweb:/ipfs/QmZegN29oqYbVjWQS3fLEC6HqamqwLBKP2aS56eo3aAg9q\"]},\"contracts/product/types/position/AccountPosition.sol\":{\"keccak256\":\"0x54bf5a232b1c14887a717bee9e935ac9f0f5de671a863cf2fcdbc1fd19a4dc85\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://993c7c9eb4da8573cb53fb282bb51d0aceb237de173391faad3bed232fb394b6\",\"dweb:/ipfs/QmYbWoMdtiJAPJeFY7WdmvD3weZ75bcLDH4ZdrPGHViPHZ\"]},\"contracts/product/types/position/VersionedPosition.sol\":{\"keccak256\":\"0x7e7314dc2829b47f03af3046280edb01a0bbe91cc63456f831f810eced8c1902\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://f1e13bb157fa60a63349a2139a7644868b70d9d23a49a3dea2581ea8926ed20a\",\"dweb:/ipfs/QmQGpogHBaXtbAuoGgTHHt4jBSNpD9NQsW6JfY3sRzAEic\"]}},\"version\":1}", + "bytecode": "0x6080806040523461001757615fd790816200001d8239f35b600080fdfe60806040526004361015610013575b600080fd5b60003560e01c806305d5c1cb146103fb57806306fdde03146103f25780630dbc9ce1146103e957806311da60b4146103e0578063153261e5146103d757806319377567146103ce5780631cb44dfc146103c55780631e0c6fb9146103bc57806320fe9c3c146103b3578063212e0ad3146103aa5780632131ea4a146103a15780632d2e52be146103985780633a25c1111461038f5780633e17b8c71461038657806343f0179b1461037d578063476fa96d1461037457806354fb39211461036b57806356bc1ad41461036257806358ca6f981461035957806359218fe914610350578063597e1fb51461034757806359ea287d1461033e5780635d16e1201461033557806360ec91d61461032c578063611c71b4146103235780636943b0171461031a5780636c376cc5146103115780636ecffff91461030857806373b88f3b146102ff57806376f37001146102f65780637dc0d1d0146102ed5780637ece075d146102e45780638c94b48f146102db5780638e480b20146102d257806391689024146102c95780639378bf7b146102c057806395d89b41146102b75780639a427d03146102ae5780639d888e86146102a5578063a12e1b331461029c578063ab582f2914610293578063b7648fb91461028a578063c07f47d414610281578063d7d7d6b814610278578063e1c3c98d1461026f578063e503b00714610266578063f667f8971461025d578063f6b3200814610254578063f77c47911461024b5763fc741c7c1461024357600080fd5b61000e6123b0565b5061000e612379565b5061000e6122c2565b5061000e612201565b5061000e6120cc565b5061000e611fc5565b5061000e611f01565b5061000e611ee2565b5061000e611e9d565b5061000e611e47565b5061000e611e1e565b5061000e611d45565b5061000e611d0f565b5061000e611cde565b5061000e611b95565b5061000e611b50565b5061000e611b12565b5061000e611a0b565b5061000e6119dd565b5061000e61197d565b5061000e6118c1565b5061000e6117eb565b5061000e611646565b5061000e61161a565b5061000e611576565b5061000e61146f565b5061000e61140d565b5061000e6113e1565b5061000e6113b9565b5061000e61138b565b5061000e6112db565b5061000e611295565b5061000e61118e565b5061000e611087565b5061000e61105c565b5061000e611030565b5061000e610f29565b5061000e610ebf565b5061000e610d66565b5061000e610bf4565b5061000e610ae2565b5061000e610a90565b5061000e610a3a565b5061000e6108e7565b5061000e6108aa565b5061000e61075e565b5061000e610676565b5061000e61064a565b5061000e61061a565b5061000e61042f565b600091031261000e57565b6002111561041957565b634e487b7160e01b600052602160045260246000fd5b503461000e57600036600319011261000e57606061044b61490e565b60405190805161045a8161040f565b8252602081015161046a8161040f565b6020830152604061ffff19910151166040820152f35b50634e487b7160e01b600052600060045260246000fd5b90600182811c921680156104c7575b60208310146104b157565b634e487b7160e01b600052602260045260246000fd5b91607f16916104a6565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101761050b57604052565b6105136104d1565b604052565b906105c4575b6040519081600082549261053184610497565b9081845260019485811690816000146105a1575060011461055e575b505061055b925003826104e8565b90565b9093915060005260209081600020936000915b81831061058957505061055b9350820101388061054d565b85548784018501529485019486945091830191610571565b91505061055b94506020925060ff191682840152151560051b820101388061054d565b6105cc610480565b61051e565b6020808252825181830181905290939260005b82811061060657505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016105e4565b503461000e57600036600319011261000e5761064661063a600080610518565b604051918291826105d1565b0390f35b503461000e57600036600319011261000e576020600080516020615e6283398151915254604051908152f35b503461000e5760008060031936011261075b57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561073c575b839161070e575b506106fc576001906106f7612663565b505580f35b604051633b3b4caf60e21b8152600490fd5b61072f915060203d8111610735575b61072781836104e8565b8101906125fa565b386106e7565b503d61071d565b61074461260f565b6106e0565b604051637990191b60e11b8152600490fd5b80fd5b503461000e57608036600319011261000e5761079061078b600080516020615f6283398151915254611971565b611971565b604051633e92a73360e11b8152906020908183806107b13060048301613d24565b0381845afa92831561089d575b60009361086e575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610861575b600092610834575b5050336001600160a01b0390911603610816576108146004614674565b005b60405163123d8bcf60e21b81526004810191909152602490fd5b0390fd5b6108539250803d1061085a575b61084b81836104e8565b81019061263d565b38806107f7565b503d610841565b61086961260f565b6107ef565b61088f919350823d8411610896575b61088781836104e8565b810190613c8b565b91386107c6565b503d61087d565b6108a561260f565b6107be565b503461000e57600036600319011261000e576020600080516020615f4283398151915254604051908152f35b6001600160a01b0381160361000e57565b503461000e5760208060031936011261000e5760043590610907826108d6565b61092261078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806109413060048301613d24565b0381845afa9283156109ec575b6000936109cd575b50604051635091e19f60e11b815260048101849052908290829060249082905afa9182156109c0575b6000926109a3575b5050336001600160a01b03909116036108165761081482613d81565b6109b99250803d1061085a5761084b81836104e8565b3880610987565b6109c861260f565b61097f565b6109e5919350823d84116108965761088781836104e8565b9138610956565b6109f461260f565b61094e565b60208091805184520151910152565b610a38909291926060604060a083019580518452610a2e602082015160208601906109f9565b01519101906109f9565b565b503461000e57602036600319011261000e57600435610a58816108d6565b610a60613a70565b5060018060a01b03166000526002602052610646610a846002604060002001612d5c565b60405191829182610a08565b503461000e57602036600319011261000e57610aaa6131d2565b50610646610abb600435600a6150c5565b604051918291829190916020806040830194805184520151910152565b8015150361000e57565b503461000e5760208060031936011261000e5760043590610b0282610ad8565b610b1d61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380610b3c3060048301613d24565b0381845afa928315610be7575b600093610bc8575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610bbb575b600092610b9e575b5050336001600160a01b03909116036108165761081482613d37565b610bb49250803d1061085a5761084b81836104e8565b3880610b82565b610bc361260f565b610b7a565b610be0919350823d84116108965761088781836104e8565b9138610b51565b610bef61260f565b610b49565b503461000e5760408060031936011261000e576004803590610c15826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610d4c575b600091610d2f575b50610d1f57808616331491858315610cc0575b505050905015610ca357600184610ca060243586613364565b55005b51636dc3a3c360e01b815290819061083090339085908401612d07565b9193819350855192838092630479e58f60e41b82525afa918215610d12575b600092610cf5575b505016331480388085610c87565b610d0b9250803d1061085a5761084b81836104e8565b3880610ce7565b610d1a61260f565b610cdf565b50505051633b3b4caf60e21b8152fd5b610d469150833d85116107355761072781836104e8565b38610c74565b610d5461260f565b610c6c565b51637990191b60e11b8152fd5b503461000e5760408060031936011261000e576004803590610d87826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610eb2575b600091610e95575b50610d1f57600080516020615ec283398151915254610e8557808616331491858315610e26575b505050905015610ca357600184610ca060243586613504565b9193819350855192838092630479e58f60e41b82525afa918215610e78575b600092610e5b575b505016331480388085610e0d565b610e719250803d1061085a5761084b81836104e8565b3880610e4d565b610e8061260f565b610e45565b5050505163ded15dbf60e01b8152fd5b610eac9150833d85116107355761072781836104e8565b38610de6565b610eba61260f565b610dde565b503461000e57600036600319011261000e5760c0610edb613ebe565b6040519080511515825260a060018060401b039182602082015116602085015260408101511515604085015282606082015116606085015260808101511515608085015201511660a0820152f35b503461000e5760208060031936011261000e57610f5761078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380610f763060048301613d24565b0381845afa928315611023575b600093611004575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610ff7575b600092610fda575b5050336001600160a01b0390911603610816576108146004356140ee565b610ff09250803d1061085a5761084b81836104e8565b3880610fbc565b610fff61260f565b610fb4565b61101c919350823d84116108965761088781836104e8565b9138610f8b565b61102b61260f565b610f83565b503461000e57600036600319011261000e576020600080516020615ea283398151915254604051908152f35b503461000e57602036600319011261000e576110766131d2565b50610646610abb600435600a615130565b503461000e5760208060031936011261000e576110b561078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806110d43060048301613d24565b0381845afa928315611181575b600093611162575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611155575b600092611138575b5050336001600160a01b03909116036108165761081460043561443e565b61114e9250803d1061085a5761084b81836104e8565b388061111a565b61115d61260f565b611112565b61117a919350823d84116108965761088781836104e8565b91386110e9565b61118961260f565b6110e1565b503461000e5760208060031936011261000e576111bc61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806111db3060048301613d24565b0381845afa928315611288575b600093611269575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561125c575b60009261123f575b5050336001600160a01b039091160361081657610814600435613f8e565b6112559250803d1061085a5761084b81836104e8565b3880611221565b61126461260f565b611219565b611281919350823d84116108965761088781836104e8565b91386111f0565b61129061260f565b6111e8565b503461000e57602036600319011261000e576004356112b3816108d6565b60018060a01b03166000526002602052602060ff600760406000200154166040519015158152f35b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561137e575b600091611360575b506106fc57600190610ca060043533613809565b611378915060203d81116107355761072781836104e8565b3861134c565b61138661260f565b611344565b503461000e57600036600319011261000e576020600080516020615ec2833981519152546040519015158152f35b503461000e57600036600319011261000e576113d3613a70565b50610646610a846004612d5c565b503461000e57600036600319011261000e576020600080516020615e0283398151915254604051908152f35b503461000e57604036600319011261000e576020611467611442611435600435602435613c65565b61143d613e25565b613aaf565b611462670de0b6b3a764000061145c816301e133806130db565b926130db565b613c04565b604051908152f35b503461000e5760208060031936011261000e5761149d61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806114bc3060048301613d24565b0381845afa928315611569575b60009361154a575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561153d575b600092611520575b5050336001600160a01b039091160361081657610814600435614310565b6115369250803d1061085a5761084b81836104e8565b3880611502565b61154561260f565b6114fa565b611562919350823d84116108965761088781836104e8565b91386114d1565b61157161260f565b6114c9565b503461000e57602036600319011261000e57600435611594816108d6565b60018060a01b0316600052600260205261064660406000206115ef604051916115be6060846104e8565b6115c781612d3c565b835260ff60076115d960028401612d5c565b92836020870152015416151560408401526148d6565b9081611609575b5060405190151581529081906020820190565b6116149150516148f7565b386115f6565b503461000e57600036600319011261000e576020600080516020615d4283398151915254604051908152f35b503461000e5760031960203682011261000e57600435906001600160401b03821161000e576102008260040191833603011261000e5760017f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b81815410156117d257819055600080516020615de283398151915292818455303b1515806117ca575b6117b857333b156117a6577fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f32936117906117896117a195602460009533600080516020615f628339815191525561172e61172460a483016123dc565b604483019061496f565b6117366125c1565b61176e611747366101848401612402565b61016483013561014484013561012485013561010486013560e487013560c4880135613d96565b61178261177b8480612466565b90896124ec565b0190612466565b90856124ec565b556040519081529081906020820190565b0390a1005b6040516314878b6960e01b8152600490fd5b604051631a27c4a960e21b8152600490fd5b5060006116c8565b604051631e7a9d9560e01b815260048101839052602490fd5b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156118b4575b600091611896575b506106fc57600080516020615ec28339815191525461188457600190610ca060043533612d21565b60405163ded15dbf60e01b8152600490fd5b6118ae915060203d81116107355761072781836104e8565b3861185c565b6118bc61260f565b611854565b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611964575b600091611946575b506106fc57600190610ca060043533613364565b61195e915060203d81116107355761072781836104e8565b38611932565b61196c61260f565b61192a565b6001600160a01b031690565b503461000e57600036600319011261000e57600080516020615da2833981519152546040516001600160a01b039091168152602090f35b6040809180518452602081015160208501520151910152565b606081019291610a3891906119b4565b503461000e57602036600319011261000e5760606119fc600435614b96565b611a0960405180926119b4565bf35b503461000e5760208060031936011261000e57611a3961078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380611a583060048301613d24565b0381845afa928315611b05575b600093611ae6575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611ad9575b600092611abc575b5050336001600160a01b039091160361081657610814600435614553565b611ad29250803d1061085a5761084b81836104e8565b3880611a9e565b611ae161260f565b611a96565b611afe919350823d84116108965761088781836104e8565b9138611a6d565b611b0d61260f565b611a65565b503461000e57602036600319011261000e57600435611b30816108d6565b60018060a01b031660005260096020526020604060002054604051908152f35b503461000e57602036600319011261000e57600435611b6e816108d6565b60018060a01b031660005260026020526020611467611b906040600020612d3c565b615a72565b503461000e5760408060031936011261000e576004803590611bb6826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115611cd1575b600091611cb4575b50610d1f57600080516020615ec283398151915254610e8557808616331491858315611c55575b505050905015610ca357600184610ca060243586612d21565b9193819350855192838092630479e58f60e41b82525afa918215611ca7575b600092611c8a575b505016331480388085611c3c565b611ca09250803d1061085a5761084b81836104e8565b3880611c7c565b611caf61260f565b611c74565b611ccb9150833d85116107355761072781836104e8565b38611c15565b611cd961260f565b611c0d565b503461000e57600036600319011261000e5761064661063a60006001610518565b604081019291610a3891906109f9565b503461000e57602036600319011261000e57611d296131d2565b506040611d396004356003615c0a565b611a09825180926109f9565b503461000e57600036600319011261000e57611d5f61261c565b50600080516020615da283398151915254604051634ec4474360e11b81526060916119fc91908390829060049082906001600160a01b03165afa908115611ddc575b600091611daf575b50614cd1565b611dcf9150833d8111611dd5575b611dc781836104e8565b810190614b63565b38611da9565b503d611dbd565b611de461260f565b611da1565b6060908051600f0b83526020810151600f0b60208401526040810151600f0b60408401528160018060801b0391015116910152565b503461000e57600036600319011261000e576080611e3a613e25565b611a096040518092611de9565b503461000e57602036600319011261000e57600435611e65816108d6565b60018060a01b031660005260026020526020611467611b906040600020611e976002611e9083612d3c565b9201612d5c565b906131ed565b503461000e57602036600319011261000e57600435611ebb816108d6565b611ec36131d2565b5060018060a01b031660005260026020526040611d3981600020612d3c565b503461000e57600036600319011261000e576020600a54604051908152f35b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611fb8575b600091611f9a575b506106fc57600080516020615ec28339815191525461188457600190610ca060043533613504565b611fb2915060203d81116107355761072781836104e8565b38611f72565b611fc061260f565b611f6a565b503461000e5760208060031936011261000e57611ff361078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806120123060048301613d24565b0381845afa9283156120bf575b6000936120a0575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215612093575b600092612076575b5050336001600160a01b039091160361081657610814600435614047565b61208c9250803d1061085a5761084b81836104e8565b3880612058565b61209b61260f565b612050565b6120b8919350823d84116108965761088781836104e8565b9138612027565b6120c761260f565b61201f565b503461000e5760408060031936011261000e5760048035906120ed826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa9081156121f4575b6000916121d7575b50610d1f57808616331491858315612178575b505050905015610ca357600184610ca060243586613809565b9193819350855192838092630479e58f60e41b82525afa9182156121ca575b6000926121ad575b50501633148038808561215f565b6121c39250803d1061085a5761084b81836104e8565b388061219f565b6121d261260f565b612197565b6121ee9150833d85116107355761072781836104e8565b3861214c565b6121fc61260f565b612144565b503461000e57602036600319011261000e5760043561221f816108d6565b600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156122b5575b600091612297575b506106fc57610ca0600192612291612663565b9061298a565b6122af915060203d81116107355761072781836104e8565b3861227e565b6122bd61260f565b612276565b503461000e57602036600319011261000e576004356122e0816108d6565b600460206122ff61078b600080516020615f6283398151915254611971565b60405163d8dfeb4560e01b815292839182905afa90811561236c575b60009161234e575b506001600160a01b0316330361233c57610814906139eb565b6040516340cbe9b160e01b8152600490fd5b612366915060203d811161085a5761084b81836104e8565b38612323565b61237461260f565b61231b565b503461000e57600036600319011261000e57600080516020615f62833981519152546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600080516020615e8283398151915254604051908152f35b3561055b816108d6565b90610a3860405192836104e8565b359081600f0b820361000e57565b919082608091031261000e5760405161241c6080826104e8565b60608193612429816123f4565b8352612437602082016123f4565b6020840152612448604082016123f4565b60408401520135906001600160801b038216820361000e5760600152565b903590601e198136030182121561000e57018035906001600160401b03821161000e5760200191813603831361000e57565b90601f81116124a657505050565b600091825260208220906020601f850160051c830194106124e2575b601f0160051c01915b8281106124d757505050565b8181556001016124cb565b90925082906124c2565b9092916001600160401b0381116125b4575b6125128161250c8454610497565b84612498565b6000601f821160011461254c5781929394600092612541575b50508160011b916000199060031b1c1916179055565b01359050388061252b565b601f1982169461256184600052602060002090565b91805b87811061259c575083600195969710612582575b505050811b019055565b0135600019600384901b60f8161c19169055388080612578565b90926020600181928686013581550194019101612564565b6125bc6104d1565b6124fe565b303b1515806125e3575b6117b8576001600080516020615e4283398151915255565b50600080516020615de283398151915254156125cb565b9081602091031261000e575161055b81610ad8565b506040513d6000823e3d90fd5b6040519061262b6060836104e8565b60006040838281528260208201520152565b9081602091031261000e575161055b816108d6565b908152602081019190915260400190565b61266b61261c565b50612684600080516020615f6283398151915254611971565b9061268d614c7c565b91600a5490835182146128e6576126a382614b96565b906126b085516004612916565b855181036128d7575084915b604051631bf1901f60e21b81526001600160a01b03926020929084169184908481600481875afa9081156128ca575b6000916128ad575b501690813b1561000e5760405163a55ff01d60e01b81528992600090829081838161272189600483016119cd565b03925af180156128a0575b61288b575b506127558661274d81612742613c9a565b94600386600a615171565b986003615c69565b61275d6146cc565b8551825103612857575b5050816004916040519283809263d8dfeb4560e01b82525afa91821561284a575b60009261282d575b50501691823b1561000e57604051637f3dd53b60e01b815260048101919091527f88a84ea6dd274b386afd27dbbe11b6192b25017f5e60bb8c4053dfddb45c294d926000908290602490829084905af18015612820575b612805575b505183519061280060405192839283612652565b0390a1565b80612814600061281a936104e8565b80610404565b386127ec565b61282861260f565b6127e7565b6128439250803d1061085a5761084b81836104e8565b3880612790565b61285261260f565b612788565b6004929661286e859388600361287495600a615171565b90612901565b956128828987516003615c69565b91889150612767565b80612814600061289a936104e8565b38612731565b6128a861260f565b61272c565b6128c49150853d871161085a5761084b81836104e8565b386126f3565b6128d261260f565b6126eb565b6128e090614b96565b916126bc565b5050565b50634e487b7160e01b600052601160045260246000fd5b9190820180921161290e57565b610a386128ea565b5480612920575090565b9050600181018091116129305790565b61055b6128ea565b9060018060a01b0316600052602052604060002090565b6001600160a01b039091168152608081019291610a3891602001906119b4565b6001600160a01b039091168152602081019190915260400190565b6129a2600080516020615f6283398151915254611971565b6129ad826009612938565b54835114612cc4576129cd60026129c48482612938565b01845190612916565b83518103612cb5575082915b60018060a01b038092166040805194631bf1901f60e21b9283875260208660049882818b81875afa908115612ca8575b600091612c8b575b5016803b1561000e578792878a92600088518092818381612a408d63060c0d2760e21b998a84528c840161294f565b03925af18015612c7e575b612c69575b50612a7c612a77612a628b6009612938565b612a6d8c6002612938565b600a8a5192614fbb565b612ce5565b97612a9187612a8c8c6002612938565b6159e5565b86518d5103612b85575b5050829086519283809263d8dfeb4560e01b82525afa918215612b78575b600092612b5b575b505016803b1561000e576000612b3494612b139287837f9d7055d24918d8c2fd08660a27bf31d4086fa71a51cd07874276470223aa480f9b8851968795869485936364e5a46f60e11b8552840161296f565b03925af18015612b4e575b612b39575b505195519051938493169583612652565b0390a2565b806128146000612b48936104e8565b38612b23565b612b5661260f565b612b1e565b612b719250803d1061085a5761084b81836104e8565b3880612ac1565b612b8061260f565b612ab9565b909491979250865190815283818c818b5afa908115612c5c575b600091612c3f575b5016803b1561000e57612c158a92612c0f612a778b8f808f9a838b998f60008094612bde8f9351978896879586948552840161294f565b03925af18015612c32575b612c1d575b50600a612c07612bff846009612938565b936002612938565b915192614fbb565b90612cc9565b969038612a9b565b806128146000612c2c936104e8565b38612bee565b612c3a61260f565b612be9565b612c569150843d861161085a5761084b81836104e8565b38612ba7565b612c6461260f565b612b9f565b806128146000612c78936104e8565b38612a50565b612c8661260f565b612a4b565b612ca29150833d851161085a5761084b81836104e8565b38612a11565b612cb061260f565b612a09565b612cbe90614b96565b916129d9565b505050565b9190916000838201938412911290801582169115161761290e57565b6020815191015190600082820192831291129080158216911516176129305790565b6001600160a01b0391821681529116602082015260400190565b90610a3891612d37612d31612663565b8261298a565b612d94565b90604051612d4b6040826104e8565b602060018294805484520154910152565b90604051612d6b6060826104e8565b6040612d8f6003839580548552612d8460018201612d3c565b602086015201612d3c565b910152565b60018060a01b03908181166000526020916002835260409360ff600786600020015416612f3b5790612dc7849284612f4c565b81612de361078b600080516020615f6283398151915254611971565b9186519586809463d8dfeb4560e01b825260049889915afa928315612f2e575b600093612f0f575b5086516301c8232360e71b8152928391829081612e2b308a8c8401612d07565b0392165afa918215612f02575b600092612ee5575b5050612ed657612e54612e59916002612938565b615b50565b612ec857600080516020615ec2833981519152546128e657612e90612e8b612e82600a54613a9b565b611e9784612d5c565b6132c5565b91612ea3670de0b6b3a7640000846131a4565b15612ead57505050565b5163d8b8b95160e01b81529081019182529081906020010390fd5b90516390898fd160e01b8152fd5b5090516324a21d2960e01b8152fd5b612efb9250803d106107355761072781836104e8565b3880612e40565b612f0a61260f565b612e38565b612f27919350823d841161085a5761084b81836104e8565b9138612e0b565b612f3661260f565b612e03565b8451636830d4d760e01b8152600490fd5b90612f58600a54614b96565b90612f72816002612f698682612938565b01845190613342565b612f7f8183516004613342565b612fae612f98612f9260408501516131c1565b8361318d565b600080516020615ea2833981519152549061318d565b9182612fe4575b516040516001600160a01b0390941693600080516020615d828339815191529350918291612b34919083612652565b61303d6004602061300661078b600080516020615f6283398151915254611971565b60405163d8dfeb4560e01b815292839182905afa9081156130ce575b6000916130b0575b506001600160a01b03169360001961310c565b833b1561000e576000613078600080516020615d828339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156130a3575b61308e575b50612fb5565b80612814600061309d936104e8565b38613088565b6130ab61260f565b613083565b6130c8915060203d811161085a5761084b81836104e8565b3861302a565b6130d661260f565b613022565b818102929160008212600160ff1b8214166130ff575b818405149015171561290e57565b6131076128ea565b6130f1565b60008113613135576000136131215750600090565b61312d61055b9161313b565b6000196130db565b5061055b905b6001600160ff1b03811161314c5790565b6024906040519062a07eb560e01b82526004820152fd5b8181029291811591840414171561290e57565b50634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916131a091613163565b0490565b8181116131ba57106131b557600190565b600090565b5050600290565b60008082126131ce575090565b0390565b604051906131e16040836104e8565b60006020838281520152565b90604061320b61055b936131ff6131d2565b50602084015190613214565b91015190613272565b9061321d6131d2565b5060208083519383518501809511613265575b01519101518101809111613258575b6040519161324e6040846104e8565b8252602082015290565b6132606128ea565b61323f565b61326d6128ea565b613230565b9061327b6131d2565b50602080835193835185039485116132ab575b01519101518103908111613258576040519161324e6040846104e8565b6132b36128ea565b61328e565b9190820391821161290e57565b602081015160009190806132e257505050670de0b6b3a764000090565b6132ec9151613308565b670de0b6b3a7640000915080821015613303575090565b905090565b670de0b6b3a764000090818102918183041490151715613335575b811561332d570490565b6131a0613176565b61333d6128ea565b613323565b9091600282018054918201809211613358575555565b6133606128ea565b5555565b61336f612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb5761339e916133dd565b60005260026020526133b36040600020615bb6565b6133b957565b604051633975ab9360e01b8152600490fd5b604051636830d4d760e01b8152600490fd5b906133e9600a54614b96565b906134038160026133fa8682612938565b018451906134ee565b61341081835160046134ee565b613423612f98612f9260408501516131c1565b9182613459575b516040516001600160a01b0390941693600080516020615e228339815191529350918291612b34919083612652565b61347b6004602061300661078b600080516020615f6283398151915254611971565b833b1561000e5760006134b6600080516020615e228339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156134e1575b6134cc575b5061342a565b8061281460006134db936104e8565b386134c6565b6134e961260f565b6134c1565b9091600482018054918201809211613358575555565b90613516613510612663565b8361298a565b600a54156136aa5760018060a01b03918281166000526020926002845260409260ff60078560002001541661369957906135518592846136bc565b8161356d61078b600080516020615f6283398151915254611971565b9185519687809463d8dfeb4560e01b82526004998a915afa92831561368c575b60009361366d575b5085516301c8232360e71b81529283918290816135b5308a8d8401612d07565b0392165afa918215613660575b600092613643575b505061363557612e546135de916002612938565b613628576136136135fc6135f3600a54613a9b565b611e9785612d5c565b51600080516020615f4283398151915254906137e3565b61361b575050565b5163677e872f60e11b8152fd5b516390898fd160e01b8152fd5b50516324a21d2960e01b8152fd5b6136599250803d106107355761072781836104e8565b38806135ca565b61366861260f565b6135c2565b613685919350823d841161085a5761084b81836104e8565b9138613595565b61369461260f565b61358d565b8351636830d4d760e01b8152600490fd5b60405163c25d67ab60e01b8152600490fd5b906136c8600a54614b96565b906136e28160026136d98682612938565b018451906137f3565b6136ef81835160046137f3565b613718613702612f9260408501516131c1565b600080516020615e82833981519152549061318d565b918261374e575b516040516001600160a01b0390941693600080516020615f228339815191529350918291612b34919083612652565b6137706004602061300661078b600080516020615f6283398151915254611971565b833b1561000e5760006137ab600080516020615f228339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156137d6575b6137c1575b5061371f565b8061281460006137d0936104e8565b386137bb565b6137de61260f565b6137b6565b6002916137ef916131a4565b1490565b9091600182018054918201809211613358575555565b90610a3891613819612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb57613848916138c4565b600052600260205261385d6040600020615bb6565b6133b957600080516020615ec283398151915254610a3857613890612e8b613886600a54613a9b565b611e976004612d5c565b6138a2670de0b6b3a7640000826131a4565b156138aa5750565b60405163d8b8b95160e01b81526004810191909152602490fd5b906138d0600a54614b96565b906138ea8160026138e18682612938565b018451906139d5565b6138f781835160046139d5565b61390a613702612f9260408501516131c1565b9182613940575b516040516001600160a01b0390941693600080516020615f828339815191529350918291612b34919083612652565b6139626004602061300661078b600080516020615f6283398151915254611971565b833b1561000e57600061399d600080516020615f828339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156139c8575b6139b3575b50613911565b8061281460006139c2936104e8565b386139ad565b6139d061260f565b6139a8565b9091600382018054918201809211613358575555565b600080516020615ec28339815191525461188457600790613a0d612d31612663565b613a6260018060a01b038216918260005260026020526020613a4f604060002094613a3786612d3c565b9060005260028352611e976002604060002001612d5c565b613a5a8151846138c4565b0151906133dd565b01805460ff19166001179055565b60405190613a7f6060836104e8565b8160008152613a8c6131d2565b60208201526040612d8f6131d2565b61055b90613aa76131d2565b506003615c0a565b60608101519091906001600160801b0316613aca81836131a4565b15613b1257670de0b6b3a764000090613ae382846131a4565b15613af55750505060200151600f0b90565b9083916020604061055b960151930151600f0b92600f0b90613b28565b9161055b9260408251920151600f0b91600f0b60005b90929391613b3682846131a4565b158015613bd8575b613bc65761055b94613b94613b8f83613b9a9686670de0b6b3a7640000976114629703928311613bb9575b8986039560008b128015828913169188121617613bac575b8103908111613b9f57613308565b61313b565b906130db565b612cc9565b613ba76128ea565b613308565b613bb46128ea565b613b81565b613bc16128ea565b613b69565b604051630db0f7cb60e01b8152600490fd5b506002613be582856131a4565b14613b3e565b8181039291600013801582851316918412161761290e57565b8115613c2c575b600160ff1b8114600019831416613c20570590565b613c286128ea565b0590565b613c34613176565b613c0b565b61146261055b92670de0b6b3a7640000926130db565b90611462670de0b6b3a764000061055b936130db565b9080613c825750613c7c57670de0b6b3a764000090565b60001990565b61055b91613308565b9081602091031261000e575190565b600080516020615e0283398151915254600080516020615f628339815191525460405163e975c0c360e01b815290602090829060049082906001600160a01b03165afa908115613d17575b600091613cf9575b50808210613303575090565b613d11915060203d81116108965761088781836104e8565b38613ced565b613d1f61260f565b613ce5565b6001600160a01b03909116815260200190565b7f482763b305ee10cd21c16c0cbeed259f2e4fcacdc9767cef16dc1fbe483d34886020613d62612663565b83600080516020615ec2833981519152555192604051938452151592a2565b600a54610a38916001600160a01b0316614c17565b95949295939093303b151580613de7575b6117b857610a3896613dd3613ddd94613dce613de298613dc9613dd896613f43565b613fe1565b61409a565b6142bc565b6143ea565b614518565b6145a6565b50600080516020615de28339815191525415613da7565b60405190613e0d6080836104e8565b60006060838281528260208201528260408201520152565b613e2d613dfe565b50613e36613dfe565b50604051613e456080826104e8565b600080516020615f028339815191525480600f0b825260801d600f0b6020820152600080516020615ee28339815191525480600f0b604083015260801c606082015290565b60405190613e9960c0836104e8565b8160a06000918281528260208201528260408201528260608201528260808201520152565b613ec6613e8a565b50613ecf613e8a565b50604051613ede60c0826104e8565b600080516020615d628339815191525460ff808216151583526001600160401b03600883901c81166020850152604883901c821615156040850152605083901c81166060850152609083901c9091161515608084015260989190911c1660a082015290565b7f18eb97ecd7366a8be310b7e675d67335c7604d5f47446a54a222473625a27e229080600080516020615d4283398151915255613f7e6147b4565b9061280060405192839283612652565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015613fd4575b613fc3575b50613f43565b6000613fce916104e8565b38613fbd565b613fdc61260f565b613fb8565b6002613ff5670de0b6b3a7640000836131a4565b1461403557807fb2743902575ffdab882dfa43a3501f82fbbefa0d2c637e393aed1e80e2cb840b91600080516020615e0283398151915255613f7e6147b4565b604051632012d38160e11b8152600490fd5b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af1801561408d575b61407c575b50613fe1565b6000614087916104e8565b38614076565b61409561260f565b614071565b60026140ae670de0b6b3a7640000836131a4565b1461403557807f6bf5f38f4e94f47ae7a4d6e56dbf388c856f890b5f0f2808b66914710b0266ca91600080516020615e8283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156141e1575b6141d0575b50614121614833565b6141c7576002614139670de0b6b3a7640000836131a4565b1461403557614146613ebe565b6001600160401b038083116141ae579161419e612800927f5dcd1837ba774ef7f1f06e50ad3f64097201da74055346f26a4c7dea9af9084e948316602082015260018152600080516020615d628339815191526141ee565b6040519081529081906020820190565b60405163477e89e360e01b815260048101849052602490fd5b610a389061409a565b60006141db916104e8565b38614118565b6141e961260f565b614113565b81518154602084015160408501516060860151600160501b600160901b0360509190911b166001600160901b031990931693151560ff1693909317610100600160481b0360089290921b919091161760ff60481b92151560481b9290921691909117178155610a38916142969060a09061428861426e6080830151151590565b855460ff60901b191690151560901b60ff60901b16178555565b01516001600160401b031690565b8154600160981b600160d81b03191660989190911b600160981b600160d81b0316179055565b60026142d0670de0b6b3a7640000836131a4565b1461403557807f8e37539629486a88c6a6083eb90030fb61cb856d56d96f53a326fda0d399ef3291600080516020615ea283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156143dd575b6143cc575b50614343614833565b6143c357600261435b670de0b6b3a7640000836131a4565b1461403557614368613ebe565b6001600160401b038083116141ae579161419e612800927f4024ee9b51b90807c93e46f7e500580ef5b0b8491e1105188a44f62eed26b129948316606082015260016040820152600080516020615d628339815191526141ee565b610a38906142bc565b60006143d7916104e8565b3861433a565b6143e561260f565b614335565b60026143fe670de0b6b3a7640000836131a4565b1461403557807fd07cf37924efa8fca893c372ddfb1614e6fd8c02cfcc9205262535680b77b93491600080516020615e6283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af1801561450b575b6144fa575b50614471614833565b6144f1576002614489670de0b6b3a7640000836131a4565b1461403557614496613ebe565b6001600160401b038083116141ae579161419e612800927f75d77d82706bf877275b9bc542ae4f30aca347d73558e05b56b35a1452f8613294831660a082015260016080820152600080516020615d628339815191526141ee565b610a38906143ea565b6000614505916104e8565b38614468565b61451361260f565b614463565b7fec4e0c10e4e0d362960c0114996546aa9c4d6cc297b00a7577e127b720791beb9080600080516020615f4283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015614599575b614588575b50614518565b6000614593916104e8565b38614582565b6145a161260f565b61457d565b60a07fb08b24c7f4e8b392d39bbaf1f4aa9bbb733ba9a467559eb8d9e2ffb634658e9091805161463860018060801b031991600080516020615f0283398151915261460a8482541660018060801b03938416178083556020870151600f0b90614657565b90556040840151600080516020615ee283398151915293845416908216179081845560608501511690614657565b90556146426147b4565b61464f6040518093611de9565b6080820152a1565b6001600160801b031660809190911b6001600160801b0319161790565b303b1561000e57604051630476982d60e21b8152610a3891613de29160008160048183305af180156146bf575b6146ae575b503690612402565b60006146b9916104e8565b386146a6565b6146c761260f565b6146a1565b6146d4613ebe565b80511590811580926147a7575b801561479a575b156128e657610a389161477e575b6040810151614762575b6080810151614746575b6147328160a06000918281528260208201528260408201528260608201528260808201520152565b600080516020615d628339815191526141ee565b60a081015161475d906001600160401b03166143ea565b61470a565b6060810151614779906001600160401b03166142bc565b614700565b6020810151614795906001600160401b031661409a565b6146f6565b50608081015115156146e8565b50604081015115156146e1565b303b156131b55760405163301fd1f560e21b8152602081600481305afa9081156147fc575b6000916147e4575090565b61055b915060203d81116108965761088781836104e8565b61480461260f565b6147d9565b919082604091031261000e576040516148236040826104e8565b6020808294805184520151910152565b6040516359ea287d60e01b815260a081600481305afa80156148c9575b600090614862575b61055b91506148d6565b60a03d81116148c2575b61487681846104e8565b82019060a08383031261075b5750906148b861055b9260606040519361489c82866104e8565b805185526148ad8360208301614809565b602086015201614809565b6040820152614858565b503d61486c565b6148d161260f565b614850565b6148e360208201516148f7565b90816148ed575090565b61055b9150604001515b8051159081614904575090565b6020915001511590565b61491661261c565b5061491f61261c565b5060405161492e6060826104e8565b600080516020615dc28339815191525460ff811661494b8161040f565b825260ff8160081c1661495d8161040f565b602083015261ffff1916604082015290565b303b151580614a33575b6117b857614992906000906001600160a01b0316614c17565b6149a461499f3683614a54565b614aa7565b15614a21576149b4903690614a54565b8051906149c08261040f565b6149c98261040f565b600080516020615dc28339815191529160ff83549116908160ff198216178455604061ff0060208501516149fc8161040f565b614a058161040f565b60081b1693848461ffff19809516171786550151169117179055565b604051639a51fe8f60e01b8152600490fd5b50600080516020615de28339815191525415614979565b6002111561000e57565b919082606091031261000e57604051614a6e6060826104e8565b604081938035614a7d81614a4a565b83526020810135614a8d81614a4a565b602084015201359061ffff198216820361000e5760400152565b60018151614ab48161040f565b614abd8261040f565b614ac68161040f565b14614ad8576040015161ffff19161590565b6001600160a01b0390614aea90614af1565b163b151590565b60018151614afe8161040f565b614b078261040f565b614b108161040f565b03614b28576040015160101c6001600160a01b031690565b8051604491614b368261040f565b604061ffff1991015116604051916327ada38760e11b8352614b578161040f565b60048301526024820152fd5b9081606091031261000e576040805191614b7e6060846104e8565b80518352602081015160208401520151604082015290565b61055b90614ba261261c565b50600080516020615da283398151915254604051637ece075d60e01b81526004810192909252606090829060249082906001600160a01b03165afa908115614c0a575b600091614bf25750614cd1565b611dcf915060603d8111611dd557611dc781836104e8565b614c1261260f565b614be5565b90813b15614c6a57816040917f41dd56c92c84169d8e89dc293d2649a911f47b357d3012bc88662395e01979d093600080516020615da28339815191525582519160018060a01b031682526020820152a1565b60405163d26af10d60e01b8152600490fd5b614c8461261c565b50600080516020615da28339815191525460405160016209351760e01b0319815261055b91606090829060049082906000906001600160a01b03165af1908115614c0a57600091614bf257505b614cd961261c565b50614ce261490e565b614cf26040830191825190614d1a565b905290565b6040810193929160209190614d0b8161040f565b8152614d168361040f565b0152565b8051614d258161040f565b6020820192835192614d368461040f565b614d40600061040f565b614d498361040f565b82614dd95750925b8051614d5c8161040f565b614d66600061040f565b614d6f8161040f565b614d795750505090565b60019051614d868161040f565b614d8f8261040f565b614d988161040f565b03614dbd57505061055b90614db7670de0b6b3a76400006000196130db565b90613c39565b610830604051928392631fafe5ed60e21b845260048401614cf7565b614de3600161040f565b614dec8361040f565b60018303614e045790614dfe91614e22565b92614d51565b5050610830604051928392631fafe5ed60e21b845260048401614cf7565b6001600160a01b0390614e3490614af1565b16604051906020928383019063d7c7a93560e01b8252602484015260248352614e5e6044846104e8565b614e686025614f59565b92614e7660405194856104e8565b602584527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668585015264185a5b195960da1b6040850152823b15614f08576000614ef39361055b969593829351915afa3d15614f00573d90614ed782614f59565b91614ee560405193846104e8565b82523d60008684013e614f83565b8051810182019101613c8b565b606090614f83565b60405162461bcd60e51b8152600481018690526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e746044820152631c9858dd60e21b6064820152608490fd5b6020906001600160401b038111614f76575b601f01601f19160190565b614f7e6104d1565b614f6b565b90919015614f8f575090565b815115614f9f5750805190602001fd5b60405162461bcd60e51b815290819061083090600483016105d1565b9392919061509190614fcb6131d2565b5061146261504e614fe8614fdf87856150c5565b938954906150c5565b94614ff16131d2565b50602080855195885196600088820398128189128116918913901516176150b8575b015196015195600087820397128188128116918813901516176150ab575b604051936150406040866104e8565b845260208401958652612d3c565b936150576131d2565b50615089602061508161506a885161313b565b95611462670de0b6b3a764000097889251906130db565b96015161313b565b9051906130db565b604051916150a06040846104e8565b825260208201529255565b6150b36128ea565b615031565b6150c06128ea565b615013565b6001916150d06131d2565b506000520160205261055b6040600020604051906150ef6040836104e8565b5480600f0b825260801d600f0b60208201526151096131d2565b5060208151910151604051916151206040846104e8565b600f0b8252600f0b602082015290565b6002916150d06131d2565b815181546001600160801b0319166001600160801b0390911617808255602090920151909161516d91600f0b90614657565b9055565b92949391948080516151839088615c0a565b9284828561518f6131d2565b50615199936153f3565b91906151a686838761561a565b6151af9161538f565b976001016151bc90612d5c565b906151c79185615731565b97906151d29161538f565b968101809111926152456152739361526c61524f61524a61524a9661528b99615300575b9c6151ff6131d2565b966020808d01519181880151808403938085116152f3575b82516152b657505060005b8a52019081511560001461529057505060005b602088015261524585518d6150c5565b61538f565b61530d565b615267895160018c0190600052602052604060002090565b61513b565b5187615130565b61526783516002860190600052602052604060002090565b519055565b6152b1916152a9670de0b6b3a7640000613b8f93613163565b905190613308565b615235565b6152e191613b8f91670de0b6b3a7640000918288029288840414911417156152e6575b835190613308565b615222565b6152ee6128ea565b6152d9565b6152fb6128ea565b615217565b6153086128ea565b6151f6565b6153156131d2565b5061532d6020615325835161533c565b92015161533c565b604051916151206040846104e8565b60016001607f1b0381136153775760016001607f1b0319811261535f57600f0b90565b60249060405190634e02165d60e01b82526004820152fd5b60249060405190632cd75ba360e11b82526004820152fd5b906153986131d2565b50602080835193835194600086820196871291129080158216911516176153e6575b01519101519060008282019283129112908015821691151617613258576040519161324e6040846104e8565b6153ee6128ea565b6153ba565b9391939290926154016131d2565b9460409182519363597e1fb560e01b85526020948581600481305afa9081156155f3575b6000916155d6575b506155c357848701908151156155a2578751156155a25785015185840151615454916132b8565b928482516154619061313b565b91015161546d91613c39565b615476906131c1565b61547f886132c5565b6154889161318d565b935163307648eb60e11b815290858083806154a68c60048301611cff565b0381305afa938415996154f861556098614db76154f2614db7996155279f99615542986155579b615595575b600092615578575b5050614db7613b8f670de0b6b3a7640000809e613163565b9161313b565b90615548600061552d8a61551561550e876131c1565b9788613163565b049e8f61552187615600565b976132b8565b8661310c565b941291821561556e5761554284915b5161313b565b90613c4f565b8d52156155665750915161313b565b916000196130db565b90840152565b90509161553c565b615542859161553c565b61558e9250803d106108965761088781836104e8565b388e6154da565b61559d61260f565b6154d2565b5050505060009294506155b69193506123e6565b9181835282015290600090565b50505060009294506155b69193506123e6565b6155ed9150863d88116107355761072781836104e8565b3861542d565b6155fb61260f565b615425565b6000811361561457600013613c7c57600090565b50600190565b9291926156256131d2565b9360409283519363597e1fb560e01b85526020948581600481305afa908115615724575b600091615707575b506156f457848401928351156156d6578451156156d6576156b46156ae6156a761569b61569161554297876156d09b9a986156c898015191015190613beb565b614db7875161313b565b614db7613b8f896132c5565b955161313b565b85613c4f565b614db7670de0b6b3a76400006000196130db565b87525161313b565b90830152565b509150506000929394506156ea91506123e6565b9181835282015290565b9150506000929394506156ea91506123e6565b61571e9150863d88116107355761072781836104e8565b38615651565b61572c61260f565b615649565b9192909261573d6131d2565b93615747816148d6565b615828579061575591615881565b60405190630dbc9ce160e01b825261579b61579561578e6020948581600481305afa90811561581b575b6000916157fe575b5084615830565b8093613272565b9161586e565b8451909490156157e85782906157b9613b8f83850151835190613308565b87525b018051909190156157d85761556091613b8f9151905190613308565b905061055b929391505190612901565b936157f883918284015190612901565b946157bc565b6158159150863d88116108965761088781836104e8565b38615787565b61582361260f565b61577f565b506000925050565b906158396131d2565b5061585e670de0b6b3a764000091602083615855838751613163565b04940151613163565b046040519161324e6040846104e8565b6020815191015181018091116129305790565b6158896131d2565b506158d46158c76158a560209360408582015191015190613214565b936158cc846150816158c760406158bc8a5161313b565b950194855190613c39565b6131c1565b905190613c39565b604051633f1d071f60e21b815290928282600481305afa9182156159a7575b600092615984575b5061594390615914670de0b6b3a7640000938492613163565b6040516343f0179b60e01b8152919004948482600481305afa918215615977575b600092615958575b50613163565b049061594f60406123e6565b92835282015290565b615970919250853d87116108965761088781836104e8565b903861593d565b61597f61260f565b615935565b6159439192506159a090843d86116108965761088781836104e8565b91906158fb565b6159af61260f565b6158f3565b6004906000926159d8575b8281558260018201558260028201558260038201550155565b6159e0610480565b6159bf565b6020615a086159f383612d3c565b936002840194615a0286612d5c565b90615a34565b815184559101516001830155615a1c575050565b615a2960006007936159b4565b01805460ff19169055565b91615a3d6131d2565b5081518015159182615a67575b505015615a6057615a5a916131ed565b90600190565b5090600090565b511190503880615a4a565b6131a0615ac06158c7670de0b6b3a764000093615abb613b8f60408051634ec4474360e11b8152606081600481305afa908115615b30575b600091615b12575b50015192615b3d565b613c39565b604051636c376cc560e01b815290602082600481305afa918215615b05575b600092615aec5750613163565b61597091925060203d81116108965761088781836104e8565b615b0d61260f565b615adf565b615b2a915060603d8111611dd557611dc781836104e8565b38615ab2565b615b3861260f565b615aaa565b8051602090910151808210613303575090565b80541580615baa575b80615b9e575b6001820154159182615b91575b82615b84575b50159081615b7e575090565b90501590565b6006015415915038615b72565b6004810154159250615b6c565b50600581015415615b5f565b50600381015415615b59565b615bd4615bc282612d3c565b615bce60038401612d3c565b90613214565b6002615be660058401548351906131a4565b14918215615bf357505090565b60060154602090910151600292506137ef916131a4565b90615c136131d2565b50600052602052604060002060405190615c2e6040836104e8565b546001600160801b03808216835260809190911c60208301908152918190615c546131d2565b5051169151166040519161324e6040846104e8565b90615c749082615c0a565b91615d01615c8a826001850195615a0287612d5c565b9390615c946131d2565b50615cac6020615ca48351615d15565b920151615d15565b9160405194615cbc6040876104e8565b6001600160801b0392831686529282166020808701918252935160009081529190935260409020935184546001600160801b0319169082161780855591511690614657565b9055615d0a5750565b6000610a38916159b4565b6001600160801b0390818111615d29571690565b60249060405190635385129160e01b82526004820152fdfe968cf792ff9a89745e4746179e93a7b9d7f08b0ff8366fd6f6dbd524ef107464d729c7f2aea8904a802db9fc1939086967cdf7fffe1510c25ccafabfc894614eb9726781b72c53f23217f424d70445b222951f008aeac7eece8139caed71ed2d6c0d5e3cd81753b1b21f67f61d56a97aae7a3e0179486d114788ad4576f53266630ac9ad193fa8d8f5a7207eefdee35934d664003a3d4c286a591e065a62034ead57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398cace7e947336f94057b47a9ab5531b0363e85c8d36c05c7d915ec8e525fd159d863625b85818a29587ee919ee6a968ee0b32f3513f2884b3968001062ba49eb6b1b30fe15febd596dffd21d4da0657732eea42b4b5a9789e3e6daab3d570999d7850062f2c27d17cdf727c8059e0b505bd3a788af62482a56bcede987d8eea5a35a294f9055e9dc7a18078b4e0139086766d723c3cd728bd59cc1f3b589741ed21d7cfd39841edd73967db6350efae442ebd8c6e1bfca55faa52b046d39b7e493bdea2cc426745068386b3804e5b401ae87ffbae9dbf293944b5307f507040c79917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f7917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f6f98b31465ac12e92b5cb136ade913276c267463c4395bb1a3999bc88fb837806897858f7b7d3c8b4e7a700b401ad192a110353a60c809946583c0d62cda7f0b70e555410d8128dff796eab5d29b97dd593ce9cab44a71b64c08244579ea6053339854479080fac0b5e7c0ecedb0fb02308a72a43cd102c6b9f918653d3400367a26469706673582212204b69baaeef80c3d10bcbfa071e5b42837bde2a623a6bd381b09c0321848898fe64736f6c63430008110033", + "deployedBytecode": "0x60806040526004361015610013575b600080fd5b60003560e01c806305d5c1cb146103fb57806306fdde03146103f25780630dbc9ce1146103e957806311da60b4146103e0578063153261e5146103d757806319377567146103ce5780631cb44dfc146103c55780631e0c6fb9146103bc57806320fe9c3c146103b3578063212e0ad3146103aa5780632131ea4a146103a15780632d2e52be146103985780633a25c1111461038f5780633e17b8c71461038657806343f0179b1461037d578063476fa96d1461037457806354fb39211461036b57806356bc1ad41461036257806358ca6f981461035957806359218fe914610350578063597e1fb51461034757806359ea287d1461033e5780635d16e1201461033557806360ec91d61461032c578063611c71b4146103235780636943b0171461031a5780636c376cc5146103115780636ecffff91461030857806373b88f3b146102ff57806376f37001146102f65780637dc0d1d0146102ed5780637ece075d146102e45780638c94b48f146102db5780638e480b20146102d257806391689024146102c95780639378bf7b146102c057806395d89b41146102b75780639a427d03146102ae5780639d888e86146102a5578063a12e1b331461029c578063ab582f2914610293578063b7648fb91461028a578063c07f47d414610281578063d7d7d6b814610278578063e1c3c98d1461026f578063e503b00714610266578063f667f8971461025d578063f6b3200814610254578063f77c47911461024b5763fc741c7c1461024357600080fd5b61000e6123b0565b5061000e612379565b5061000e6122c2565b5061000e612201565b5061000e6120cc565b5061000e611fc5565b5061000e611f01565b5061000e611ee2565b5061000e611e9d565b5061000e611e47565b5061000e611e1e565b5061000e611d45565b5061000e611d0f565b5061000e611cde565b5061000e611b95565b5061000e611b50565b5061000e611b12565b5061000e611a0b565b5061000e6119dd565b5061000e61197d565b5061000e6118c1565b5061000e6117eb565b5061000e611646565b5061000e61161a565b5061000e611576565b5061000e61146f565b5061000e61140d565b5061000e6113e1565b5061000e6113b9565b5061000e61138b565b5061000e6112db565b5061000e611295565b5061000e61118e565b5061000e611087565b5061000e61105c565b5061000e611030565b5061000e610f29565b5061000e610ebf565b5061000e610d66565b5061000e610bf4565b5061000e610ae2565b5061000e610a90565b5061000e610a3a565b5061000e6108e7565b5061000e6108aa565b5061000e61075e565b5061000e610676565b5061000e61064a565b5061000e61061a565b5061000e61042f565b600091031261000e57565b6002111561041957565b634e487b7160e01b600052602160045260246000fd5b503461000e57600036600319011261000e57606061044b61490e565b60405190805161045a8161040f565b8252602081015161046a8161040f565b6020830152604061ffff19910151166040820152f35b50634e487b7160e01b600052600060045260246000fd5b90600182811c921680156104c7575b60208310146104b157565b634e487b7160e01b600052602260045260246000fd5b91607f16916104a6565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101761050b57604052565b6105136104d1565b604052565b906105c4575b6040519081600082549261053184610497565b9081845260019485811690816000146105a1575060011461055e575b505061055b925003826104e8565b90565b9093915060005260209081600020936000915b81831061058957505061055b9350820101388061054d565b85548784018501529485019486945091830191610571565b91505061055b94506020925060ff191682840152151560051b820101388061054d565b6105cc610480565b61051e565b6020808252825181830181905290939260005b82811061060657505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016105e4565b503461000e57600036600319011261000e5761064661063a600080610518565b604051918291826105d1565b0390f35b503461000e57600036600319011261000e576020600080516020615e6283398151915254604051908152f35b503461000e5760008060031936011261075b57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561073c575b839161070e575b506106fc576001906106f7612663565b505580f35b604051633b3b4caf60e21b8152600490fd5b61072f915060203d8111610735575b61072781836104e8565b8101906125fa565b386106e7565b503d61071d565b61074461260f565b6106e0565b604051637990191b60e11b8152600490fd5b80fd5b503461000e57608036600319011261000e5761079061078b600080516020615f6283398151915254611971565b611971565b604051633e92a73360e11b8152906020908183806107b13060048301613d24565b0381845afa92831561089d575b60009361086e575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610861575b600092610834575b5050336001600160a01b0390911603610816576108146004614674565b005b60405163123d8bcf60e21b81526004810191909152602490fd5b0390fd5b6108539250803d1061085a575b61084b81836104e8565b81019061263d565b38806107f7565b503d610841565b61086961260f565b6107ef565b61088f919350823d8411610896575b61088781836104e8565b810190613c8b565b91386107c6565b503d61087d565b6108a561260f565b6107be565b503461000e57600036600319011261000e576020600080516020615f4283398151915254604051908152f35b6001600160a01b0381160361000e57565b503461000e5760208060031936011261000e5760043590610907826108d6565b61092261078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806109413060048301613d24565b0381845afa9283156109ec575b6000936109cd575b50604051635091e19f60e11b815260048101849052908290829060249082905afa9182156109c0575b6000926109a3575b5050336001600160a01b03909116036108165761081482613d81565b6109b99250803d1061085a5761084b81836104e8565b3880610987565b6109c861260f565b61097f565b6109e5919350823d84116108965761088781836104e8565b9138610956565b6109f461260f565b61094e565b60208091805184520151910152565b610a38909291926060604060a083019580518452610a2e602082015160208601906109f9565b01519101906109f9565b565b503461000e57602036600319011261000e57600435610a58816108d6565b610a60613a70565b5060018060a01b03166000526002602052610646610a846002604060002001612d5c565b60405191829182610a08565b503461000e57602036600319011261000e57610aaa6131d2565b50610646610abb600435600a6150c5565b604051918291829190916020806040830194805184520151910152565b8015150361000e57565b503461000e5760208060031936011261000e5760043590610b0282610ad8565b610b1d61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380610b3c3060048301613d24565b0381845afa928315610be7575b600093610bc8575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610bbb575b600092610b9e575b5050336001600160a01b03909116036108165761081482613d37565b610bb49250803d1061085a5761084b81836104e8565b3880610b82565b610bc361260f565b610b7a565b610be0919350823d84116108965761088781836104e8565b9138610b51565b610bef61260f565b610b49565b503461000e5760408060031936011261000e576004803590610c15826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610d4c575b600091610d2f575b50610d1f57808616331491858315610cc0575b505050905015610ca357600184610ca060243586613364565b55005b51636dc3a3c360e01b815290819061083090339085908401612d07565b9193819350855192838092630479e58f60e41b82525afa918215610d12575b600092610cf5575b505016331480388085610c87565b610d0b9250803d1061085a5761084b81836104e8565b3880610ce7565b610d1a61260f565b610cdf565b50505051633b3b4caf60e21b8152fd5b610d469150833d85116107355761072781836104e8565b38610c74565b610d5461260f565b610c6c565b51637990191b60e11b8152fd5b503461000e5760408060031936011261000e576004803590610d87826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115610eb2575b600091610e95575b50610d1f57600080516020615ec283398151915254610e8557808616331491858315610e26575b505050905015610ca357600184610ca060243586613504565b9193819350855192838092630479e58f60e41b82525afa918215610e78575b600092610e5b575b505016331480388085610e0d565b610e719250803d1061085a5761084b81836104e8565b3880610e4d565b610e8061260f565b610e45565b5050505163ded15dbf60e01b8152fd5b610eac9150833d85116107355761072781836104e8565b38610de6565b610eba61260f565b610dde565b503461000e57600036600319011261000e5760c0610edb613ebe565b6040519080511515825260a060018060401b039182602082015116602085015260408101511515604085015282606082015116606085015260808101511515608085015201511660a0820152f35b503461000e5760208060031936011261000e57610f5761078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380610f763060048301613d24565b0381845afa928315611023575b600093611004575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215610ff7575b600092610fda575b5050336001600160a01b0390911603610816576108146004356140ee565b610ff09250803d1061085a5761084b81836104e8565b3880610fbc565b610fff61260f565b610fb4565b61101c919350823d84116108965761088781836104e8565b9138610f8b565b61102b61260f565b610f83565b503461000e57600036600319011261000e576020600080516020615ea283398151915254604051908152f35b503461000e57602036600319011261000e576110766131d2565b50610646610abb600435600a615130565b503461000e5760208060031936011261000e576110b561078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806110d43060048301613d24565b0381845afa928315611181575b600093611162575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611155575b600092611138575b5050336001600160a01b03909116036108165761081460043561443e565b61114e9250803d1061085a5761084b81836104e8565b388061111a565b61115d61260f565b611112565b61117a919350823d84116108965761088781836104e8565b91386110e9565b61118961260f565b6110e1565b503461000e5760208060031936011261000e576111bc61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806111db3060048301613d24565b0381845afa928315611288575b600093611269575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561125c575b60009261123f575b5050336001600160a01b039091160361081657610814600435613f8e565b6112559250803d1061085a5761084b81836104e8565b3880611221565b61126461260f565b611219565b611281919350823d84116108965761088781836104e8565b91386111f0565b61129061260f565b6111e8565b503461000e57602036600319011261000e576004356112b3816108d6565b60018060a01b03166000526002602052602060ff600760406000200154166040519015158152f35b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa90811561137e575b600091611360575b506106fc57600190610ca060043533613809565b611378915060203d81116107355761072781836104e8565b3861134c565b61138661260f565b611344565b503461000e57600036600319011261000e576020600080516020615ec2833981519152546040519015158152f35b503461000e57600036600319011261000e576113d3613a70565b50610646610a846004612d5c565b503461000e57600036600319011261000e576020600080516020615e0283398151915254604051908152f35b503461000e57604036600319011261000e576020611467611442611435600435602435613c65565b61143d613e25565b613aaf565b611462670de0b6b3a764000061145c816301e133806130db565b926130db565b613c04565b604051908152f35b503461000e5760208060031936011261000e5761149d61078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806114bc3060048301613d24565b0381845afa928315611569575b60009361154a575b50604051635091e19f60e11b815260048101849052908290829060249082905afa91821561153d575b600092611520575b5050336001600160a01b039091160361081657610814600435614310565b6115369250803d1061085a5761084b81836104e8565b3880611502565b61154561260f565b6114fa565b611562919350823d84116108965761088781836104e8565b91386114d1565b61157161260f565b6114c9565b503461000e57602036600319011261000e57600435611594816108d6565b60018060a01b0316600052600260205261064660406000206115ef604051916115be6060846104e8565b6115c781612d3c565b835260ff60076115d960028401612d5c565b92836020870152015416151560408401526148d6565b9081611609575b5060405190151581529081906020820190565b6116149150516148f7565b386115f6565b503461000e57600036600319011261000e576020600080516020615d4283398151915254604051908152f35b503461000e5760031960203682011261000e57600435906001600160401b03821161000e576102008260040191833603011261000e5760017f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b81815410156117d257819055600080516020615de283398151915292818455303b1515806117ca575b6117b857333b156117a6577fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f32936117906117896117a195602460009533600080516020615f628339815191525561172e61172460a483016123dc565b604483019061496f565b6117366125c1565b61176e611747366101848401612402565b61016483013561014484013561012485013561010486013560e487013560c4880135613d96565b61178261177b8480612466565b90896124ec565b0190612466565b90856124ec565b556040519081529081906020820190565b0390a1005b6040516314878b6960e01b8152600490fd5b604051631a27c4a960e21b8152600490fd5b5060006116c8565b604051631e7a9d9560e01b815260048101839052602490fd5b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156118b4575b600091611896575b506106fc57600080516020615ec28339815191525461188457600190610ca060043533612d21565b60405163ded15dbf60e01b8152600490fd5b6118ae915060203d81116107355761072781836104e8565b3861185c565b6118bc61260f565b611854565b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611964575b600091611946575b506106fc57600190610ca060043533613364565b61195e915060203d81116107355761072781836104e8565b38611932565b61196c61260f565b61192a565b6001600160a01b031690565b503461000e57600036600319011261000e57600080516020615da2833981519152546040516001600160a01b039091168152602090f35b6040809180518452602081015160208501520151910152565b606081019291610a3891906119b4565b503461000e57602036600319011261000e5760606119fc600435614b96565b611a0960405180926119b4565bf35b503461000e5760208060031936011261000e57611a3961078b600080516020615f6283398151915254611971565b604051633e92a73360e11b81529190818380611a583060048301613d24565b0381845afa928315611b05575b600093611ae6575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215611ad9575b600092611abc575b5050336001600160a01b039091160361081657610814600435614553565b611ad29250803d1061085a5761084b81836104e8565b3880611a9e565b611ae161260f565b611a96565b611afe919350823d84116108965761088781836104e8565b9138611a6d565b611b0d61260f565b611a65565b503461000e57602036600319011261000e57600435611b30816108d6565b60018060a01b031660005260096020526020604060002054604051908152f35b503461000e57602036600319011261000e57600435611b6e816108d6565b60018060a01b031660005260026020526020611467611b906040600020612d3c565b615a72565b503461000e5760408060031936011261000e576004803590611bb6826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa908115611cd1575b600091611cb4575b50610d1f57600080516020615ec283398151915254610e8557808616331491858315611c55575b505050905015610ca357600184610ca060243586612d21565b9193819350855192838092630479e58f60e41b82525afa918215611ca7575b600092611c8a575b505016331480388085611c3c565b611ca09250803d1061085a5761084b81836104e8565b3880611c7c565b611caf61260f565b611c74565b611ccb9150833d85116107355761072781836104e8565b38611c15565b611cd961260f565b611c0d565b503461000e57600036600319011261000e5761064661063a60006001610518565b604081019291610a3891906109f9565b503461000e57602036600319011261000e57611d296131d2565b506040611d396004356003615c0a565b611a09825180926109f9565b503461000e57600036600319011261000e57611d5f61261c565b50600080516020615da283398151915254604051634ec4474360e11b81526060916119fc91908390829060049082906001600160a01b03165afa908115611ddc575b600091611daf575b50614cd1565b611dcf9150833d8111611dd5575b611dc781836104e8565b810190614b63565b38611da9565b503d611dbd565b611de461260f565b611da1565b6060908051600f0b83526020810151600f0b60208401526040810151600f0b60408401528160018060801b0391015116910152565b503461000e57600036600319011261000e576080611e3a613e25565b611a096040518092611de9565b503461000e57602036600319011261000e57600435611e65816108d6565b60018060a01b031660005260026020526020611467611b906040600020611e976002611e9083612d3c565b9201612d5c565b906131ed565b503461000e57602036600319011261000e57600435611ebb816108d6565b611ec36131d2565b5060018060a01b031660005260026020526040611d3981600020612d3c565b503461000e57600036600319011261000e576020600a54604051908152f35b503461000e57602036600319011261000e57600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa908115611fb8575b600091611f9a575b506106fc57600080516020615ec28339815191525461188457600190610ca060043533613504565b611fb2915060203d81116107355761072781836104e8565b38611f72565b611fc061260f565b611f6a565b503461000e5760208060031936011261000e57611ff361078b600080516020615f6283398151915254611971565b604051633e92a73360e11b815291908183806120123060048301613d24565b0381845afa9283156120bf575b6000936120a0575b50604051635091e19f60e11b815260048101849052908290829060249082905afa918215612093575b600092612076575b5050336001600160a01b039091160361081657610814600435614047565b61208c9250803d1061085a5761084b81836104e8565b3880612058565b61209b61260f565b612050565b6120b8919350823d84116108965761088781836104e8565b9138612027565b6120c761260f565b61201f565b503461000e5760408060031936011261000e5760048035906120ed826108d6565b600080516020615e42833981519152926002845414610d595760028455600080516020615f62833981519152548151635c975abb60e01b81526001600160a01b039182169160209182818781875afa9081156121f4575b6000916121d7575b50610d1f57808616331491858315612178575b505050905015610ca357600184610ca060243586613809565b9193819350855192838092630479e58f60e41b82525afa9182156121ca575b6000926121ad575b50501633148038808561215f565b6121c39250803d1061085a5761084b81836104e8565b388061219f565b6121d261260f565b612197565b6121ee9150833d85116107355761072781836104e8565b3861214c565b6121fc61260f565b612144565b503461000e57602036600319011261000e5760043561221f816108d6565b600080516020615e4283398151915260028154146107495760028155600080516020615f6283398151915254604051635c975abb60e01b815290602090829060049082906001600160a01b03165afa9081156122b5575b600091612297575b506106fc57610ca0600192612291612663565b9061298a565b6122af915060203d81116107355761072781836104e8565b3861227e565b6122bd61260f565b612276565b503461000e57602036600319011261000e576004356122e0816108d6565b600460206122ff61078b600080516020615f6283398151915254611971565b60405163d8dfeb4560e01b815292839182905afa90811561236c575b60009161234e575b506001600160a01b0316330361233c57610814906139eb565b6040516340cbe9b160e01b8152600490fd5b612366915060203d811161085a5761084b81836104e8565b38612323565b61237461260f565b61231b565b503461000e57600036600319011261000e57600080516020615f62833981519152546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600080516020615e8283398151915254604051908152f35b3561055b816108d6565b90610a3860405192836104e8565b359081600f0b820361000e57565b919082608091031261000e5760405161241c6080826104e8565b60608193612429816123f4565b8352612437602082016123f4565b6020840152612448604082016123f4565b60408401520135906001600160801b038216820361000e5760600152565b903590601e198136030182121561000e57018035906001600160401b03821161000e5760200191813603831361000e57565b90601f81116124a657505050565b600091825260208220906020601f850160051c830194106124e2575b601f0160051c01915b8281106124d757505050565b8181556001016124cb565b90925082906124c2565b9092916001600160401b0381116125b4575b6125128161250c8454610497565b84612498565b6000601f821160011461254c5781929394600092612541575b50508160011b916000199060031b1c1916179055565b01359050388061252b565b601f1982169461256184600052602060002090565b91805b87811061259c575083600195969710612582575b505050811b019055565b0135600019600384901b60f8161c19169055388080612578565b90926020600181928686013581550194019101612564565b6125bc6104d1565b6124fe565b303b1515806125e3575b6117b8576001600080516020615e4283398151915255565b50600080516020615de283398151915254156125cb565b9081602091031261000e575161055b81610ad8565b506040513d6000823e3d90fd5b6040519061262b6060836104e8565b60006040838281528260208201520152565b9081602091031261000e575161055b816108d6565b908152602081019190915260400190565b61266b61261c565b50612684600080516020615f6283398151915254611971565b9061268d614c7c565b91600a5490835182146128e6576126a382614b96565b906126b085516004612916565b855181036128d7575084915b604051631bf1901f60e21b81526001600160a01b03926020929084169184908481600481875afa9081156128ca575b6000916128ad575b501690813b1561000e5760405163a55ff01d60e01b81528992600090829081838161272189600483016119cd565b03925af180156128a0575b61288b575b506127558661274d81612742613c9a565b94600386600a615171565b986003615c69565b61275d6146cc565b8551825103612857575b5050816004916040519283809263d8dfeb4560e01b82525afa91821561284a575b60009261282d575b50501691823b1561000e57604051637f3dd53b60e01b815260048101919091527f88a84ea6dd274b386afd27dbbe11b6192b25017f5e60bb8c4053dfddb45c294d926000908290602490829084905af18015612820575b612805575b505183519061280060405192839283612652565b0390a1565b80612814600061281a936104e8565b80610404565b386127ec565b61282861260f565b6127e7565b6128439250803d1061085a5761084b81836104e8565b3880612790565b61285261260f565b612788565b6004929661286e859388600361287495600a615171565b90612901565b956128828987516003615c69565b91889150612767565b80612814600061289a936104e8565b38612731565b6128a861260f565b61272c565b6128c49150853d871161085a5761084b81836104e8565b386126f3565b6128d261260f565b6126eb565b6128e090614b96565b916126bc565b5050565b50634e487b7160e01b600052601160045260246000fd5b9190820180921161290e57565b610a386128ea565b5480612920575090565b9050600181018091116129305790565b61055b6128ea565b9060018060a01b0316600052602052604060002090565b6001600160a01b039091168152608081019291610a3891602001906119b4565b6001600160a01b039091168152602081019190915260400190565b6129a2600080516020615f6283398151915254611971565b6129ad826009612938565b54835114612cc4576129cd60026129c48482612938565b01845190612916565b83518103612cb5575082915b60018060a01b038092166040805194631bf1901f60e21b9283875260208660049882818b81875afa908115612ca8575b600091612c8b575b5016803b1561000e578792878a92600088518092818381612a408d63060c0d2760e21b998a84528c840161294f565b03925af18015612c7e575b612c69575b50612a7c612a77612a628b6009612938565b612a6d8c6002612938565b600a8a5192614fbb565b612ce5565b97612a9187612a8c8c6002612938565b6159e5565b86518d5103612b85575b5050829086519283809263d8dfeb4560e01b82525afa918215612b78575b600092612b5b575b505016803b1561000e576000612b3494612b139287837f9d7055d24918d8c2fd08660a27bf31d4086fa71a51cd07874276470223aa480f9b8851968795869485936364e5a46f60e11b8552840161296f565b03925af18015612b4e575b612b39575b505195519051938493169583612652565b0390a2565b806128146000612b48936104e8565b38612b23565b612b5661260f565b612b1e565b612b719250803d1061085a5761084b81836104e8565b3880612ac1565b612b8061260f565b612ab9565b909491979250865190815283818c818b5afa908115612c5c575b600091612c3f575b5016803b1561000e57612c158a92612c0f612a778b8f808f9a838b998f60008094612bde8f9351978896879586948552840161294f565b03925af18015612c32575b612c1d575b50600a612c07612bff846009612938565b936002612938565b915192614fbb565b90612cc9565b969038612a9b565b806128146000612c2c936104e8565b38612bee565b612c3a61260f565b612be9565b612c569150843d861161085a5761084b81836104e8565b38612ba7565b612c6461260f565b612b9f565b806128146000612c78936104e8565b38612a50565b612c8661260f565b612a4b565b612ca29150833d851161085a5761084b81836104e8565b38612a11565b612cb061260f565b612a09565b612cbe90614b96565b916129d9565b505050565b9190916000838201938412911290801582169115161761290e57565b6020815191015190600082820192831291129080158216911516176129305790565b6001600160a01b0391821681529116602082015260400190565b90610a3891612d37612d31612663565b8261298a565b612d94565b90604051612d4b6040826104e8565b602060018294805484520154910152565b90604051612d6b6060826104e8565b6040612d8f6003839580548552612d8460018201612d3c565b602086015201612d3c565b910152565b60018060a01b03908181166000526020916002835260409360ff600786600020015416612f3b5790612dc7849284612f4c565b81612de361078b600080516020615f6283398151915254611971565b9186519586809463d8dfeb4560e01b825260049889915afa928315612f2e575b600093612f0f575b5086516301c8232360e71b8152928391829081612e2b308a8c8401612d07565b0392165afa918215612f02575b600092612ee5575b5050612ed657612e54612e59916002612938565b615b50565b612ec857600080516020615ec2833981519152546128e657612e90612e8b612e82600a54613a9b565b611e9784612d5c565b6132c5565b91612ea3670de0b6b3a7640000846131a4565b15612ead57505050565b5163d8b8b95160e01b81529081019182529081906020010390fd5b90516390898fd160e01b8152fd5b5090516324a21d2960e01b8152fd5b612efb9250803d106107355761072781836104e8565b3880612e40565b612f0a61260f565b612e38565b612f27919350823d841161085a5761084b81836104e8565b9138612e0b565b612f3661260f565b612e03565b8451636830d4d760e01b8152600490fd5b90612f58600a54614b96565b90612f72816002612f698682612938565b01845190613342565b612f7f8183516004613342565b612fae612f98612f9260408501516131c1565b8361318d565b600080516020615ea2833981519152549061318d565b9182612fe4575b516040516001600160a01b0390941693600080516020615d828339815191529350918291612b34919083612652565b61303d6004602061300661078b600080516020615f6283398151915254611971565b60405163d8dfeb4560e01b815292839182905afa9081156130ce575b6000916130b0575b506001600160a01b03169360001961310c565b833b1561000e576000613078600080516020615d828339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156130a3575b61308e575b50612fb5565b80612814600061309d936104e8565b38613088565b6130ab61260f565b613083565b6130c8915060203d811161085a5761084b81836104e8565b3861302a565b6130d661260f565b613022565b818102929160008212600160ff1b8214166130ff575b818405149015171561290e57565b6131076128ea565b6130f1565b60008113613135576000136131215750600090565b61312d61055b9161313b565b6000196130db565b5061055b905b6001600160ff1b03811161314c5790565b6024906040519062a07eb560e01b82526004820152fd5b8181029291811591840414171561290e57565b50634e487b7160e01b600052601260045260246000fd5b670de0b6b3a7640000916131a091613163565b0490565b8181116131ba57106131b557600190565b600090565b5050600290565b60008082126131ce575090565b0390565b604051906131e16040836104e8565b60006020838281520152565b90604061320b61055b936131ff6131d2565b50602084015190613214565b91015190613272565b9061321d6131d2565b5060208083519383518501809511613265575b01519101518101809111613258575b6040519161324e6040846104e8565b8252602082015290565b6132606128ea565b61323f565b61326d6128ea565b613230565b9061327b6131d2565b50602080835193835185039485116132ab575b01519101518103908111613258576040519161324e6040846104e8565b6132b36128ea565b61328e565b9190820391821161290e57565b602081015160009190806132e257505050670de0b6b3a764000090565b6132ec9151613308565b670de0b6b3a7640000915080821015613303575090565b905090565b670de0b6b3a764000090818102918183041490151715613335575b811561332d570490565b6131a0613176565b61333d6128ea565b613323565b9091600282018054918201809211613358575555565b6133606128ea565b5555565b61336f612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb5761339e916133dd565b60005260026020526133b36040600020615bb6565b6133b957565b604051633975ab9360e01b8152600490fd5b604051636830d4d760e01b8152600490fd5b906133e9600a54614b96565b906134038160026133fa8682612938565b018451906134ee565b61341081835160046134ee565b613423612f98612f9260408501516131c1565b9182613459575b516040516001600160a01b0390941693600080516020615e228339815191529350918291612b34919083612652565b61347b6004602061300661078b600080516020615f6283398151915254611971565b833b1561000e5760006134b6600080516020615e228339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156134e1575b6134cc575b5061342a565b8061281460006134db936104e8565b386134c6565b6134e961260f565b6134c1565b9091600482018054918201809211613358575555565b90613516613510612663565b8361298a565b600a54156136aa5760018060a01b03918281166000526020926002845260409260ff60078560002001541661369957906135518592846136bc565b8161356d61078b600080516020615f6283398151915254611971565b9185519687809463d8dfeb4560e01b82526004998a915afa92831561368c575b60009361366d575b5085516301c8232360e71b81529283918290816135b5308a8d8401612d07565b0392165afa918215613660575b600092613643575b505061363557612e546135de916002612938565b613628576136136135fc6135f3600a54613a9b565b611e9785612d5c565b51600080516020615f4283398151915254906137e3565b61361b575050565b5163677e872f60e11b8152fd5b516390898fd160e01b8152fd5b50516324a21d2960e01b8152fd5b6136599250803d106107355761072781836104e8565b38806135ca565b61366861260f565b6135c2565b613685919350823d841161085a5761084b81836104e8565b9138613595565b61369461260f565b61358d565b8351636830d4d760e01b8152600490fd5b60405163c25d67ab60e01b8152600490fd5b906136c8600a54614b96565b906136e28160026136d98682612938565b018451906137f3565b6136ef81835160046137f3565b613718613702612f9260408501516131c1565b600080516020615e82833981519152549061318d565b918261374e575b516040516001600160a01b0390941693600080516020615f228339815191529350918291612b34919083612652565b6137706004602061300661078b600080516020615f6283398151915254611971565b833b1561000e5760006137ab600080516020615f228339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156137d6575b6137c1575b5061371f565b8061281460006137d0936104e8565b386137bb565b6137de61260f565b6137b6565b6002916137ef916131a4565b1490565b9091600182018054918201809211613358575555565b90610a3891613819612d31612663565b6001600160a01b03811660008181526002602052604090206007015490929060ff166133cb57613848916138c4565b600052600260205261385d6040600020615bb6565b6133b957600080516020615ec283398151915254610a3857613890612e8b613886600a54613a9b565b611e976004612d5c565b6138a2670de0b6b3a7640000826131a4565b156138aa5750565b60405163d8b8b95160e01b81526004810191909152602490fd5b906138d0600a54614b96565b906138ea8160026138e18682612938565b018451906139d5565b6138f781835160046139d5565b61390a613702612f9260408501516131c1565b9182613940575b516040516001600160a01b0390941693600080516020615f828339815191529350918291612b34919083612652565b6139626004602061300661078b600080516020615f6283398151915254611971565b833b1561000e57600061399d600080516020615f828339815191529582936040519485809481936364e5a46f60e11b83528c6004840161296f565b03925af180156139c8575b6139b3575b50613911565b8061281460006139c2936104e8565b386139ad565b6139d061260f565b6139a8565b9091600382018054918201809211613358575555565b600080516020615ec28339815191525461188457600790613a0d612d31612663565b613a6260018060a01b038216918260005260026020526020613a4f604060002094613a3786612d3c565b9060005260028352611e976002604060002001612d5c565b613a5a8151846138c4565b0151906133dd565b01805460ff19166001179055565b60405190613a7f6060836104e8565b8160008152613a8c6131d2565b60208201526040612d8f6131d2565b61055b90613aa76131d2565b506003615c0a565b60608101519091906001600160801b0316613aca81836131a4565b15613b1257670de0b6b3a764000090613ae382846131a4565b15613af55750505060200151600f0b90565b9083916020604061055b960151930151600f0b92600f0b90613b28565b9161055b9260408251920151600f0b91600f0b60005b90929391613b3682846131a4565b158015613bd8575b613bc65761055b94613b94613b8f83613b9a9686670de0b6b3a7640000976114629703928311613bb9575b8986039560008b128015828913169188121617613bac575b8103908111613b9f57613308565b61313b565b906130db565b612cc9565b613ba76128ea565b613308565b613bb46128ea565b613b81565b613bc16128ea565b613b69565b604051630db0f7cb60e01b8152600490fd5b506002613be582856131a4565b14613b3e565b8181039291600013801582851316918412161761290e57565b8115613c2c575b600160ff1b8114600019831416613c20570590565b613c286128ea565b0590565b613c34613176565b613c0b565b61146261055b92670de0b6b3a7640000926130db565b90611462670de0b6b3a764000061055b936130db565b9080613c825750613c7c57670de0b6b3a764000090565b60001990565b61055b91613308565b9081602091031261000e575190565b600080516020615e0283398151915254600080516020615f628339815191525460405163e975c0c360e01b815290602090829060049082906001600160a01b03165afa908115613d17575b600091613cf9575b50808210613303575090565b613d11915060203d81116108965761088781836104e8565b38613ced565b613d1f61260f565b613ce5565b6001600160a01b03909116815260200190565b7f482763b305ee10cd21c16c0cbeed259f2e4fcacdc9767cef16dc1fbe483d34886020613d62612663565b83600080516020615ec2833981519152555192604051938452151592a2565b600a54610a38916001600160a01b0316614c17565b95949295939093303b151580613de7575b6117b857610a3896613dd3613ddd94613dce613de298613dc9613dd896613f43565b613fe1565b61409a565b6142bc565b6143ea565b614518565b6145a6565b50600080516020615de28339815191525415613da7565b60405190613e0d6080836104e8565b60006060838281528260208201528260408201520152565b613e2d613dfe565b50613e36613dfe565b50604051613e456080826104e8565b600080516020615f028339815191525480600f0b825260801d600f0b6020820152600080516020615ee28339815191525480600f0b604083015260801c606082015290565b60405190613e9960c0836104e8565b8160a06000918281528260208201528260408201528260608201528260808201520152565b613ec6613e8a565b50613ecf613e8a565b50604051613ede60c0826104e8565b600080516020615d628339815191525460ff808216151583526001600160401b03600883901c81166020850152604883901c821615156040850152605083901c81166060850152609083901c9091161515608084015260989190911c1660a082015290565b7f18eb97ecd7366a8be310b7e675d67335c7604d5f47446a54a222473625a27e229080600080516020615d4283398151915255613f7e6147b4565b9061280060405192839283612652565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015613fd4575b613fc3575b50613f43565b6000613fce916104e8565b38613fbd565b613fdc61260f565b613fb8565b6002613ff5670de0b6b3a7640000836131a4565b1461403557807fb2743902575ffdab882dfa43a3501f82fbbefa0d2c637e393aed1e80e2cb840b91600080516020615e0283398151915255613f7e6147b4565b604051632012d38160e11b8152600490fd5b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af1801561408d575b61407c575b50613fe1565b6000614087916104e8565b38614076565b61409561260f565b614071565b60026140ae670de0b6b3a7640000836131a4565b1461403557807f6bf5f38f4e94f47ae7a4d6e56dbf388c856f890b5f0f2808b66914710b0266ca91600080516020615e8283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156141e1575b6141d0575b50614121614833565b6141c7576002614139670de0b6b3a7640000836131a4565b1461403557614146613ebe565b6001600160401b038083116141ae579161419e612800927f5dcd1837ba774ef7f1f06e50ad3f64097201da74055346f26a4c7dea9af9084e948316602082015260018152600080516020615d628339815191526141ee565b6040519081529081906020820190565b60405163477e89e360e01b815260048101849052602490fd5b610a389061409a565b60006141db916104e8565b38614118565b6141e961260f565b614113565b81518154602084015160408501516060860151600160501b600160901b0360509190911b166001600160901b031990931693151560ff1693909317610100600160481b0360089290921b919091161760ff60481b92151560481b9290921691909117178155610a38916142969060a09061428861426e6080830151151590565b855460ff60901b191690151560901b60ff60901b16178555565b01516001600160401b031690565b8154600160981b600160d81b03191660989190911b600160981b600160d81b0316179055565b60026142d0670de0b6b3a7640000836131a4565b1461403557807f8e37539629486a88c6a6083eb90030fb61cb856d56d96f53a326fda0d399ef3291600080516020615ea283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af180156143dd575b6143cc575b50614343614833565b6143c357600261435b670de0b6b3a7640000836131a4565b1461403557614368613ebe565b6001600160401b038083116141ae579161419e612800927f4024ee9b51b90807c93e46f7e500580ef5b0b8491e1105188a44f62eed26b129948316606082015260016040820152600080516020615d628339815191526141ee565b610a38906142bc565b60006143d7916104e8565b3861433a565b6143e561260f565b614335565b60026143fe670de0b6b3a7640000836131a4565b1461403557807fd07cf37924efa8fca893c372ddfb1614e6fd8c02cfcc9205262535680b77b93491600080516020615e6283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b815260008160048183305af1801561450b575b6144fa575b50614471614833565b6144f1576002614489670de0b6b3a7640000836131a4565b1461403557614496613ebe565b6001600160401b038083116141ae579161419e612800927f75d77d82706bf877275b9bc542ae4f30aca347d73558e05b56b35a1452f8613294831660a082015260016080820152600080516020615d628339815191526141ee565b610a38906143ea565b6000614505916104e8565b38614468565b61451361260f565b614463565b7fec4e0c10e4e0d362960c0114996546aa9c4d6cc297b00a7577e127b720791beb9080600080516020615f4283398151915255613f7e6147b4565b303b1561000e57604051630476982d60e21b8152610a38919060008160048183305af18015614599575b614588575b50614518565b6000614593916104e8565b38614582565b6145a161260f565b61457d565b60a07fb08b24c7f4e8b392d39bbaf1f4aa9bbb733ba9a467559eb8d9e2ffb634658e9091805161463860018060801b031991600080516020615f0283398151915261460a8482541660018060801b03938416178083556020870151600f0b90614657565b90556040840151600080516020615ee283398151915293845416908216179081845560608501511690614657565b90556146426147b4565b61464f6040518093611de9565b6080820152a1565b6001600160801b031660809190911b6001600160801b0319161790565b303b1561000e57604051630476982d60e21b8152610a3891613de29160008160048183305af180156146bf575b6146ae575b503690612402565b60006146b9916104e8565b386146a6565b6146c761260f565b6146a1565b6146d4613ebe565b80511590811580926147a7575b801561479a575b156128e657610a389161477e575b6040810151614762575b6080810151614746575b6147328160a06000918281528260208201528260408201528260608201528260808201520152565b600080516020615d628339815191526141ee565b60a081015161475d906001600160401b03166143ea565b61470a565b6060810151614779906001600160401b03166142bc565b614700565b6020810151614795906001600160401b031661409a565b6146f6565b50608081015115156146e8565b50604081015115156146e1565b303b156131b55760405163301fd1f560e21b8152602081600481305afa9081156147fc575b6000916147e4575090565b61055b915060203d81116108965761088781836104e8565b61480461260f565b6147d9565b919082604091031261000e576040516148236040826104e8565b6020808294805184520151910152565b6040516359ea287d60e01b815260a081600481305afa80156148c9575b600090614862575b61055b91506148d6565b60a03d81116148c2575b61487681846104e8565b82019060a08383031261075b5750906148b861055b9260606040519361489c82866104e8565b805185526148ad8360208301614809565b602086015201614809565b6040820152614858565b503d61486c565b6148d161260f565b614850565b6148e360208201516148f7565b90816148ed575090565b61055b9150604001515b8051159081614904575090565b6020915001511590565b61491661261c565b5061491f61261c565b5060405161492e6060826104e8565b600080516020615dc28339815191525460ff811661494b8161040f565b825260ff8160081c1661495d8161040f565b602083015261ffff1916604082015290565b303b151580614a33575b6117b857614992906000906001600160a01b0316614c17565b6149a461499f3683614a54565b614aa7565b15614a21576149b4903690614a54565b8051906149c08261040f565b6149c98261040f565b600080516020615dc28339815191529160ff83549116908160ff198216178455604061ff0060208501516149fc8161040f565b614a058161040f565b60081b1693848461ffff19809516171786550151169117179055565b604051639a51fe8f60e01b8152600490fd5b50600080516020615de28339815191525415614979565b6002111561000e57565b919082606091031261000e57604051614a6e6060826104e8565b604081938035614a7d81614a4a565b83526020810135614a8d81614a4a565b602084015201359061ffff198216820361000e5760400152565b60018151614ab48161040f565b614abd8261040f565b614ac68161040f565b14614ad8576040015161ffff19161590565b6001600160a01b0390614aea90614af1565b163b151590565b60018151614afe8161040f565b614b078261040f565b614b108161040f565b03614b28576040015160101c6001600160a01b031690565b8051604491614b368261040f565b604061ffff1991015116604051916327ada38760e11b8352614b578161040f565b60048301526024820152fd5b9081606091031261000e576040805191614b7e6060846104e8565b80518352602081015160208401520151604082015290565b61055b90614ba261261c565b50600080516020615da283398151915254604051637ece075d60e01b81526004810192909252606090829060249082906001600160a01b03165afa908115614c0a575b600091614bf25750614cd1565b611dcf915060603d8111611dd557611dc781836104e8565b614c1261260f565b614be5565b90813b15614c6a57816040917f41dd56c92c84169d8e89dc293d2649a911f47b357d3012bc88662395e01979d093600080516020615da28339815191525582519160018060a01b031682526020820152a1565b60405163d26af10d60e01b8152600490fd5b614c8461261c565b50600080516020615da28339815191525460405160016209351760e01b0319815261055b91606090829060049082906000906001600160a01b03165af1908115614c0a57600091614bf257505b614cd961261c565b50614ce261490e565b614cf26040830191825190614d1a565b905290565b6040810193929160209190614d0b8161040f565b8152614d168361040f565b0152565b8051614d258161040f565b6020820192835192614d368461040f565b614d40600061040f565b614d498361040f565b82614dd95750925b8051614d5c8161040f565b614d66600061040f565b614d6f8161040f565b614d795750505090565b60019051614d868161040f565b614d8f8261040f565b614d988161040f565b03614dbd57505061055b90614db7670de0b6b3a76400006000196130db565b90613c39565b610830604051928392631fafe5ed60e21b845260048401614cf7565b614de3600161040f565b614dec8361040f565b60018303614e045790614dfe91614e22565b92614d51565b5050610830604051928392631fafe5ed60e21b845260048401614cf7565b6001600160a01b0390614e3490614af1565b16604051906020928383019063d7c7a93560e01b8252602484015260248352614e5e6044846104e8565b614e686025614f59565b92614e7660405194856104e8565b602584527f416464726573733a206c6f772d6c6576656c207374617469632063616c6c20668585015264185a5b195960da1b6040850152823b15614f08576000614ef39361055b969593829351915afa3d15614f00573d90614ed782614f59565b91614ee560405193846104e8565b82523d60008684013e614f83565b8051810182019101613c8b565b606090614f83565b60405162461bcd60e51b8152600481018690526024808201527f416464726573733a207374617469632063616c6c20746f206e6f6e2d636f6e746044820152631c9858dd60e21b6064820152608490fd5b6020906001600160401b038111614f76575b601f01601f19160190565b614f7e6104d1565b614f6b565b90919015614f8f575090565b815115614f9f5750805190602001fd5b60405162461bcd60e51b815290819061083090600483016105d1565b9392919061509190614fcb6131d2565b5061146261504e614fe8614fdf87856150c5565b938954906150c5565b94614ff16131d2565b50602080855195885196600088820398128189128116918913901516176150b8575b015196015195600087820397128188128116918813901516176150ab575b604051936150406040866104e8565b845260208401958652612d3c565b936150576131d2565b50615089602061508161506a885161313b565b95611462670de0b6b3a764000097889251906130db565b96015161313b565b9051906130db565b604051916150a06040846104e8565b825260208201529255565b6150b36128ea565b615031565b6150c06128ea565b615013565b6001916150d06131d2565b506000520160205261055b6040600020604051906150ef6040836104e8565b5480600f0b825260801d600f0b60208201526151096131d2565b5060208151910151604051916151206040846104e8565b600f0b8252600f0b602082015290565b6002916150d06131d2565b815181546001600160801b0319166001600160801b0390911617808255602090920151909161516d91600f0b90614657565b9055565b92949391948080516151839088615c0a565b9284828561518f6131d2565b50615199936153f3565b91906151a686838761561a565b6151af9161538f565b976001016151bc90612d5c565b906151c79185615731565b97906151d29161538f565b968101809111926152456152739361526c61524f61524a61524a9661528b99615300575b9c6151ff6131d2565b966020808d01519181880151808403938085116152f3575b82516152b657505060005b8a52019081511560001461529057505060005b602088015261524585518d6150c5565b61538f565b61530d565b615267895160018c0190600052602052604060002090565b61513b565b5187615130565b61526783516002860190600052602052604060002090565b519055565b6152b1916152a9670de0b6b3a7640000613b8f93613163565b905190613308565b615235565b6152e191613b8f91670de0b6b3a7640000918288029288840414911417156152e6575b835190613308565b615222565b6152ee6128ea565b6152d9565b6152fb6128ea565b615217565b6153086128ea565b6151f6565b6153156131d2565b5061532d6020615325835161533c565b92015161533c565b604051916151206040846104e8565b60016001607f1b0381136153775760016001607f1b0319811261535f57600f0b90565b60249060405190634e02165d60e01b82526004820152fd5b60249060405190632cd75ba360e11b82526004820152fd5b906153986131d2565b50602080835193835194600086820196871291129080158216911516176153e6575b01519101519060008282019283129112908015821691151617613258576040519161324e6040846104e8565b6153ee6128ea565b6153ba565b9391939290926154016131d2565b9460409182519363597e1fb560e01b85526020948581600481305afa9081156155f3575b6000916155d6575b506155c357848701908151156155a2578751156155a25785015185840151615454916132b8565b928482516154619061313b565b91015161546d91613c39565b615476906131c1565b61547f886132c5565b6154889161318d565b935163307648eb60e11b815290858083806154a68c60048301611cff565b0381305afa938415996154f861556098614db76154f2614db7996155279f99615542986155579b615595575b600092615578575b5050614db7613b8f670de0b6b3a7640000809e613163565b9161313b565b90615548600061552d8a61551561550e876131c1565b9788613163565b049e8f61552187615600565b976132b8565b8661310c565b941291821561556e5761554284915b5161313b565b90613c4f565b8d52156155665750915161313b565b916000196130db565b90840152565b90509161553c565b615542859161553c565b61558e9250803d106108965761088781836104e8565b388e6154da565b61559d61260f565b6154d2565b5050505060009294506155b69193506123e6565b9181835282015290600090565b50505060009294506155b69193506123e6565b6155ed9150863d88116107355761072781836104e8565b3861542d565b6155fb61260f565b615425565b6000811361561457600013613c7c57600090565b50600190565b9291926156256131d2565b9360409283519363597e1fb560e01b85526020948581600481305afa908115615724575b600091615707575b506156f457848401928351156156d6578451156156d6576156b46156ae6156a761569b61569161554297876156d09b9a986156c898015191015190613beb565b614db7875161313b565b614db7613b8f896132c5565b955161313b565b85613c4f565b614db7670de0b6b3a76400006000196130db565b87525161313b565b90830152565b509150506000929394506156ea91506123e6565b9181835282015290565b9150506000929394506156ea91506123e6565b61571e9150863d88116107355761072781836104e8565b38615651565b61572c61260f565b615649565b9192909261573d6131d2565b93615747816148d6565b615828579061575591615881565b60405190630dbc9ce160e01b825261579b61579561578e6020948581600481305afa90811561581b575b6000916157fe575b5084615830565b8093613272565b9161586e565b8451909490156157e85782906157b9613b8f83850151835190613308565b87525b018051909190156157d85761556091613b8f9151905190613308565b905061055b929391505190612901565b936157f883918284015190612901565b946157bc565b6158159150863d88116108965761088781836104e8565b38615787565b61582361260f565b61577f565b506000925050565b906158396131d2565b5061585e670de0b6b3a764000091602083615855838751613163565b04940151613163565b046040519161324e6040846104e8565b6020815191015181018091116129305790565b6158896131d2565b506158d46158c76158a560209360408582015191015190613214565b936158cc846150816158c760406158bc8a5161313b565b950194855190613c39565b6131c1565b905190613c39565b604051633f1d071f60e21b815290928282600481305afa9182156159a7575b600092615984575b5061594390615914670de0b6b3a7640000938492613163565b6040516343f0179b60e01b8152919004948482600481305afa918215615977575b600092615958575b50613163565b049061594f60406123e6565b92835282015290565b615970919250853d87116108965761088781836104e8565b903861593d565b61597f61260f565b615935565b6159439192506159a090843d86116108965761088781836104e8565b91906158fb565b6159af61260f565b6158f3565b6004906000926159d8575b8281558260018201558260028201558260038201550155565b6159e0610480565b6159bf565b6020615a086159f383612d3c565b936002840194615a0286612d5c565b90615a34565b815184559101516001830155615a1c575050565b615a2960006007936159b4565b01805460ff19169055565b91615a3d6131d2565b5081518015159182615a67575b505015615a6057615a5a916131ed565b90600190565b5090600090565b511190503880615a4a565b6131a0615ac06158c7670de0b6b3a764000093615abb613b8f60408051634ec4474360e11b8152606081600481305afa908115615b30575b600091615b12575b50015192615b3d565b613c39565b604051636c376cc560e01b815290602082600481305afa918215615b05575b600092615aec5750613163565b61597091925060203d81116108965761088781836104e8565b615b0d61260f565b615adf565b615b2a915060603d8111611dd557611dc781836104e8565b38615ab2565b615b3861260f565b615aaa565b8051602090910151808210613303575090565b80541580615baa575b80615b9e575b6001820154159182615b91575b82615b84575b50159081615b7e575090565b90501590565b6006015415915038615b72565b6004810154159250615b6c565b50600581015415615b5f565b50600381015415615b59565b615bd4615bc282612d3c565b615bce60038401612d3c565b90613214565b6002615be660058401548351906131a4565b14918215615bf357505090565b60060154602090910151600292506137ef916131a4565b90615c136131d2565b50600052602052604060002060405190615c2e6040836104e8565b546001600160801b03808216835260809190911c60208301908152918190615c546131d2565b5051169151166040519161324e6040846104e8565b90615c749082615c0a565b91615d01615c8a826001850195615a0287612d5c565b9390615c946131d2565b50615cac6020615ca48351615d15565b920151615d15565b9160405194615cbc6040876104e8565b6001600160801b0392831686529282166020808701918252935160009081529190935260409020935184546001600160801b0319169082161780855591511690614657565b9055615d0a5750565b6000610a38916159b4565b6001600160801b0390818111615d29571690565b60249060405190635385129160e01b82526004820152fdfe968cf792ff9a89745e4746179e93a7b9d7f08b0ff8366fd6f6dbd524ef107464d729c7f2aea8904a802db9fc1939086967cdf7fffe1510c25ccafabfc894614eb9726781b72c53f23217f424d70445b222951f008aeac7eece8139caed71ed2d6c0d5e3cd81753b1b21f67f61d56a97aae7a3e0179486d114788ad4576f53266630ac9ad193fa8d8f5a7207eefdee35934d664003a3d4c286a591e065a62034ead57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398cace7e947336f94057b47a9ab5531b0363e85c8d36c05c7d915ec8e525fd159d863625b85818a29587ee919ee6a968ee0b32f3513f2884b3968001062ba49eb6b1b30fe15febd596dffd21d4da0657732eea42b4b5a9789e3e6daab3d570999d7850062f2c27d17cdf727c8059e0b505bd3a788af62482a56bcede987d8eea5a35a294f9055e9dc7a18078b4e0139086766d723c3cd728bd59cc1f3b589741ed21d7cfd39841edd73967db6350efae442ebd8c6e1bfca55faa52b046d39b7e493bdea2cc426745068386b3804e5b401ae87ffbae9dbf293944b5307f507040c79917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f7917d72d9b73e141a5f0eff6b5933a24665154df6903ed198d591afc8ac62f8f6f98b31465ac12e92b5cb136ade913276c267463c4395bb1a3999bc88fb837806897858f7b7d3c8b4e7a700b401ad192a110353a60c809946583c0d62cda7f0b70e555410d8128dff796eab5d29b97dd593ce9cab44a71b64c08244579ea6053339854479080fac0b5e7c0ecedb0fb02308a72a43cd102c6b9f918653d3400367a26469706673582212204b69baaeef80c3d10bcbfa071e5b42837bde2a623a6bd381b09c0321848898fe64736f6c63430008110033" } diff --git a/packages/perennial/deployments/arbitrumGoerli/solcInputs/008bd4aa82b76d91af7a1bfbf9fddc30.json b/packages/perennial/deployments/arbitrumGoerli/solcInputs/008bd4aa82b76d91af7a1bfbf9fddc30.json new file mode 100644 index 00000000..c18aea23 --- /dev/null +++ b/packages/perennial/deployments/arbitrumGoerli/solcInputs/008bd4aa82b76d91af7a1bfbf9fddc30.json @@ -0,0 +1,165 @@ +{ + "language": "Solidity", + "sources": { + "@equilibria/emptyset-batcher/interfaces/IBatcher.sol": { + "content": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"@equilibria/root/token/types/Token6.sol\";\nimport \"../interfaces/IEmptySetReserve.sol\";\n\ninterface IBatcher {\n event Wrap(address indexed to, UFixed18 amount);\n event Unwrap(address indexed to, UFixed18 amount);\n event Rebalance(UFixed18 newMinted, UFixed18 newRedeemed);\n event Close(UFixed18 amount);\n\n error BatcherNotImplementedError();\n error BatcherBalanceMismatchError(UFixed18 oldBalance, UFixed18 newBalance);\n\n function RESERVE() external view returns (IEmptySetReserve); // solhint-disable-line func-name-mixedcase\n function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase\n function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase\n function totalBalance() external view returns (UFixed18);\n function wrap(UFixed18 amount, address to) external;\n function unwrap(UFixed18 amount, address to) external;\n function rebalance() external;\n}\n" + }, + "@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol": { + "content": "//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\n\ninterface IEmptySetReserve {\n event Redeem(address indexed account, uint256 costAmount, uint256 redeemAmount);\n event Mint(address indexed account, uint256 mintAmount, uint256 costAmount);\n event Repay(address indexed account, uint256 repayAmount);\n\n function debt(address borrower) external view returns (UFixed18);\n function repay(address borrower, UFixed18 amount) external;\n function mint(UFixed18 amount) external;\n function redeem(UFixed18 amount) external;\n}\n" + }, + "@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/Fixed18.sol\";\n\ninterface IOracleProvider {\n /// @dev Error for invalid oracle round\n error InvalidOracleRound();\n\n /// @dev A singular oracle version with its corresponding data\n struct OracleVersion {\n /// @dev The iterative version\n uint256 version;\n\n /// @dev the timestamp of the oracle update\n uint256 timestamp;\n\n /// @dev The oracle price of the corresponding version\n Fixed18 price;\n }\n\n function sync() external returns (OracleVersion memory);\n function currentVersion() external view returns (OracleVersion memory);\n function atVersion(uint256 oracleVersion) external view returns (OracleVersion memory);\n}\n" + }, + "@equilibria/root/control/unstructured/UInitializable.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../../storage/UStorage.sol\";\n\n/**\n * @title UInitializable\n * @notice Library to manage the initialization lifecycle of upgradeable contracts\n * @dev `UInitializable` allows the creation of pseudo-constructors for upgradeable contracts. One\n * `initializer` should be declared per top-level contract. Child contracts can use the `onlyInitializer`\n * modifier to tag their internal initialization functions to ensure that they can only be called\n * from a top-level `initializer` or a constructor.\n */\nabstract contract UInitializable {\n error UInitializableZeroVersionError();\n error UInitializableAlreadyInitializedError(uint256 version);\n error UInitializableNotInitializingError();\n\n event Initialized(uint256 version);\n\n /// @dev The initialized flag\n Uint256Storage private constant _version = Uint256Storage.wrap(keccak256(\"equilibria.root.UInitializable.version\"));\n\n /// @dev The initializing flag\n BoolStorage private constant _initializing = BoolStorage.wrap(keccak256(\"equilibria.root.UInitializable.initializing\"));\n\n /// @dev Can only be called once per version, `version` is 1-indexed\n modifier initializer(uint256 version) {\n if (version == 0) revert UInitializableZeroVersionError();\n if (_version.read() >= version) revert UInitializableAlreadyInitializedError(version);\n\n _version.store(version);\n _initializing.store(true);\n\n _;\n\n _initializing.store(false);\n emit Initialized(version);\n }\n\n /// @dev Can only be called from an initializer or constructor\n modifier onlyInitializer() {\n if (!_constructing() && !_initializing.read()) revert UInitializableNotInitializingError();\n _;\n }\n\n /**\n * @notice Returns whether the contract is currently being constructed\n * @dev {Address.isContract} returns false for contracts currently in the process of being constructed\n * @return Whether the contract is currently being constructed\n */\n function _constructing() private view returns (bool) {\n return !Address.isContract(address(this));\n }\n}\n" + }, + "@equilibria/root/control/unstructured/UReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./UInitializable.sol\";\nimport \"../../storage/UStorage.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * NOTE: This contract has been extended from the Open Zeppelin library to include an\n * unstructured storage pattern, so that it can be safely mixed in with upgradeable\n * contracts without affecting their storage patterns through inheritance.\n */\nabstract contract UReentrancyGuard is UInitializable {\n error UReentrancyGuardReentrantCallError();\n\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n /**\n * @dev unstructured storage slot for the reentrancy status\n */\n Uint256Storage private constant _status = Uint256Storage.wrap(keccak256(\"equilibria.root.UReentrancyGuard.status\"));\n\n /**\n * @dev Initializes the contract setting the status to _NOT_ENTERED.\n */\n function __UReentrancyGuard__initialize() internal onlyInitializer {\n _status.store(_NOT_ENTERED);\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n if (_status.read() == _ENTERED) revert UReentrancyGuardReentrantCallError();\n\n // Any calls to nonReentrant after this point will fail\n _status.store(_ENTERED);\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status.store(_NOT_ENTERED);\n }\n}\n" + }, + "@equilibria/root/curve/CurveMath.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../number/types/UFixed18.sol\";\nimport \"../number/types/Fixed18.sol\";\n\n/**\n * @title CurveMath\n * @notice Library for managing math operations for utilization curves.\n */\nlibrary CurveMath {\n error CurveMathOutOfBoundsError();\n\n /**\n * @notice Computes a linear interpolation between two points\n * @param startX First point's x-coordinate\n * @param startY First point's y-coordinate\n * @param endX Second point's x-coordinate\n * @param endY Second point's y-coordinate\n * @param targetX x-coordinate to interpolate\n * @return y-coordinate for `targetX` along the line from (`startX`, `startY`) -> (`endX`, `endY`)\n */\n function linearInterpolation(\n UFixed18 startX,\n Fixed18 startY,\n UFixed18 endX,\n Fixed18 endY,\n UFixed18 targetX\n ) internal pure returns (Fixed18) {\n if (targetX.lt(startX) || targetX.gt(endX)) revert CurveMathOutOfBoundsError();\n\n UFixed18 xRange = endX.sub(startX);\n Fixed18 yRange = endY.sub(startY);\n UFixed18 xRatio = targetX.sub(startX).div(xRange);\n return yRange.mul(Fixed18Lib.from(xRatio)).add(startY);\n }\n}\n" + }, + "@equilibria/root/curve/types/JumpRateUtilizationCurve.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../CurveMath.sol\";\nimport \"../../number/types/PackedUFixed18.sol\";\nimport \"../../number/types/PackedFixed18.sol\";\n\n/// @dev JumpRateUtilizationCurve type\nstruct JumpRateUtilizationCurve {\n PackedFixed18 minRate;\n PackedFixed18 maxRate;\n PackedFixed18 targetRate;\n PackedUFixed18 targetUtilization;\n}\nusing JumpRateUtilizationCurveLib for JumpRateUtilizationCurve global;\ntype JumpRateUtilizationCurveStorage is bytes32;\nusing JumpRateUtilizationCurveStorageLib for JumpRateUtilizationCurveStorage global;\n\n/**\n * @title JumpRateUtilizationCurveLib\n * @notice Library for the Jump Rate utilization curve type\n */\nlibrary JumpRateUtilizationCurveLib {\n /**\n * @notice Computes the corresponding rate for a utilization ratio\n * @param utilization The utilization ratio\n * @return The corresponding rate\n */\n function compute(JumpRateUtilizationCurve memory self, UFixed18 utilization) internal pure returns (Fixed18) {\n UFixed18 targetUtilization = self.targetUtilization.unpack();\n if (utilization.lt(targetUtilization)) {\n return CurveMath.linearInterpolation(\n UFixed18Lib.ZERO,\n self.minRate.unpack(),\n targetUtilization,\n self.targetRate.unpack(),\n utilization\n );\n }\n if (utilization.lt(UFixed18Lib.ONE)) {\n return CurveMath.linearInterpolation(\n targetUtilization,\n self.targetRate.unpack(),\n UFixed18Lib.ONE,\n self.maxRate.unpack(),\n utilization\n );\n }\n return self.maxRate.unpack();\n }\n}\n\nlibrary JumpRateUtilizationCurveStorageLib {\n function read(JumpRateUtilizationCurveStorage self) internal view returns (JumpRateUtilizationCurve memory) {\n return _storagePointer(self);\n }\n\n function store(JumpRateUtilizationCurveStorage self, JumpRateUtilizationCurve memory value) internal {\n JumpRateUtilizationCurve storage storagePointer = _storagePointer(self);\n\n storagePointer.minRate = value.minRate;\n storagePointer.maxRate = value.maxRate;\n storagePointer.targetRate = value.targetRate;\n storagePointer.targetUtilization = value.targetUtilization;\n }\n\n function _storagePointer(JumpRateUtilizationCurveStorage self)\n private pure returns (JumpRateUtilizationCurve storage pointer) {\n assembly { pointer.slot := self }\n }\n}" + }, + "@equilibria/root/number/types/Fixed18.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport \"./UFixed18.sol\";\nimport \"./PackedFixed18.sol\";\n\n/// @dev Fixed18 type\ntype Fixed18 is int256;\nusing Fixed18Lib for Fixed18 global;\ntype Fixed18Storage is bytes32;\nusing Fixed18StorageLib for Fixed18Storage global;\n\n/**\n * @title Fixed18Lib\n * @notice Library for the signed fixed-decimal type.\n */\nlibrary Fixed18Lib {\n error Fixed18OverflowError(uint256 value);\n error Fixed18PackingOverflowError(int256 value);\n error Fixed18PackingUnderflowError(int256 value);\n\n int256 private constant BASE = 1e18;\n Fixed18 public constant ZERO = Fixed18.wrap(0);\n Fixed18 public constant ONE = Fixed18.wrap(BASE);\n Fixed18 public constant NEG_ONE = Fixed18.wrap(-1 * BASE);\n Fixed18 public constant MAX = Fixed18.wrap(type(int256).max);\n Fixed18 public constant MIN = Fixed18.wrap(type(int256).min);\n\n /**\n * @notice Creates a signed fixed-decimal from an unsigned fixed-decimal\n * @param a Unsigned fixed-decimal\n * @return New signed fixed-decimal\n */\n function from(UFixed18 a) internal pure returns (Fixed18) {\n uint256 value = UFixed18.unwrap(a);\n if (value > uint256(type(int256).max)) revert Fixed18OverflowError(value);\n return Fixed18.wrap(int256(value));\n }\n\n /**\n * @notice Creates a signed fixed-decimal from a sign and an unsigned fixed-decimal\n * @param s Sign\n * @param m Unsigned fixed-decimal magnitude\n * @return New signed fixed-decimal\n */\n function from(int256 s, UFixed18 m) internal pure returns (Fixed18) {\n if (s > 0) return from(m);\n if (s < 0) return Fixed18.wrap(-1 * Fixed18.unwrap(from(m)));\n return ZERO;\n }\n\n /**\n * @notice Creates a signed fixed-decimal from a signed integer\n * @param a Signed number\n * @return New signed fixed-decimal\n */\n function from(int256 a) internal pure returns (Fixed18) {\n return Fixed18.wrap(a * BASE);\n }\n\n /**\n * @notice Creates a packed signed fixed-decimal from an signed fixed-decimal\n * @param a signed fixed-decimal\n * @return New packed signed fixed-decimal\n */\n function pack(Fixed18 a) internal pure returns (PackedFixed18) {\n int256 value = Fixed18.unwrap(a);\n if (value > type(int128).max) revert Fixed18PackingOverflowError(value);\n if (value < type(int128).min) revert Fixed18PackingUnderflowError(value);\n return PackedFixed18.wrap(int128(value));\n }\n\n /**\n * @notice Returns whether the signed fixed-decimal is equal to zero.\n * @param a Signed fixed-decimal\n * @return Whether the signed fixed-decimal is zero.\n */\n function isZero(Fixed18 a) internal pure returns (bool) {\n return Fixed18.unwrap(a) == 0;\n }\n\n /**\n * @notice Adds two signed fixed-decimals `a` and `b` together\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Resulting summed signed fixed-decimal\n */\n function add(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(Fixed18.unwrap(a) + Fixed18.unwrap(b));\n }\n\n /**\n * @notice Subtracts signed fixed-decimal `b` from `a`\n * @param a Signed fixed-decimal to subtract from\n * @param b Signed fixed-decimal to subtract\n * @return Resulting subtracted signed fixed-decimal\n */\n function sub(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(Fixed18.unwrap(a) - Fixed18.unwrap(b));\n }\n\n /**\n * @notice Multiplies two signed fixed-decimals `a` and `b` together\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Resulting multiplied signed fixed-decimal\n */\n function mul(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(Fixed18.unwrap(a) * Fixed18.unwrap(b) / BASE);\n }\n\n /**\n * @notice Divides signed fixed-decimal `a` by `b`\n * @param a Signed fixed-decimal to divide\n * @param b Signed fixed-decimal to divide by\n * @return Resulting divided signed fixed-decimal\n */\n function div(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(Fixed18.unwrap(a) * BASE / Fixed18.unwrap(b));\n }\n\n /**\n * @notice Divides unsigned fixed-decimal `a` by `b`\n * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0`, `MAX` for `n/0`, and `MIN` for `-n/0`.\n * @param a Unsigned fixed-decimal to divide\n * @param b Unsigned fixed-decimal to divide by\n * @return Resulting divided unsigned fixed-decimal\n */\n function unsafeDiv(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n if (isZero(b)) {\n if (gt(a, ZERO)) return MAX;\n if (lt(a, ZERO)) return MIN;\n return ONE;\n } else {\n return div(a, b);\n }\n }\n\n /**\n * @notice Computes a * b / c without loss of precision due to BASE conversion\n * @param a First signed fixed-decimal\n * @param b Signed number to multiply by\n * @param c Signed number to divide by\n * @return Resulting computation\n */\n function muldiv(Fixed18 a, int256 b, int256 c) internal pure returns (Fixed18) {\n return muldiv(a, Fixed18.wrap(b), Fixed18.wrap(c));\n }\n\n /**\n * @notice Computes a * b / c without loss of precision due to BASE conversion\n * @param a First signed fixed-decimal\n * @param b Signed fixed-decimal to multiply by\n * @param c Signed fixed-decimal to divide by\n * @return Resulting computation\n */\n function muldiv(Fixed18 a, Fixed18 b, Fixed18 c) internal pure returns (Fixed18) {\n return Fixed18.wrap(Fixed18.unwrap(a) * Fixed18.unwrap(b) / Fixed18.unwrap(c));\n }\n\n /**\n * @notice Returns whether signed fixed-decimal `a` is equal to `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Whether `a` is equal to `b`\n */\n function eq(Fixed18 a, Fixed18 b) internal pure returns (bool) {\n return compare(a, b) == 1;\n }\n\n /**\n * @notice Returns whether signed fixed-decimal `a` is greater than `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Whether `a` is greater than `b`\n */\n function gt(Fixed18 a, Fixed18 b) internal pure returns (bool) {\n return compare(a, b) == 2;\n }\n\n /**\n * @notice Returns whether signed fixed-decimal `a` is less than `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Whether `a` is less than `b`\n */\n function lt(Fixed18 a, Fixed18 b) internal pure returns (bool) {\n return compare(a, b) == 0;\n }\n\n /**\n * @notice Returns whether signed fixed-decimal `a` is greater than or equal to `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Whether `a` is greater than or equal to `b`\n */\n function gte(Fixed18 a, Fixed18 b) internal pure returns (bool) {\n return gt(a, b) || eq(a, b);\n }\n\n /**\n * @notice Returns whether signed fixed-decimal `a` is less than or equal to `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Whether `a` is less than or equal to `b`\n */\n function lte(Fixed18 a, Fixed18 b) internal pure returns (bool) {\n return lt(a, b) || eq(a, b);\n }\n\n /**\n * @notice Compares the signed fixed-decimals `a` and `b`\n * @dev Returns: 2 for greater than\n * 1 for equal to\n * 0 for less than\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Compare result of `a` and `b`\n */\n function compare(Fixed18 a, Fixed18 b) internal pure returns (uint256) {\n (int256 au, int256 bu) = (Fixed18.unwrap(a), Fixed18.unwrap(b));\n if (au > bu) return 2;\n if (au < bu) return 0;\n return 1;\n }\n\n /**\n * @notice Returns a signed fixed-decimal representing the ratio of `a` over `b`\n * @param a First signed number\n * @param b Second signed number\n * @return Ratio of `a` over `b`\n */\n function ratio(int256 a, int256 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(a * BASE / b);\n }\n\n /**\n * @notice Returns the minimum of signed fixed-decimals `a` and `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Minimum of `a` and `b`\n */\n function min(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(SignedMath.min(Fixed18.unwrap(a), Fixed18.unwrap(b)));\n }\n\n /**\n * @notice Returns the maximum of signed fixed-decimals `a` and `b`\n * @param a First signed fixed-decimal\n * @param b Second signed fixed-decimal\n * @return Maximum of `a` and `b`\n */\n function max(Fixed18 a, Fixed18 b) internal pure returns (Fixed18) {\n return Fixed18.wrap(SignedMath.max(Fixed18.unwrap(a), Fixed18.unwrap(b)));\n }\n\n /**\n * @notice Converts the signed fixed-decimal into an integer, truncating any decimal portion\n * @param a Signed fixed-decimal\n * @return Truncated signed number\n */\n function truncate(Fixed18 a) internal pure returns (int256) {\n return Fixed18.unwrap(a) / BASE;\n }\n\n /**\n * @notice Returns the sign of the signed fixed-decimal\n * @dev Returns: -1 for negative\n * 0 for zero\n * 1 for positive\n * @param a Signed fixed-decimal\n * @return Sign of the signed fixed-decimal\n */\n function sign(Fixed18 a) internal pure returns (int256) {\n if (Fixed18.unwrap(a) > 0) return 1;\n if (Fixed18.unwrap(a) < 0) return -1;\n return 0;\n }\n\n /**\n * @notice Returns the absolute value of the signed fixed-decimal\n * @param a Signed fixed-decimal\n * @return Absolute value of the signed fixed-decimal\n */\n function abs(Fixed18 a) internal pure returns (UFixed18) {\n return UFixed18.wrap(SignedMath.abs(Fixed18.unwrap(a)));\n }\n}\n\nlibrary Fixed18StorageLib {\n function read(Fixed18Storage self) internal view returns (Fixed18 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Fixed18Storage self, Fixed18 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@equilibria/root/number/types/PackedFixed18.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./Fixed18.sol\";\n\n/// @dev PackedFixed18 type\ntype PackedFixed18 is int128;\nusing PackedFixed18Lib for PackedFixed18 global;\n\n/**\n * @title PackedFixed18Lib\n * @dev A packed version of the Fixed18 which takes up half the storage space (two PackedFixed18 can be packed\n * into a single slot). Only valid within the range -1.7014118e+20 <= x <= 1.7014118e+20.\n * @notice Library for the packed signed fixed-decimal type.\n */\nlibrary PackedFixed18Lib {\n PackedFixed18 public constant MAX = PackedFixed18.wrap(type(int128).max);\n PackedFixed18 public constant MIN = PackedFixed18.wrap(type(int128).min);\n\n /**\n * @notice Creates an unpacked signed fixed-decimal from a packed signed fixed-decimal\n * @param self packed signed fixed-decimal\n * @return New unpacked signed fixed-decimal\n */\n function unpack(PackedFixed18 self) internal pure returns (Fixed18) {\n return Fixed18.wrap(int256(PackedFixed18.unwrap(self)));\n }\n}\n" + }, + "@equilibria/root/number/types/PackedUFixed18.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"./UFixed18.sol\";\n\n/// @dev PackedUFixed18 type\ntype PackedUFixed18 is uint128;\nusing PackedUFixed18Lib for PackedUFixed18 global;\n\n/**\n * @title PackedUFixed18Lib\n * @dev A packed version of the UFixed18 which takes up half the storage space (two PackedUFixed18 can be packed\n * into a single slot). Only valid within the range 0 <= x <= 3.4028237e+20.\n * @notice Library for the packed unsigned fixed-decimal type.\n */\nlibrary PackedUFixed18Lib {\n PackedUFixed18 public constant MAX = PackedUFixed18.wrap(type(uint128).max);\n\n /**\n * @notice Creates an unpacked unsigned fixed-decimal from a packed unsigned fixed-decimal\n * @param self packed unsigned fixed-decimal\n * @return New unpacked unsigned fixed-decimal\n */\n function unpack(PackedUFixed18 self) internal pure returns (UFixed18) {\n return UFixed18.wrap(uint256(PackedUFixed18.unwrap(self)));\n }\n}\n" + }, + "@equilibria/root/number/types/UFixed18.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"./Fixed18.sol\";\nimport \"./PackedUFixed18.sol\";\n\n/// @dev UFixed18 type\ntype UFixed18 is uint256;\nusing UFixed18Lib for UFixed18 global;\ntype UFixed18Storage is bytes32;\nusing UFixed18StorageLib for UFixed18Storage global;\n\n/**\n * @title UFixed18Lib\n * @notice Library for the unsigned fixed-decimal type.\n */\nlibrary UFixed18Lib {\n error UFixed18UnderflowError(int256 value);\n error UFixed18PackingOverflowError(uint256 value);\n\n uint256 private constant BASE = 1e18;\n UFixed18 public constant ZERO = UFixed18.wrap(0);\n UFixed18 public constant ONE = UFixed18.wrap(BASE);\n UFixed18 public constant MAX = UFixed18.wrap(type(uint256).max);\n\n /**\n * @notice Creates a unsigned fixed-decimal from a signed fixed-decimal\n * @param a Signed fixed-decimal\n * @return New unsigned fixed-decimal\n */\n function from(Fixed18 a) internal pure returns (UFixed18) {\n int256 value = Fixed18.unwrap(a);\n if (value < 0) revert UFixed18UnderflowError(value);\n return UFixed18.wrap(uint256(value));\n }\n\n /**\n * @notice Creates a unsigned fixed-decimal from a unsigned integer\n * @param a Unsigned number\n * @return New unsigned fixed-decimal\n */\n function from(uint256 a) internal pure returns (UFixed18) {\n return UFixed18.wrap(a * BASE);\n }\n\n /**\n * @notice Creates a packed unsigned fixed-decimal from an unsigned fixed-decimal\n * @param a unsigned fixed-decimal\n * @return New packed unsigned fixed-decimal\n */\n function pack(UFixed18 a) internal pure returns (PackedUFixed18) {\n uint256 value = UFixed18.unwrap(a);\n if (value > type(uint128).max) revert UFixed18PackingOverflowError(value);\n return PackedUFixed18.wrap(uint128(value));\n }\n\n /**\n * @notice Returns whether the unsigned fixed-decimal is equal to zero.\n * @param a Unsigned fixed-decimal\n * @return Whether the unsigned fixed-decimal is zero.\n */\n function isZero(UFixed18 a) internal pure returns (bool) {\n return UFixed18.unwrap(a) == 0;\n }\n\n /**\n * @notice Adds two unsigned fixed-decimals `a` and `b` together\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Resulting summed unsigned fixed-decimal\n */\n function add(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(UFixed18.unwrap(a) + UFixed18.unwrap(b));\n }\n\n /**\n * @notice Subtracts unsigned fixed-decimal `b` from `a`\n * @param a Unsigned fixed-decimal to subtract from\n * @param b Unsigned fixed-decimal to subtract\n * @return Resulting subtracted unsigned fixed-decimal\n */\n function sub(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(UFixed18.unwrap(a) - UFixed18.unwrap(b));\n }\n\n /**\n * @notice Multiplies two unsigned fixed-decimals `a` and `b` together\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Resulting multiplied unsigned fixed-decimal\n */\n function mul(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / BASE);\n }\n\n /**\n * @notice Divides unsigned fixed-decimal `a` by `b`\n * @param a Unsigned fixed-decimal to divide\n * @param b Unsigned fixed-decimal to divide by\n * @return Resulting divided unsigned fixed-decimal\n */\n function div(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(UFixed18.unwrap(a) * BASE / UFixed18.unwrap(b));\n }\n\n /**\n * @notice Divides unsigned fixed-decimal `a` by `b`\n * @dev Does not revert on divide-by-0, instead returns `ONE` for `0/0` and `MAX` for `n/0`.\n * @param a Unsigned fixed-decimal to divide\n * @param b Unsigned fixed-decimal to divide by\n * @return Resulting divided unsigned fixed-decimal\n */\n function unsafeDiv(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n if (isZero(b)) {\n return isZero(a) ? ONE : MAX;\n } else {\n return div(a, b);\n }\n }\n\n /**\n * @notice Computes a * b / c without loss of precision due to BASE conversion\n * @param a First unsigned fixed-decimal\n * @param b Unsigned number to multiply by\n * @param c Unsigned number to divide by\n * @return Resulting computation\n */\n function muldiv(UFixed18 a, uint256 b, uint256 c) internal pure returns (UFixed18) {\n return muldiv(a, UFixed18.wrap(b), UFixed18.wrap(c));\n }\n\n /**\n * @notice Computes a * b / c without loss of precision due to BASE conversion\n * @param a First unsigned fixed-decimal\n * @param b Unsigned fixed-decimal to multiply by\n * @param c Unsigned fixed-decimal to divide by\n * @return Resulting computation\n */\n function muldiv(UFixed18 a, UFixed18 b, UFixed18 c) internal pure returns (UFixed18) {\n return UFixed18.wrap(UFixed18.unwrap(a) * UFixed18.unwrap(b) / UFixed18.unwrap(c));\n }\n\n /**\n * @notice Returns whether unsigned fixed-decimal `a` is equal to `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Whether `a` is equal to `b`\n */\n function eq(UFixed18 a, UFixed18 b) internal pure returns (bool) {\n return compare(a, b) == 1;\n }\n\n /**\n * @notice Returns whether unsigned fixed-decimal `a` is greater than `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Whether `a` is greater than `b`\n */\n function gt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\n return compare(a, b) == 2;\n }\n\n /**\n * @notice Returns whether unsigned fixed-decimal `a` is less than `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Whether `a` is less than `b`\n */\n function lt(UFixed18 a, UFixed18 b) internal pure returns (bool) {\n return compare(a, b) == 0;\n }\n\n /**\n * @notice Returns whether unsigned fixed-decimal `a` is greater than or equal to `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Whether `a` is greater than or equal to `b`\n */\n function gte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\n return gt(a, b) || eq(a, b);\n }\n\n /**\n * @notice Returns whether unsigned fixed-decimal `a` is less than or equal to `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Whether `a` is less than or equal to `b`\n */\n function lte(UFixed18 a, UFixed18 b) internal pure returns (bool) {\n return lt(a, b) || eq(a, b);\n }\n\n /**\n * @notice Compares the unsigned fixed-decimals `a` and `b`\n * @dev Returns: 2 for greater than\n * 1 for equal to\n * 0 for less than\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Compare result of `a` and `b`\n */\n function compare(UFixed18 a, UFixed18 b) internal pure returns (uint256) {\n (uint256 au, uint256 bu) = (UFixed18.unwrap(a), UFixed18.unwrap(b));\n if (au > bu) return 2;\n if (au < bu) return 0;\n return 1;\n }\n\n /**\n * @notice Returns a unsigned fixed-decimal representing the ratio of `a` over `b`\n * @param a First unsigned number\n * @param b Second unsigned number\n * @return Ratio of `a` over `b`\n */\n function ratio(uint256 a, uint256 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(a * BASE / b);\n }\n\n /**\n * @notice Returns the minimum of unsigned fixed-decimals `a` and `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Minimum of `a` and `b`\n */\n function min(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(Math.min(UFixed18.unwrap(a), UFixed18.unwrap(b)));\n }\n\n /**\n * @notice Returns the maximum of unsigned fixed-decimals `a` and `b`\n * @param a First unsigned fixed-decimal\n * @param b Second unsigned fixed-decimal\n * @return Maximum of `a` and `b`\n */\n function max(UFixed18 a, UFixed18 b) internal pure returns (UFixed18) {\n return UFixed18.wrap(Math.max(UFixed18.unwrap(a), UFixed18.unwrap(b)));\n }\n\n /**\n * @notice Converts the unsigned fixed-decimal into an integer, truncating any decimal portion\n * @param a Unsigned fixed-decimal\n * @return Truncated unsigned number\n */\n function truncate(UFixed18 a) internal pure returns (uint256) {\n return UFixed18.unwrap(a) / BASE;\n }\n}\n\nlibrary UFixed18StorageLib {\n function read(UFixed18Storage self) internal view returns (UFixed18 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(UFixed18Storage self, UFixed18 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@equilibria/root/storage/UStorage.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../number/types/UFixed18.sol\";\n\n/// @dev Stored boolean slot\ntype BoolStorage is bytes32;\nusing BoolStorageLib for BoolStorage global;\n\n/// @dev Stored uint256 slot\ntype Uint256Storage is bytes32;\nusing Uint256StorageLib for Uint256Storage global;\n\n/// @dev Stored int256 slot\ntype Int256Storage is bytes32;\nusing Int256StorageLib for Int256Storage global;\n\n/// @dev Stored address slot\ntype AddressStorage is bytes32;\nusing AddressStorageLib for AddressStorage global;\n\n/// @dev Stored bytes32 slot\ntype Bytes32Storage is bytes32;\nusing Bytes32StorageLib for Bytes32Storage global;\n\n/**\n * @title BoolStorageLib\n * @notice Library to manage storage and retrival of a boolean at a fixed storage slot\n */\nlibrary BoolStorageLib {\n /**\n * @notice Retrieves the stored value\n * @param self Storage slot\n * @return value Stored bool value\n */\n function read(BoolStorage self) internal view returns (bool value) {\n assembly {\n value := sload(self)\n }\n }\n\n /**\n * @notice Stores the value at the specific slot\n * @param self Storage slot\n * @param value boolean value to store\n */\n function store(BoolStorage self, bool value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\n/**\n * @title Uint256StorageLib\n * @notice Library to manage storage and retrival of an uint256 at a fixed storage slot\n */\nlibrary Uint256StorageLib {\n /**\n * @notice Retrieves the stored value\n * @param self Storage slot\n * @return value Stored uint256 value\n */\n function read(Uint256Storage self) internal view returns (uint256 value) {\n assembly {\n value := sload(self)\n }\n }\n\n /**\n * @notice Stores the value at the specific slot\n * @param self Storage slot\n * @param value uint256 value to store\n */\n function store(Uint256Storage self, uint256 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\n/**\n * @title Int256StorageLib\n * @notice Library to manage storage and retrival of an int256 at a fixed storage slot\n */\nlibrary Int256StorageLib {\n /**\n * @notice Retrieves the stored value\n * @param self Storage slot\n * @return value Stored int256 value\n */\n function read(Int256Storage self) internal view returns (int256 value) {\n assembly {\n value := sload(self)\n }\n }\n\n /**\n * @notice Stores the value at the specific slot\n * @param self Storage slot\n * @param value int256 value to store\n */\n function store(Int256Storage self, int256 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\n/**\n * @title AddressStorageLib\n * @notice Library to manage storage and retrival of an address at a fixed storage slot\n */\nlibrary AddressStorageLib {\n /**\n * @notice Retrieves the stored value\n * @param self Storage slot\n * @return value Stored address value\n */\n function read(AddressStorage self) internal view returns (address value) {\n assembly {\n value := sload(self)\n }\n }\n\n /**\n * @notice Stores the value at the specific slot\n * @param self Storage slot\n * @param value address value to store\n */\n function store(AddressStorage self, address value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n\n/**\n * @title Bytes32StorageLib\n * @notice Library to manage storage and retrival of a bytes32 at a fixed storage slot\n */\nlibrary Bytes32StorageLib {\n /**\n * @notice Retrieves the stored value\n * @param self Storage slot\n * @return value Stored bytes32 value\n */\n function read(Bytes32Storage self) internal view returns (bytes32 value) {\n assembly {\n value := sload(self)\n }\n }\n\n /**\n * @notice Stores the value at the specific slot\n * @param self Storage slot\n * @param value bytes32 value to store\n */\n function store(Bytes32Storage self, bytes32 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@equilibria/root/token/types/Token18.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../../number/types/UFixed18.sol\";\n\n/// @dev Token18\ntype Token18 is address;\nusing Token18Lib for Token18 global;\ntype Token18Storage is bytes32;\nusing Token18StorageLib for Token18Storage global;\n\n/**\n * @title Token18Lib\n * @notice Library to manage 18-decimal ERC20s that is compliant with the fixed-decimal types.\n * @dev Maintains significant gas savings over other Token implementations since no conversion take place\n */\nlibrary Token18Lib {\n using SafeERC20 for IERC20;\n\n Token18 public constant ZERO = Token18.wrap(address(0));\n\n /**\n * @notice Returns whether a token is the zero address\n * @param self Token to check for\n * @return Whether the token is the zero address\n */\n function isZero(Token18 self) internal pure returns (bool) {\n return Token18.unwrap(self) == Token18.unwrap(ZERO);\n }\n\n /**\n * @notice Returns whether the two tokens are equal\n * @param a First token to compare\n * @param b Second token to compare\n * @return Whether the two tokens are equal\n */\n function eq(Token18 a, Token18 b) internal pure returns (bool) {\n return Token18.unwrap(a) == Token18.unwrap(b);\n }\n\n /**\n * @notice Approves `grantee` to spend infinite tokens from the caller\n * @param self Token to transfer\n * @param grantee Address to allow spending\n */\n function approve(Token18 self, address grantee) internal {\n IERC20(Token18.unwrap(self)).safeApprove(grantee, type(uint256).max);\n }\n\n /**\n * @notice Approves `grantee` to spend `amount` tokens from the caller\n * @dev There are important race conditions to be aware of when using this function\n with values other than 0. This will revert if moving from non-zero to non-zero amounts\n See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\n * @param self Token to transfer\n * @param grantee Address to allow spending\n * @param amount Amount of tokens to approve to spend\n */\n function approve(Token18 self, address grantee, UFixed18 amount) internal {\n IERC20(Token18.unwrap(self)).safeApprove(grantee, UFixed18.unwrap(amount));\n }\n\n /**\n * @notice Transfers all held tokens from the caller to the `recipient`\n * @param self Token to transfer\n * @param recipient Address to receive the tokens\n */\n function push(Token18 self, address recipient) internal {\n push(self, recipient, balanceOf(self, address(this)));\n }\n\n /**\n * @notice Transfers `amount` tokens from the caller to the `recipient`\n * @param self Token to transfer\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n */\n function push(Token18 self, address recipient, UFixed18 amount) internal {\n IERC20(Token18.unwrap(self)).safeTransfer(recipient, UFixed18.unwrap(amount));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to the caller\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param amount Amount of tokens to transfer\n */\n function pull(Token18 self, address benefactor, UFixed18 amount) internal {\n IERC20(Token18.unwrap(self)).safeTransferFrom(benefactor, address(this), UFixed18.unwrap(amount));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n */\n function pullTo(Token18 self, address benefactor, address recipient, UFixed18 amount) internal {\n IERC20(Token18.unwrap(self)).safeTransferFrom(benefactor, recipient, UFixed18.unwrap(amount));\n }\n\n /**\n * @notice Returns the name of the token\n * @param self Token to check for\n * @return Token name\n */\n function name(Token18 self) internal view returns (string memory) {\n return IERC20Metadata(Token18.unwrap(self)).name();\n }\n\n /**\n * @notice Returns the symbol of the token\n * @param self Token to check for\n * @return Token symbol\n */\n function symbol(Token18 self) internal view returns (string memory) {\n return IERC20Metadata(Token18.unwrap(self)).symbol();\n }\n\n /**\n * @notice Returns the `self` token balance of the caller\n * @param self Token to check for\n * @return Token balance of the caller\n */\n function balanceOf(Token18 self) internal view returns (UFixed18) {\n return balanceOf(self, address(this));\n }\n\n /**\n * @notice Returns the `self` token balance of `account`\n * @param self Token to check for\n * @param account Account to check\n * @return Token balance of the account\n */\n function balanceOf(Token18 self, address account) internal view returns (UFixed18) {\n return UFixed18.wrap(IERC20(Token18.unwrap(self)).balanceOf(account));\n }\n}\n\nlibrary Token18StorageLib {\n function read(Token18Storage self) internal view returns (Token18 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Token18Storage self, Token18 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@equilibria/root/token/types/Token6.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"../../number/types/UFixed18.sol\";\n\n/// @dev Token6\ntype Token6 is address;\nusing Token6Lib for Token6 global;\ntype Token6Storage is bytes32;\nusing Token6StorageLib for Token6Storage global;\n\n/**\n * @title Token6Lib\n * @notice Library to manage 6-decimal ERC20s that is compliant with the fixed-decimal types.\n * @dev Automatically converts from Base-6 token amounts to Base-18 UFixed18 amounts, with optional rounding\n */\nlibrary Token6Lib {\n using SafeERC20 for IERC20;\n\n Token6 public constant ZERO = Token6.wrap(address(0));\n\n uint256 private constant OFFSET = 1e12;\n\n /**\n * @notice Returns whether a token is the zero address\n * @param self Token to check for\n * @return Whether the token is the zero address\n */\n function isZero(Token6 self) internal pure returns (bool) {\n return Token6.unwrap(self) == Token6.unwrap(ZERO);\n }\n\n /**\n * @notice Returns whether the two tokens are equal\n * @param a First token to compare\n * @param b Second token to compare\n * @return Whether the two tokens are equal\n */\n function eq(Token6 a, Token6 b) internal pure returns (bool) {\n return Token6.unwrap(a) == Token6.unwrap(b);\n }\n\n /**\n * @notice Approves `grantee` to spend infinite tokens from the caller\n * @param self Token to transfer\n * @param grantee Address to allow spending\n */\n function approve(Token6 self, address grantee) internal {\n IERC20(Token6.unwrap(self)).safeApprove(grantee, type(uint256).max);\n }\n\n /**\n * @notice Approves `grantee` to spend `amount` tokens from the caller\n * @dev There are important race conditions to be aware of when using this function\n with values other than 0. This will revert if moving from non-zero to non-zero amounts\n See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\n * @param self Token to transfer\n * @param grantee Address to allow spending\n * @param amount Amount of tokens to approve to spend\n */\n function approve(Token6 self, address grantee, UFixed18 amount) internal {\n IERC20(Token6.unwrap(self)).safeApprove(grantee, toTokenAmount(amount, false));\n }\n\n /**\n * @notice Approves `grantee` to spend `amount` tokens from the caller\n * @dev There are important race conditions to be aware of when using this function\n with values other than 0. This will revert if moving from non-zero to non-zero amounts\n See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57\n * @param self Token to transfer\n * @param grantee Address to allow spending\n * @param amount Amount of tokens to approve to spend\n * @param roundUp Whether to round decimal token amount up to the next unit\n */\n function approve(Token6 self, address grantee, UFixed18 amount, bool roundUp) internal {\n IERC20(Token6.unwrap(self)).safeApprove(grantee, toTokenAmount(amount, roundUp));\n }\n\n /**\n * @notice Transfers all held tokens from the caller to the `recipient`\n * @param self Token to transfer\n * @param recipient Address to receive the tokens\n */\n function push(Token6 self, address recipient) internal {\n push(self, recipient, balanceOf(self, address(this)));\n }\n\n /**\n * @notice Transfers `amount` tokens from the caller to the `recipient`\n * @param self Token to transfer\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n */\n function push(Token6 self, address recipient, UFixed18 amount) internal {\n IERC20(Token6.unwrap(self)).safeTransfer(recipient, toTokenAmount(amount, false));\n }\n\n /**\n * @notice Transfers `amount` tokens from the caller to the `recipient`\n * @param self Token to transfer\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n * @param roundUp Whether to round decimal token amount up to the next unit\n */\n function push(Token6 self, address recipient, UFixed18 amount, bool roundUp) internal {\n IERC20(Token6.unwrap(self)).safeTransfer(recipient, toTokenAmount(amount, roundUp));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to the caller\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param amount Amount of tokens to transfer\n */\n function pull(Token6 self, address benefactor, UFixed18 amount) internal {\n IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, address(this), toTokenAmount(amount, false));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to the caller\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param amount Amount of tokens to transfer\n * @param roundUp Whether to round decimal token amount up to the next unit\n */\n function pull(Token6 self, address benefactor, UFixed18 amount, bool roundUp) internal {\n IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, address(this), toTokenAmount(amount, roundUp));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n */\n function pullTo(Token6 self, address benefactor, address recipient, UFixed18 amount) internal {\n IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, recipient, toTokenAmount(amount, false));\n }\n\n /**\n * @notice Transfers `amount` tokens from the `benefactor` to `recipient`\n * @dev Reverts if trying to pull Ether\n * @param self Token to transfer\n * @param benefactor Address to transfer tokens from\n * @param recipient Address to transfer tokens to\n * @param amount Amount of tokens to transfer\n * @param roundUp Whether to round decimal token amount up to the next unit\n */\n function pullTo(Token6 self, address benefactor, address recipient, UFixed18 amount, bool roundUp) internal {\n IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, recipient, toTokenAmount(amount, roundUp));\n }\n\n /**\n * @notice Returns the name of the token\n * @param self Token to check for\n * @return Token name\n */\n function name(Token6 self) internal view returns (string memory) {\n return IERC20Metadata(Token6.unwrap(self)).name();\n }\n\n /**\n * @notice Returns the symbol of the token\n * @param self Token to check for\n * @return Token symbol\n */\n function symbol(Token6 self) internal view returns (string memory) {\n return IERC20Metadata(Token6.unwrap(self)).symbol();\n }\n\n /**\n * @notice Returns the `self` token balance of the caller\n * @param self Token to check for\n * @return Token balance of the caller\n */\n function balanceOf(Token6 self) internal view returns (UFixed18) {\n return balanceOf(self, address(this));\n }\n\n /**\n * @notice Returns the `self` token balance of `account`\n * @param self Token to check for\n * @param account Account to check\n * @return Token balance of the account\n */\n function balanceOf(Token6 self, address account) internal view returns (UFixed18) {\n return fromTokenAmount(IERC20(Token6.unwrap(self)).balanceOf(account));\n }\n\n /**\n * @notice Converts the unsigned fixed-decimal amount into the token amount according to\n * it's defined decimals\n * @dev Provides the ability to \"round up\" the token amount which is useful in situations where\n * are swapping one token for another and don't want to give away \"free\" units due to rounding\n * errors in the favor of the user.\n * @param amount Amount to convert\n * @param roundUp Whether to round decimal token amount up to the next unit\n * @return Normalized token amount\n */\n function toTokenAmount(UFixed18 amount, bool roundUp) private pure returns (uint256) {\n return roundUp ? Math.ceilDiv(UFixed18.unwrap(amount), OFFSET) : UFixed18.unwrap(amount) / OFFSET;\n }\n\n /**\n * @notice Converts the token amount into the unsigned fixed-decimal amount according to\n * it's defined decimals\n * @param amount Token amount to convert\n * @return Normalized unsigned fixed-decimal amount\n */\n function fromTokenAmount(uint256 amount) private pure returns (UFixed18) {\n return UFixed18.wrap(amount * OFFSET);\n }\n}\n\nlibrary Token6StorageLib {\n function read(Token6Storage self) internal view returns (Token6 value) {\n assembly {\n value := sload(self)\n }\n }\n\n function store(Token6Storage self, Token6 value) internal {\n assembly {\n sstore(self, value)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\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 /**\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.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 Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) 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(\n IERC20 token,\n address spender,\n uint256 value\n ) 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 require(\n (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(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\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) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 (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(\n address target,\n bytes memory data,\n string memory errorMessage\n ) 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(\n address target,\n bytes memory data,\n uint256 value\n ) 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(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) 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 (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(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\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(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal 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 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" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "contracts/controller/UControllerProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.15;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/storage/UStorage.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../interfaces/IController.sol\";\nimport \"../interfaces/IProduct.sol\";\n\n/**\n * @title UControllerProvider\n * @notice Mix-in that manages a controller pointer and associated permissioning modifiers.\n * @dev Uses unstructured storage so that it is safe to mix-in to upgreadable contracts without modifying\n * their storage layout.\n */\nabstract contract UControllerProvider is UInitializable {\n error NotOwnerError(uint256 coordinatorId);\n error NotProductError(IProduct product);\n error NotCollateralError();\n error PausedError();\n error InvalidControllerError();\n error NotAccountOrMultiInvokerError(address account, address operator);\n\n /// @dev The controller contract address\n AddressStorage private constant _controller = AddressStorage.wrap(keccak256(\"equilibria.perennial.UControllerProvider.controller\"));\n function controller() public view returns (IController) { return IController(_controller.read()); }\n\n /**\n * @notice Initializes the contract state\n * @param controller_ Protocol Controller contract address\n */\n // solhint-disable-next-line func-name-mixedcase\n function __UControllerProvider__initialize(IController controller_) internal onlyInitializer {\n if (!Address.isContract(address(controller_))) revert InvalidControllerError();\n _controller.store(address(controller_));\n }\n\n /// @dev Only allow a valid product contract to call\n modifier onlyProduct {\n if (!controller().isProduct(IProduct(msg.sender))) revert NotProductError(IProduct(msg.sender));\n\n _;\n }\n\n /// @dev Verify that `product` is a valid product contract\n modifier isProduct(IProduct product) {\n if (!controller().isProduct(product)) revert NotProductError(product);\n\n _;\n }\n\n /// @dev Only allow the Collateral contract to call\n modifier onlyCollateral {\n if (msg.sender != address(controller().collateral())) revert NotCollateralError();\n\n _;\n }\n\n /// @dev Only allow the coordinator owner to call\n modifier onlyOwner(uint256 coordinatorId) {\n if (msg.sender != controller().owner(coordinatorId)) revert NotOwnerError(coordinatorId);\n\n _;\n }\n\n /// @dev Only allow if the protocol is currently unpaused\n modifier notPaused() {\n if (controller().paused()) revert PausedError();\n\n _;\n }\n\n /// @dev Ensure the `msg.sender` is ether the `account` or the Controller's multiInvoker\n modifier onlyAccountOrMultiInvoker(address account) {\n if (!(msg.sender == account || msg.sender == address(controller().multiInvoker()))) {\n revert NotAccountOrMultiInvokerError(account, msg.sender);\n }\n _;\n }\n}\n" + }, + "contracts/interfaces/ICollateral.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/root/number/types/Fixed18.sol\";\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"./IController.sol\";\nimport \"./IProduct.sol\";\n\ninterface ICollateral {\n event Deposit(address indexed user, IProduct indexed product, UFixed18 amount);\n event Withdrawal(address indexed user, IProduct indexed product, UFixed18 amount);\n event AccountSettle(IProduct indexed product, address indexed account, Fixed18 amount, UFixed18 newShortfall);\n event ProductSettle(IProduct indexed product, UFixed18 protocolFee, UFixed18 productFee);\n event Liquidation(address indexed user, IProduct indexed product, address liquidator, UFixed18 fee);\n event ShortfallResolution(IProduct indexed product, UFixed18 amount);\n event FeeClaim(address indexed account, UFixed18 amount);\n\n error CollateralCantLiquidate(UFixed18 totalMaintenance, UFixed18 totalCollateral);\n error CollateralInsufficientCollateralError();\n error CollateralUnderLimitError();\n error CollateralZeroAddressError();\n error CollateralAccountLiquidatingError(address account);\n\n function token() external view returns (Token18);\n function fees(address account) external view returns (UFixed18);\n function initialize(IController controller_) external;\n function depositTo(address account, IProduct product, UFixed18 amount) external;\n function withdrawTo(address receiver, IProduct product, UFixed18 amount) external;\n function withdrawFrom(address account, address receiver, IProduct product, UFixed18 amount) external;\n function liquidate(address account, IProduct product) external;\n function settleAccount(address account, Fixed18 amount) external;\n function settleProduct(UFixed18 amount) external;\n function collateral(address account, IProduct product) external view returns (UFixed18);\n function collateral(IProduct product) external view returns (UFixed18);\n function shortfall(IProduct product) external view returns (UFixed18);\n function liquidatable(address account, IProduct product) external view returns (bool);\n function liquidatableNext(address account, IProduct product) external view returns (bool);\n function resolveShortfall(IProduct product, UFixed18 amount) external;\n function claimFee() external;\n}\n" + }, + "contracts/interfaces/IContractPayoffProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/Fixed18.sol\";\n\ninterface IContractPayoffProvider {\n function payoff(Fixed18 price) external view returns (Fixed18 payoff);\n}\n" + }, + "contracts/interfaces/IController.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\";\nimport \"./ICollateral.sol\";\nimport \"./IIncentivizer.sol\";\nimport \"./IProduct.sol\";\nimport \"./IMultiInvoker.sol\";\nimport \"./types/PayoffDefinition.sol\";\n\ninterface IController {\n /// @dev Coordinator of a one or many products\n struct Coordinator {\n /// @dev Pending owner of the product, can accept ownership\n address pendingOwner;\n\n /// @dev Owner of the product, allowed to update select parameters\n address owner;\n\n /// @dev Treasury of the product, collects fees\n address treasury;\n }\n\n event CollateralUpdated(ICollateral newCollateral);\n event IncentivizerUpdated(IIncentivizer newIncentivizer);\n event ProductBeaconUpdated(IBeacon newProductBeacon);\n event MultiInvokerUpdated(IMultiInvoker newMultiInvoker);\n event ProtocolFeeUpdated(UFixed18 newProtocolFee);\n event MinFundingFeeUpdated(UFixed18 newMinFundingFee);\n event LiquidationFeeUpdated(UFixed18 newLiquidationFee);\n event IncentivizationFeeUpdated(UFixed18 newIncentivizationFee);\n event MinCollateralUpdated(UFixed18 newMinCollateral);\n event ProgramsPerProductUpdated(uint256 newProgramsPerProduct);\n event PauserUpdated(address newPauser);\n event PausedUpdated(bool newPaused);\n event CoordinatorPendingOwnerUpdated(uint256 indexed coordinatorId, address newPendingOwner);\n event CoordinatorOwnerUpdated(uint256 indexed coordinatorId, address newOwner);\n event CoordinatorTreasuryUpdated(uint256 indexed coordinatorId, address newTreasury);\n event CoordinatorCreated(uint256 indexed coordinatorId, address owner);\n event ProductCreated(IProduct indexed product, IProduct.ProductInfo productInfo);\n\n error ControllerNoZeroCoordinatorError();\n error ControllerNotPauserError();\n error ControllerNotOwnerError(uint256 controllerId);\n error ControllerNotPendingOwnerError(uint256 controllerId);\n error ControllerInvalidProtocolFeeError();\n error ControllerInvalidMinFundingFeeError();\n error ControllerInvalidLiquidationFeeError();\n error ControllerInvalidIncentivizationFeeError();\n error ControllerNotContractAddressError();\n\n function collateral() external view returns (ICollateral);\n function incentivizer() external view returns (IIncentivizer);\n function productBeacon() external view returns (IBeacon);\n function multiInvoker() external view returns (IMultiInvoker);\n function coordinators(uint256 collateralId) external view returns (Coordinator memory);\n function coordinatorFor(IProduct product) external view returns (uint256);\n function protocolFee() external view returns (UFixed18);\n function minFundingFee() external view returns (UFixed18);\n function liquidationFee() external view returns (UFixed18);\n function incentivizationFee() external view returns (UFixed18);\n function minCollateral() external view returns (UFixed18);\n function programsPerProduct() external view returns (uint256);\n function pauser() external view returns (address);\n function paused() external view returns (bool);\n function initialize(ICollateral collateral_, IIncentivizer incentivizer_, IBeacon productBeacon_) external;\n function createCoordinator() external returns (uint256);\n function updateCoordinatorPendingOwner(uint256 coordinatorId, address newPendingOwner) external;\n function acceptCoordinatorOwner(uint256 coordinatorId) external;\n function updateCoordinatorTreasury(uint256 coordinatorId, address newTreasury) external;\n function createProduct(uint256 coordinatorId, IProduct.ProductInfo calldata productInfo) external returns (IProduct);\n function updateCollateral(ICollateral newCollateral) external;\n function updateIncentivizer(IIncentivizer newIncentivizer) external;\n function updateProductBeacon(IBeacon newProductBeacon) external;\n function updateMultiInvoker(IMultiInvoker newMultiInvoker) external;\n function updateProtocolFee(UFixed18 newProtocolFee) external;\n function updateMinFundingFee(UFixed18 newMinFundingFee) external;\n function updateLiquidationFee(UFixed18 newLiquidationFee) external;\n function updateIncentivizationFee(UFixed18 newIncentivizationFee) external;\n function updateMinCollateral(UFixed18 newMinCollateral) external;\n function updateProgramsPerProduct(uint256 newProductsPerProduct) external;\n function updatePauser(address newPauser) external;\n function updatePaused(bool newPaused) external;\n function isProduct(IProduct product) external view returns (bool);\n function owner() external view returns (address);\n function owner(uint256 coordinatorId) external view returns (address);\n function owner(IProduct product) external view returns (address);\n function treasury() external view returns (address);\n function treasury(uint256 coordinatorId) external view returns (address);\n function treasury(IProduct product) external view returns (address);\n}\n" + }, + "contracts/interfaces/IIncentivizer.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\";\nimport \"./types/ProgramInfo.sol\";\nimport \"./IController.sol\";\nimport \"./IProduct.sol\";\n\ninterface IIncentivizer {\n event ProgramCreated(IProduct indexed product, uint256 indexed programId, ProgramInfo programInfo, UFixed18 programFeeAmount);\n event ProgramStarted(IProduct indexed product, uint256 indexed programId, uint256 version);\n event ProgramComplete(IProduct indexed product, uint256 indexed programId, uint256 version);\n event Claim(IProduct indexed product, address indexed account, uint256 indexed programId, UFixed18 amount);\n event FeeClaim(Token18 indexed token, UFixed18 amount);\n\n error IncentivizerNotAllowedError(IProduct product);\n error IncentivizerTooManyProgramsError();\n error IncentivizerNotProgramOwnerError(IProduct product, uint256 programId);\n error IncentivizerInvalidProgramError(IProduct product, uint256 programId);\n error IncentivizerBatchClaimArgumentMismatchError();\n\n function programInfos(IProduct product, uint256 programId) external view returns (ProgramInfo memory);\n function fees(Token18 token) external view returns (UFixed18);\n function initialize(IController controller_) external;\n function create(IProduct product, ProgramInfo calldata info) external returns (uint256);\n function complete(IProduct product, uint256 programId) external;\n function sync(IOracleProvider.OracleVersion memory currentOracleVersion) external;\n function syncAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) external;\n function claim(IProduct product, uint256[] calldata programIds) external;\n function claimFor(address account, IProduct product, uint256[] calldata programIds) external;\n function claim(IProduct[] calldata products, uint256[][] calldata programIds) external;\n function claimFee(Token18[] calldata tokens) external;\n function active(IProduct product) external view returns (uint256);\n function count(IProduct product) external view returns (uint256);\n function unclaimed(IProduct product, address account, uint256 programId) external view returns (UFixed18);\n function available(IProduct product, uint256 programId) external view returns (UFixed18);\n function versionStarted(IProduct product, uint256 programId) external view returns (uint256);\n function versionComplete(IProduct product, uint256 programId) external view returns (uint256);\n function owner(IProduct product, uint256 programId) external view returns (address);\n function treasury(IProduct product, uint256 programId) external view returns (address);\n}\n" + }, + "contracts/interfaces/IMultiInvoker.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/token/types/Token6.sol\";\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"@equilibria/emptyset-batcher/interfaces/IBatcher.sol\";\nimport \"@equilibria/emptyset-batcher/interfaces/IEmptySetReserve.sol\";\n\nimport \"./IController.sol\";\nimport \"./ICollateral.sol\";\nimport \"./IProduct.sol\";\n\ninterface IPerennialVault {\n event Deposit(address indexed sender, address indexed account, uint256 version, UFixed18 assets);\n event Redemption(address indexed sender, address indexed account, uint256 version, UFixed18 shares);\n event Claim(address indexed sender, address indexed account, UFixed18 assets);\n\n function deposit(UFixed18 assets, address account) external;\n function redeem(UFixed18 shares, address account) external;\n function claim(address account) external;\n}\n\ninterface IMultiInvoker {\n /// @dev Core protocol actions that can be composed\n enum PerennialAction {\n NO_OP,\n DEPOSIT,\n WITHDRAW,\n OPEN_TAKE,\n CLOSE_TAKE,\n OPEN_MAKE,\n CLOSE_MAKE,\n CLAIM,\n WRAP,\n UNWRAP,\n WRAP_AND_DEPOSIT,\n WITHDRAW_AND_UNWRAP,\n VAULT_DEPOSIT,\n VAULT_REDEEM,\n VAULT_CLAIM,\n VAULT_WRAP_AND_DEPOSIT\n }\n\n /// @dev Struct for action invocation\n struct Invocation {\n PerennialAction action;\n bytes args;\n }\n\n function initialize() external;\n function USDC() external view returns (Token6); // solhint-disable-line func-name-mixedcase\n function DSU() external view returns (Token18); // solhint-disable-line func-name-mixedcase\n function batcher() external view returns (IBatcher);\n function controller() external view returns (IController);\n function collateral() external view returns (ICollateral);\n function reserve() external view returns (IEmptySetReserve);\n function invoke(Invocation[] calldata invocations) external;\n}\n" + }, + "contracts/interfaces/IParamProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\";\nimport \"./types/PendingFeeUpdates.sol\";\n\ninterface IParamProvider {\n event MaintenanceUpdated(UFixed18 newMaintenance, uint256 version);\n event FundingFeeUpdated(UFixed18 newFundingFee, uint256 version);\n event MakerFeeUpdated(UFixed18 newMakerFee, uint256 version);\n event PendingMakerFeeUpdated(UFixed18 newMakerFee);\n event TakerFeeUpdated(UFixed18 newTakerFee, uint256 version);\n event PendingTakerFeeUpdated(UFixed18 newTakerFee);\n event PositionFeeUpdated(UFixed18 newPositionFee, uint256 version);\n event PendingPositionFeeUpdated(UFixed18 newPositionFee);\n event MakerLimitUpdated(UFixed18 newMakerLimit, uint256 version);\n event JumpRateUtilizationCurveUpdated(\n JumpRateUtilizationCurve,\n uint256 version\n );\n\n error ParamProviderInvalidParamValue();\n\n function maintenance() external view returns (UFixed18);\n function updateMaintenance(UFixed18 newMaintenance) external;\n function fundingFee() external view returns (UFixed18);\n function updateFundingFee(UFixed18 newFundingFee) external;\n function makerFee() external view returns (UFixed18);\n function updateMakerFee(UFixed18 newMakerFee) external;\n function takerFee() external view returns (UFixed18);\n function updateTakerFee(UFixed18 newTakerFee) external;\n function positionFee() external view returns (UFixed18);\n function updatePositionFee(UFixed18 newPositionFee) external;\n function makerLimit() external view returns (UFixed18);\n function updateMakerLimit(UFixed18 newMakerLimit) external;\n function utilizationCurve() external view returns (JumpRateUtilizationCurve memory);\n function updateUtilizationCurve(JumpRateUtilizationCurve memory newUtilizationCurve) external;\n function pendingFeeUpdates() external view returns (PendingFeeUpdates memory);\n}\n" + }, + "contracts/interfaces/IPayoffProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/Fixed18.sol\";\nimport \"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\";\nimport \"./types/PayoffDefinition.sol\";\n\ninterface IPayoffProvider {\n event OracleUpdated(address newOracle, uint256 oracleVersion);\n\n error PayoffProviderInvalidOracle();\n error PayoffProviderInvalidPayoffDefinitionError();\n\n function oracle() external view returns (IOracleProvider);\n function payoffDefinition() external view returns (PayoffDefinition memory);\n function currentVersion() external view returns (IOracleProvider.OracleVersion memory);\n function atVersion(uint256 oracleVersion) external view returns (IOracleProvider.OracleVersion memory);\n}\n" + }, + "contracts/interfaces/IProduct.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/root/curve/types/JumpRateUtilizationCurve.sol\";\nimport \"./IPayoffProvider.sol\";\nimport \"./IParamProvider.sol\";\nimport \"./types/PayoffDefinition.sol\";\nimport \"./types/Position.sol\";\nimport \"./types/PrePosition.sol\";\nimport \"./types/Accumulator.sol\";\n\ninterface IProduct is IPayoffProvider, IParamProvider {\n /// @dev Product Creation parameters\n struct ProductInfo {\n /// @dev name of the product\n string name;\n\n /// @dev symbol of the product\n string symbol;\n\n /// @dev product payoff definition\n PayoffDefinition payoffDefinition;\n\n /// @dev oracle address\n IOracleProvider oracle;\n\n /// @dev product maintenance ratio\n UFixed18 maintenance;\n\n /// @dev product funding fee\n UFixed18 fundingFee;\n\n /// @dev product maker fee\n UFixed18 makerFee;\n\n /// @dev product taker fee\n UFixed18 takerFee;\n\n /// @dev product position fee share\n UFixed18 positionFee;\n\n /// @dev product maker limit\n UFixed18 makerLimit;\n\n /// @dev utulization curve definition\n JumpRateUtilizationCurve utilizationCurve;\n }\n\n event Settle(uint256 preVersion, uint256 toVersion);\n event AccountSettle(address indexed account, uint256 preVersion, uint256 toVersion);\n event MakeOpened(address indexed account, uint256 version, UFixed18 amount);\n event TakeOpened(address indexed account, uint256 version, UFixed18 amount);\n event MakeClosed(address indexed account, uint256 version, UFixed18 amount);\n event TakeClosed(address indexed account, uint256 version, UFixed18 amount);\n event ClosedUpdated(bool indexed newClosed, uint256 version);\n\n error ProductInsufficientLiquidityError(UFixed18 socializationFactor);\n error ProductDoubleSidedError();\n error ProductOverClosedError();\n error ProductInsufficientCollateralError();\n error ProductInLiquidationError();\n error ProductMakerOverLimitError();\n error ProductOracleBootstrappingError();\n error ProductClosedError();\n\n function name() external view returns (string memory);\n function symbol() external view returns (string memory);\n function initialize(ProductInfo calldata productInfo_) external;\n function settle() external;\n function settleAccount(address account) external;\n function openTake(UFixed18 amount) external;\n function openTakeFor(address account, UFixed18 amount) external;\n function closeTake(UFixed18 amount) external;\n function closeTakeFor(address account, UFixed18 amount) external;\n function openMake(UFixed18 amount) external;\n function openMakeFor(address account, UFixed18 amount) external;\n function closeMake(UFixed18 amount) external;\n function closeMakeFor(address account, UFixed18 amount) external;\n function closeAll(address account) external;\n function maintenance(address account) external view returns (UFixed18);\n function maintenanceNext(address account) external view returns (UFixed18);\n function isClosed(address account) external view returns (bool);\n function isLiquidating(address account) external view returns (bool);\n function position(address account) external view returns (Position memory);\n function pre(address account) external view returns (PrePosition memory);\n function latestVersion() external view returns (uint256);\n function positionAtVersion(uint256 oracleVersion) external view returns (Position memory);\n function pre() external view returns (PrePosition memory);\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory);\n function latestVersion(address account) external view returns (uint256);\n function rate(Position memory position) external view returns (Fixed18);\n function closed() external view returns (bool);\n function updateClosed(bool newClosed) external;\n function updateOracle(IOracleProvider newOracle) external;\n}\n" + }, + "contracts/interfaces/types/Accumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/Fixed18.sol\";\nimport \"./PackedAccumulator.sol\";\n\n/// @dev Accumulator type\nstruct Accumulator {\n /// @dev maker accumulator per share\n Fixed18 maker;\n /// @dev taker accumulator per share\n Fixed18 taker;\n}\nusing AccumulatorLib for Accumulator global;\n\n/**\n * @title AccountAccumulatorLib\n * @notice Library that surfaces math operations for the Accumulator type.\n * @dev Accumulators track the cumulative change in position value over time for the maker and taker positions\n * respectively. Account-level accumulators can then use two of these values `a` and `a'` to compute the\n * change in position value since last sync. This change in value is then used to compute P&L and fees.\n */\nlibrary AccumulatorLib {\n /**\n * @notice Creates a packed accumulator from an accumulator\n * @param self an accumulator\n * @return New packed accumulator\n */\n function pack(Accumulator memory self) internal pure returns (PackedAccumulator memory) {\n return PackedAccumulator({maker: self.maker.pack(), taker: self.taker.pack()});\n }\n\n /**\n * @notice Adds two accumulators together\n * @param a The first accumulator to sum\n * @param b The second accumulator to sum\n * @return The resulting summed accumulator\n */\n function add(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\n return Accumulator({maker: a.maker.add(b.maker), taker: a.taker.add(b.taker)});\n }\n\n /**\n * @notice Subtracts accumulator `b` from `a`\n * @param a The accumulator to subtract from\n * @param b The accumulator to subtract\n * @return The resulting subtracted accumulator\n */\n function sub(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\n return Accumulator({maker: a.maker.sub(b.maker), taker: a.taker.sub(b.taker)});\n }\n\n /**\n * @notice Multiplies two accumulators together\n * @param a The first accumulator to multiply\n * @param b The second accumulator to multiply\n * @return The resulting multiplied accumulator\n */\n function mul(Accumulator memory a, Accumulator memory b) internal pure returns (Accumulator memory) {\n return Accumulator({maker: a.maker.mul(b.maker), taker: a.taker.mul(b.taker)});\n }\n\n /**\n * @notice Sums the maker and taker together from a single accumulator\n * @param self The struct to operate on\n * @return The sum of its maker and taker\n */\n function sum(Accumulator memory self) internal pure returns (Fixed18) {\n return self.maker.add(self.taker);\n }\n}\n" + }, + "contracts/interfaces/types/PackedAccumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/PackedFixed18.sol\";\nimport \"./Accumulator.sol\";\n\n/// @dev PackedAccumulator type\nstruct PackedAccumulator {\n /// @dev maker accumulator per share\n PackedFixed18 maker;\n /// @dev taker accumulator per share\n PackedFixed18 taker;\n}\nusing PackedAccumulatorLib for PackedAccumulator global;\n\n/**\n * @title PackedAccumulatorLib\n * @dev A packed version of the Accumulator which takes up a single storage slot using `PackedFixed18` values.\n * @notice Library for the packed Accumulator type.\n */\nlibrary PackedAccumulatorLib {\n /**\n * @notice Creates an accumulator from a packed accumulator\n * @param self packed accumulator\n * @return New accumulator\n */\n function unpack(PackedAccumulator memory self) internal pure returns (Accumulator memory) {\n return Accumulator({maker: self.maker.unpack(), taker: self.taker.unpack()});\n }\n}\n" + }, + "contracts/interfaces/types/PackedPosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/PackedUFixed18.sol\";\nimport \"./Position.sol\";\n\n/// @dev PackedPosition type\nstruct PackedPosition {\n /// @dev Quantity of the maker position\n PackedUFixed18 maker;\n /// @dev Quantity of the taker position\n PackedUFixed18 taker;\n}\nusing PackedPositionLib for PackedPosition global;\n\n/**\n * @title PackedPositionLib\n * @dev A packed version of the Position which takes up a single storage slot using `PackedFixed18` values.\n * @notice Library for the packed Position type.\n */\nlibrary PackedPositionLib {\n /**\n * @notice Creates an position from a packed position\n * @param self packed position\n * @return New position\n */\n function unpack(PackedPosition memory self) internal pure returns (Position memory) {\n return Position({maker: self.maker.unpack(), taker: self.taker.unpack()});\n }\n}\n" + }, + "contracts/interfaces/types/PayoffDefinition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../../interfaces/IContractPayoffProvider.sol\";\n\n/// @dev PayoffDefinition tyoe\nstruct PayoffDefinition {\n PayoffDefinitionLib.PayoffType payoffType;\n PayoffDefinitionLib.PayoffDirection payoffDirection;\n bytes30 data;\n}\nusing PayoffDefinitionLib for PayoffDefinition global;\ntype PayoffDefinitionStorage is bytes32;\nusing PayoffDefinitionStorageLib for PayoffDefinitionStorage global;\n\n/**\n * @title PayoffDefinitionLib\n * @dev Library that surfaces logic for PayoffDefinition type functionality\n * @notice Library for the PayoffDefinition type. Performs validity and price transformation\n based on the payoff definition type.\n */\nlibrary PayoffDefinitionLib {\n using Address for address;\n\n error PayoffDefinitionUnsupportedTransform(PayoffType payoffType, PayoffDirection payoffDirection);\n error PayoffDefinitionNotContract(PayoffType payoffType, bytes30 data);\n\n /// @dev Payoff function type enum\n enum PayoffType { PASSTHROUGH, CONTRACT }\n enum PayoffDirection { LONG, SHORT }\n\n /**\n * @notice Checks validity of the payoff definition\n * @param self a payoff definition\n * @return Whether the payoff definition is valid for it's given type\n */\n function valid(PayoffDefinition memory self) internal view returns (bool) {\n if (self.payoffType == PayoffType.CONTRACT) return address(_providerContract(self)).isContract();\n\n // All other payoff types should have no data\n return uint(bytes32(self.data)) == 0;\n }\n\n /**\n * @notice Transforms a price based on the payoff definition\n * @param self a payoff definition\n * @param price raw oracle price\n * @return Price transformed by the payoff definition function\n */\n function transform(\n PayoffDefinition memory self,\n Fixed18 price\n ) internal view returns (Fixed18) {\n PayoffType payoffType = self.payoffType;\n PayoffDirection payoffDirection = self.payoffDirection;\n Fixed18 transformedPrice;\n\n // First get the price depending on the type\n if (payoffType == PayoffType.PASSTHROUGH) transformedPrice = price;\n else if (payoffType == PayoffType.CONTRACT) transformedPrice = _payoffFromContract(self, price);\n else revert PayoffDefinitionUnsupportedTransform(payoffType, payoffDirection);\n\n // Then transform it depending on the direction flag\n if (self.payoffDirection == PayoffDirection.LONG) return transformedPrice;\n else if (self.payoffDirection == PayoffDirection.SHORT) return transformedPrice.mul(Fixed18Lib.NEG_ONE);\n else revert PayoffDefinitionUnsupportedTransform(payoffType, payoffDirection);\n }\n\n /**\n * @notice Parses the data field into an address\n * @dev Reverts if payoffType is not CONTRACT\n * @param self a payoff definition\n * @return IContractPayoffProvider address\n */\n function _providerContract(\n PayoffDefinition memory self\n ) private pure returns (IContractPayoffProvider) {\n if (self.payoffType != PayoffType.CONTRACT) revert PayoffDefinitionNotContract(self.payoffType, self.data);\n // Shift to pull the last 20 bytes, then cast to an address\n return IContractPayoffProvider(address(bytes20(self.data << 80)));\n }\n\n /**\n * @notice Performs a price transformation by calling the underlying payoff contract\n * @param self a payoff definition\n * @param price raw oracle price\n * @return Price transformed by the payoff definition function on the contract\n */\n function _payoffFromContract(\n PayoffDefinition memory self,\n Fixed18 price\n ) private view returns (Fixed18) {\n bytes memory ret = address(_providerContract(self)).functionStaticCall(\n abi.encodeCall(IContractPayoffProvider.payoff, price)\n );\n return Fixed18.wrap(abi.decode(ret, (int256)));\n }\n}\n\n/**\n * @title PayoffDefinitionStorageLib\n * @notice Library that surfaces storage read and writes for the PayoffDefinition type\n */\nlibrary PayoffDefinitionStorageLib {\n function read(PayoffDefinitionStorage self) internal view returns (PayoffDefinition memory) {\n return _storagePointer(self);\n }\n\n function store(PayoffDefinitionStorage self, PayoffDefinition memory value) internal {\n PayoffDefinition storage storagePointer = _storagePointer(self);\n\n storagePointer.payoffType = value.payoffType;\n storagePointer.payoffDirection = value.payoffDirection;\n storagePointer.data = value.data;\n }\n\n function _storagePointer(\n PayoffDefinitionStorage self\n ) private pure returns (PayoffDefinition storage pointer) {\n assembly { pointer.slot := self } // solhint-disable-line no-inline-assembly\n }\n}\n" + }, + "contracts/interfaces/types/PendingFeeUpdates.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\n\n/// @dev PendingFeeUpdates type. Fees can be between 0 and 1 ** 10^18, so uint64 is sufficient\nstruct PendingFeeUpdates {\n bool makerFeeUpdated;\n uint64 pendingMakerFee;\n bool takerFeeUpdated;\n uint64 pendingTakerFee;\n bool positionFeeUpdated;\n uint64 pendingPositionFee;\n}\nusing PendingFeeUpdatesLib for PendingFeeUpdates global;\ntype PendingFeeUpdatesStorage is bytes32;\nusing PendingFeeUpdatesStorageLib for PendingFeeUpdatesStorage global;\n\n/**\n * @title PendingFeeUpdatesLib\n * @dev Library that surfaces convenience functions for the PendingFeeUpdates type\n * @notice Library for the PendingFeeUpdates type. Allows for setting and reading fee updates and clearing state\n */\nlibrary PendingFeeUpdatesLib {\n error PendingFeeUpdatesUnsupportedValue(UFixed18 value);\n\n /**\n * @notice Updates the pending maker fee to `newMakerFee` and sets the `makerFeeUpdated` flag\n * @dev Reverts if `newMakerFee` is invalid\n * @param self PendingFeeUpdates struct\n * @param newMakerFee new maker fee value\n */\n function updateMakerFee(PendingFeeUpdates memory self, UFixed18 newMakerFee) internal pure {\n if (UFixed18.unwrap(newMakerFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newMakerFee);\n self.pendingMakerFee = uint64(UFixed18.unwrap(newMakerFee));\n self.makerFeeUpdated = true;\n }\n\n /// @dev Returns the UFixed18-wrapped pending maker fee\n function makerFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\n return UFixed18.wrap(uint256(self.pendingMakerFee));\n }\n\n /**\n * @notice Updates the pending taker fee to `newTakerFee` and sets the `takerFeeUpdated` flag\n * @dev Reverts if `newTakerFee` is invalid\n * @param self PendingFeeUpdates struct\n * @param newTakerFee new taker fee value\n */\n function updateTakerFee(PendingFeeUpdates memory self, UFixed18 newTakerFee) internal pure {\n if (UFixed18.unwrap(newTakerFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newTakerFee);\n self.pendingTakerFee = uint64(UFixed18.unwrap(newTakerFee));\n self.takerFeeUpdated = true;\n }\n\n /// @dev Returns the UFixed18-wrapped pending taker fee\n function takerFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\n return UFixed18.wrap(uint256(self.pendingTakerFee));\n }\n\n /**\n * @notice Updates the pending position fee to `newPositionFee` and sets the `positionFeeUpdated` flag\n * @dev Reverts if `newPositionFee` is invalid\n * @param self PendingFeeUpdates struct\n * @param newPositionFee new position fee value\n */\n function updatePositionFee(PendingFeeUpdates memory self, UFixed18 newPositionFee) internal pure {\n if (UFixed18.unwrap(newPositionFee) > type(uint64).max) revert PendingFeeUpdatesUnsupportedValue(newPositionFee);\n self.pendingPositionFee = uint64(UFixed18.unwrap(newPositionFee));\n self.positionFeeUpdated = true;\n }\n\n /// @dev Returns the UFixed18-wrapped pending position fee\n function positionFee(PendingFeeUpdates memory self) internal pure returns (UFixed18) {\n return UFixed18.wrap(uint256(self.pendingPositionFee));\n }\n\n /// @dev Returns true if any of the updated flags are true\n function hasUpdates(PendingFeeUpdates memory self) internal pure returns (bool) {\n return self.makerFeeUpdated || self.takerFeeUpdated || self.positionFeeUpdated;\n }\n\n /// @dev Resets all struct values to defaults\n function clear(PendingFeeUpdates memory self) internal pure {\n self.makerFeeUpdated = false;\n self.pendingMakerFee = 0;\n self.takerFeeUpdated = false;\n self.pendingTakerFee = 0;\n self.positionFeeUpdated = false;\n self.pendingPositionFee = 0;\n }\n}\n\n/**\n * @title PendingFeeUpdatesStorageLib\n * @notice Library that surfaces storage read and writes for the PendingFeeUpdates type\n */\nlibrary PendingFeeUpdatesStorageLib {\n struct PendingFeeUpdatesStoragePointer {\n PendingFeeUpdates value;\n }\n\n function read(PendingFeeUpdatesStorage self) internal view returns (PendingFeeUpdates memory) {\n return _storagePointer(self).value;\n }\n\n function store(PendingFeeUpdatesStorage self, PendingFeeUpdates memory value) internal {\n _storagePointer(self).value = value;\n }\n\n function _storagePointer(\n PendingFeeUpdatesStorage self\n ) private pure returns (PendingFeeUpdatesStoragePointer storage pointer) {\n /// @solidity memory-safe-assembly\n assembly { pointer.slot := self } // solhint-disable-line no-inline-assembly\n }\n}\n" + }, + "contracts/interfaces/types/Position.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"../IProduct.sol\";\nimport \"./Accumulator.sol\";\nimport \"./PrePosition.sol\";\nimport \"./PackedPosition.sol\";\n\n/// @dev Position type\nstruct Position {\n /// @dev Quantity of the maker position\n UFixed18 maker;\n /// @dev Quantity of the taker position\n UFixed18 taker;\n}\nusing PositionLib for Position global;\n\n/**\n * @title PositionLib\n * @notice Library that surfaces math and settlement computations for the Position type.\n * @dev Positions track the current quantity of the account's maker and taker positions respectively\n * denominated as a unit of the product's payoff function.\n */\nlibrary PositionLib {\n /**\n * @notice Creates a packed position from an position\n * @param self A position\n * @return New packed position\n */\n function pack(Position memory self) internal pure returns (PackedPosition memory) {\n return PackedPosition({maker: self.maker.pack(), taker: self.taker.pack()});\n }\n\n /**\n * @notice Returns whether the position is fully empty\n * @param self A position\n * @return Whether the position is empty\n */\n function isEmpty(Position memory self) internal pure returns (bool) {\n return self.maker.isZero() && self.taker.isZero();\n }\n\n /**\n * @notice Adds position `a` and `b` together, returning the result\n * @param a The first position to sum\n * @param b The second position to sum\n * @return Resulting summed position\n */\n function add(Position memory a, Position memory b) internal pure returns (Position memory) {\n return Position({maker: a.maker.add(b.maker), taker: a.taker.add(b.taker)});\n }\n\n /**\n * @notice Subtracts position `b` from `a`, returning the result\n * @param a The position to subtract from\n * @param b The position to subtract\n * @return Resulting subtracted position\n */\n function sub(Position memory a, Position memory b) internal pure returns (Position memory) {\n return Position({maker: a.maker.sub(b.maker), taker: a.taker.sub(b.taker)});\n }\n\n /**\n * @notice Multiplies position `self` by accumulator `accumulator` and returns the resulting accumulator\n * @param self The Position to operate on\n * @param accumulator The accumulator to multiply by\n * @return Resulting multiplied accumulator\n */\n function mul(Position memory self, Accumulator memory accumulator) internal pure returns (Accumulator memory) {\n return Accumulator({\n maker: Fixed18Lib.from(self.maker).mul(accumulator.maker),\n taker: Fixed18Lib.from(self.taker).mul(accumulator.taker)\n });\n }\n\n /**\n * @notice Scales position `self` by fixed-decimal `scale` and returns the resulting position\n * @param self The Position to operate on\n * @param scale The Fixed-decimal to scale by\n * @return Resulting scaled position\n */\n function mul(Position memory self, UFixed18 scale) internal pure returns (Position memory) {\n return Position({maker: self.maker.mul(scale), taker: self.taker.mul(scale)});\n }\n\n /**\n * @notice Divides position `self` by `b` and returns the resulting accumulator\n * @param self The Position to operate on\n * @param b The number to divide by\n * @return Resulting divided accumulator\n */\n function div(Position memory self, uint256 b) internal pure returns (Accumulator memory) {\n return Accumulator({\n maker: Fixed18Lib.from(self.maker).div(Fixed18Lib.from(UFixed18Lib.from(b))),\n taker: Fixed18Lib.from(self.taker).div(Fixed18Lib.from(UFixed18Lib.from(b)))\n });\n }\n\n /**\n * @notice Returns the maximum of `self`'s maker and taker values\n * @param self The struct to operate on\n * @return Resulting maximum value\n */\n function max(Position memory self) internal pure returns (UFixed18) {\n return UFixed18Lib.max(self.maker, self.taker);\n }\n\n /**\n * @notice Sums the maker and taker together from a single position\n * @param self The struct to operate on\n * @return The sum of its maker and taker\n */\n function sum(Position memory self) internal pure returns (UFixed18) {\n return self.maker.add(self.taker);\n }\n\n /**\n * @notice Computes the next position after the pending-settlement position delta is included\n * @param self The current Position\n * @param pre The pending-settlement position delta\n * @return Next Position\n */\n function next(Position memory self, PrePosition memory pre) internal pure returns (Position memory) {\n return sub(add(self, pre.openPosition), pre.closePosition);\n }\n\n /**\n * @notice Returns the settled position at oracle version `toOracleVersion`\n * @dev Checks if a new position is ready to be settled based on the provided `toOracleVersion`\n * and `pre` and returns accordingly\n * @param self The current Position\n * @param pre The pending-settlement position delta\n * @param toOracleVersion The oracle version to settle to\n * @return Settled position at oracle version\n * @return Whether a new position was settled\n */\n function settled(\n Position memory self,\n PrePosition memory pre,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal pure returns (Position memory, bool) {\n return pre.canSettle(toOracleVersion) ? (next(self, pre), true) : (self, false);\n }\n\n /**\n * @notice Returns the socialization factor for the current position\n * @dev Socialization account for the case where `taker` > `maker` temporarily due to a liquidation\n * on the maker side. This dampens the taker's exposure pro-rata to ensure that the maker side\n * is never exposed over 1 x short.\n * @param self The Position to operate on\n * @return Socialization factor\n */\n function socializationFactor(Position memory self) internal pure returns (UFixed18) {\n return self.taker.isZero() ? UFixed18Lib.ONE : UFixed18Lib.min(UFixed18Lib.ONE, self.maker.div(self.taker));\n }\n}\n" + }, + "contracts/interfaces/types/PrePosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/number/types/UFixed18.sol\";\nimport \"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\";\nimport \"./Position.sol\";\nimport \"../IProduct.sol\";\n\n/// @dev PrePosition type\nstruct PrePosition {\n /// @dev Oracle version at which the new position delta was recorded\n uint256 oracleVersion;\n\n /// @dev Size of position to open at oracle version\n Position openPosition;\n\n /// @dev Size of position to close at oracle version\n Position closePosition;\n}\nusing PrePositionLib for PrePosition global;\n\n/**\n * @title PrePositionLib\n * @notice Library that manages a pre-settlement position delta.\n * @dev PrePositions track the currently awaiting-settlement deltas to a settled Position. These are\n * Primarily necessary to introduce lag into the settlement system such that oracle lag cannot be\n * gamed to a user's advantage. When a user opens or closes a new position, it sits as a PrePosition\n * for one oracle version until it's settle into the Position, making it then effective. PrePositions\n * are automatically settled at the correct oracle version even if a flywheel call doesn't happen until\n * several version into the future by using the historical version lookups in the corresponding \"Versioned\"\n * global state types.\n */\nlibrary PrePositionLib {\n /**\n * @notice Returns whether there is no pending-settlement position delta\n * @param self The struct to operate on\n * @return Whether the pending-settlement position delta is empty\n */\n function isEmpty(PrePosition memory self) internal pure returns (bool) {\n return self.openPosition.isEmpty() && self.closePosition.isEmpty();\n }\n\n /**\n * @notice Increments the maker side of the open position delta\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The position amount to open\n */\n function openMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.openPosition.maker = self.openPosition.maker.add(amount);\n self.oracleVersion = currentVersion;\n }\n\n /**\n * @notice Increments the maker side of the close position delta\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The maker position amount to close\n */\n function closeMake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.closePosition.maker = self.closePosition.maker.add(amount);\n self.oracleVersion = currentVersion;\n }\n\n /**\n * @notice Increments the taker side of the open position delta\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The taker position amount to open\n */\n function openTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.openPosition.taker = self.openPosition.taker.add(amount);\n self.oracleVersion = currentVersion;\n }\n\n /**\n * @notice Increments the taker side of the close position delta\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @param amount The taker position amount to close\n */\n function closeTake(PrePosition storage self, uint256 currentVersion, UFixed18 amount) internal {\n self.closePosition.taker = self.closePosition.taker.add(amount);\n self.oracleVersion = currentVersion;\n }\n\n /**\n * @notice Returns whether the the pending position delta can be settled at version `toOracleVersion`\n * @dev Pending-settlement positions deltas can be settled (1) oracle version after they are recorded\n * @param self The struct to operate on\n * @param toOracleVersion The potential oracle version to settle\n * @return Whether the position delta can be settled\n */\n function canSettle(\n PrePosition memory self,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal pure returns (bool) {\n return self.oracleVersion != 0 && toOracleVersion.version > self.oracleVersion;\n }\n\n /**\n * @notice Computes the fee incurred for opening or closing the pending-settlement position\n * @dev Must be called from a valid product to get the proper fee amounts\n * @param self The struct to operate on\n * @param latestOracleVersion The oracle version at which position was modified\n * @return The maker / taker fee incurred\n */\n function computeFee(\n PrePosition memory self,\n IOracleProvider.OracleVersion memory latestOracleVersion\n ) internal view returns (Position memory) {\n Position memory positionDelta = self.openPosition.add(self.closePosition);\n\n (UFixed18 makerNotional, UFixed18 takerNotional) = (\n Fixed18Lib.from(positionDelta.maker).mul(latestOracleVersion.price).abs(),\n Fixed18Lib.from(positionDelta.taker).mul(latestOracleVersion.price).abs()\n );\n\n IProduct product = IProduct(address(this));\n return Position(makerNotional.mul(product.makerFee()), takerNotional.mul(product.takerFee()));\n }\n\n /**\n * @notice Computes the next oracle version to settle\n * @dev - If there is no pending-settlement position delta, returns the current oracle version\n * - Otherwise returns the oracle version at which the pending-settlement position delta can be first settled\n *\n * Corresponds to point (b) in the Position settlement flow\n * @param self The struct to operate on\n * @param currentVersion The current oracle version index\n * @return Next oracle version to settle\n */\n function settleVersion(PrePosition storage self, uint256 currentVersion) internal view returns (uint256) {\n uint256 _oracleVersion = self.oracleVersion;\n return _oracleVersion == 0 ? currentVersion : _oracleVersion + 1;\n }\n}\n" + }, + "contracts/interfaces/types/ProgramInfo.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/token/types/Token18.sol\";\nimport \"../IProduct.sol\";\nimport \"./Position.sol\";\nimport \"./Accumulator.sol\";\n\n/// @dev ProgramInfo type\nstruct ProgramInfo {\n /// @dev Coordinator for this program\n uint256 coordinatorId;\n\n /// @dev Amount of total maker and taker rewards\n Position amount;\n\n /// @dev start timestamp of the program\n uint256 start;\n\n /// @dev duration of the program (in seconds)\n uint256 duration;\n\n /**\n * @dev Reward ERC20 token contract\n * @notice Perennial does not support non-standard ERC20s as reward tokens for incentive programs, including,\n but not limited to: fee on transfer and rebase tokens. Using such a non-standard token will likely\n result in loss of funds.\n */\n Token18 token;\n}\nusing ProgramInfoLib for ProgramInfo global;\n\n/**\n * @title ProgramInfoLib\n * @notice Library that snapshots the static information for a single program.\n * @dev This information does not change during the operation of a program.\n */\nlibrary ProgramInfoLib {\n uint256 private constant MIN_DURATION = 1 days;\n uint256 private constant MAX_DURATION = 2 * 365 days;\n\n error ProgramInvalidStartError();\n error ProgramInvalidDurationError();\n\n /**\n * @notice Validates and creates a new Program\n * @dev Reverts for invalid programInfos\n * @param programInfo Un-sanitized static program information\n */\n function validate(ProgramInfo memory programInfo) internal view {\n if (isStarted(programInfo, block.timestamp)) revert ProgramInvalidStartError();\n if (programInfo.duration < MIN_DURATION || programInfo.duration > MAX_DURATION) revert ProgramInvalidDurationError();\n }\n\n /**\n * @notice Computes a new program info with the fee taken out of the amount\n * @param programInfo Original program info\n * @param incentivizationFee The incentivization fee\n * @return New program info\n * @return Fee amount\n */\n function deductFee(ProgramInfo memory programInfo, UFixed18 incentivizationFee)\n internal pure returns (ProgramInfo memory, UFixed18) {\n Position memory newProgramAmount = programInfo.amount.mul(UFixed18Lib.ONE.sub(incentivizationFee));\n UFixed18 programFeeAmount = programInfo.amount.sub(newProgramAmount).sum();\n programInfo.amount = newProgramAmount;\n return (programInfo, programFeeAmount);\n }\n\n /**\n * @notice Returns the maker and taker amounts per position share\n * @param self The ProgramInfo to operate on\n * @return programFee Amounts per share\n */\n function amountPerShare(ProgramInfo memory self) internal pure returns (Accumulator memory) {\n return self.amount.div(self.duration);\n }\n\n /**\n * @notice Returns whether the program has started by timestamp `timestamp`\n * @param self The ProgramInfo to operate on\n * @param timestamp Timestamp to check for\n * @return Whether the program has started\n */\n function isStarted(ProgramInfo memory self, uint256 timestamp) internal pure returns (bool) {\n return timestamp >= self.start;\n }\n\n /**\n * @notice Returns whether the program is completed by timestamp `timestamp`\n * @param self The ProgramInfo to operate on\n * @param timestamp Timestamp to check for\n * @return Whether the program is completed\n */\n function isComplete(ProgramInfo memory self, uint256 timestamp) internal pure returns (bool) {\n return timestamp >= (self.start + self.duration);\n }\n}\n" + }, + "contracts/product/Product.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.17;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/root/control/unstructured/UReentrancyGuard.sol\";\nimport \"../controller/UControllerProvider.sol\";\nimport \"./UPayoffProvider.sol\";\nimport \"./UParamProvider.sol\";\nimport \"./types/position/AccountPosition.sol\";\nimport \"./types/accumulator/AccountAccumulator.sol\";\n\n/**\n * @title Product\n * @notice Manages logic and state for a single product market.\n * @dev Cloned by the Controller contract to launch new product markets.\n */\ncontract Product is IProduct, UInitializable, UParamProvider, UPayoffProvider, UReentrancyGuard {\n /// @dev Whether or not the product is closed\n BoolStorage private constant _closed = BoolStorage.wrap(keccak256(\"equilibria.perennial.Product.closed\"));\n\n function closed() public view returns (bool) {\n return _closed.read();\n }\n\n /// @dev The name of the product\n string public name;\n\n /// @dev The symbol of the product\n string public symbol;\n\n /// @dev The individual position state for each account\n mapping(address => AccountPosition) private _positions;\n\n /// @dev The global position state for the product\n VersionedPosition private _position;\n\n /// @dev The individual accumulator state for each account\n mapping(address => AccountAccumulator) private _accumulators;\n\n /// @dev The global accumulator state for the product\n VersionedAccumulator private _accumulator;\n\n /**\n * @notice Initializes the contract state\n * @param productInfo_ Product initialization params\n */\n function initialize(ProductInfo calldata productInfo_) external initializer(1) {\n __UControllerProvider__initialize(IController(msg.sender));\n __UPayoffProvider__initialize(productInfo_.oracle, productInfo_.payoffDefinition);\n __UReentrancyGuard__initialize();\n __UParamProvider__initialize(\n productInfo_.maintenance,\n productInfo_.fundingFee,\n productInfo_.makerFee,\n productInfo_.takerFee,\n productInfo_.positionFee,\n productInfo_.makerLimit,\n productInfo_.utilizationCurve\n );\n\n name = productInfo_.name;\n symbol = productInfo_.symbol;\n }\n\n /**\n * @notice Surfaces global settlement externally\n */\n function settle() external nonReentrant notPaused {\n _settle();\n }\n\n /**\n * @notice Core global settlement flywheel\n * @dev\n * a) last settle oracle version\n * b) latest pre position oracle version\n * c) current oracle version\n *\n * Settles from a->b then from b->c if either interval is non-zero to account for a change\n * in position quantity at (b).\n *\n * Syncs each to instantaneously after the oracle update.\n */\n function _settle() private returns (IOracleProvider.OracleVersion memory currentOracleVersion) {\n IController _controller = controller();\n\n // Get current oracle version\n currentOracleVersion = _sync();\n\n // Get latest oracle version\n uint256 _latestVersion = latestVersion();\n if (_latestVersion == currentOracleVersion.version) return currentOracleVersion; // short circuit entirely if a == c\n IOracleProvider.OracleVersion memory latestOracleVersion = atVersion(_latestVersion);\n\n // Get settle oracle version\n uint256 _settleVersion = _position.pre.settleVersion(currentOracleVersion.version);\n IOracleProvider.OracleVersion memory settleOracleVersion = _settleVersion == currentOracleVersion.version\n ? currentOracleVersion // if b == c, don't re-call provider for oracle version\n : atVersion(_settleVersion);\n\n // Initiate\n _controller.incentivizer().sync(currentOracleVersion);\n UFixed18 boundedFundingFee = _boundedFundingFee();\n\n // value a->b\n UFixed18 accumulatedFee = _accumulator.accumulate(\n boundedFundingFee, _position, latestOracleVersion, settleOracleVersion);\n\n // position a->b\n _position.settle(_latestVersion, settleOracleVersion);\n\n // Apply any pending fee updates if present\n _settleFeeUpdates();\n\n // short-circuit from a->c if b == c\n if (settleOracleVersion.version != currentOracleVersion.version) {\n // value b->c\n accumulatedFee = accumulatedFee.add(\n _accumulator.accumulate(boundedFundingFee, _position, settleOracleVersion, currentOracleVersion)\n );\n\n // position b->c (every accumulator version needs a position stamp)\n _position.settle(settleOracleVersion.version, currentOracleVersion);\n }\n\n // settle collateral\n _controller.collateral().settleProduct(accumulatedFee);\n\n emit Settle(settleOracleVersion.version, currentOracleVersion.version);\n }\n\n /**\n * @notice Surfaces account settlement externally\n * @param account Account to settle\n */\n function settleAccount(address account) external nonReentrant notPaused {\n IOracleProvider.OracleVersion memory currentOracleVersion = _settle();\n _settleAccount(account, currentOracleVersion);\n }\n\n /**\n * @notice Core account settlement flywheel\n * @param account Account to settle\n * @dev\n * a) last settle oracle version\n * b) latest pre position oracle version\n * c) current oracle version\n *\n * Settles from a->b then from b->c if either interval is non-zero to account for a change\n * in position quantity at (b).\n *\n * Syncs each to instantaneously after the oracle update.\n */\n function _settleAccount(address account, IOracleProvider.OracleVersion memory currentOracleVersion) private {\n IController _controller = controller();\n\n // Get latest oracle version\n if (latestVersion(account) == currentOracleVersion.version) return; // short circuit entirely if a == c\n\n // Get settle oracle version\n uint256 _settleVersion = _positions[account].pre.settleVersion(currentOracleVersion.version);\n IOracleProvider.OracleVersion memory settleOracleVersion = _settleVersion == currentOracleVersion.version\n ? currentOracleVersion // if b == c, don't re-call provider for oracle version\n : atVersion(_settleVersion);\n\n // sync incentivizer before accumulator\n _controller.incentivizer().syncAccount(account, settleOracleVersion);\n\n // value a->b\n Fixed18 accumulated = _accumulators[account].syncTo(\n _accumulator, _positions[account], settleOracleVersion.version).sum();\n\n // position a->b\n _positions[account].settle(settleOracleVersion);\n\n // short-circuit from a->c if b == c\n if (settleOracleVersion.version != currentOracleVersion.version) {\n // sync incentivizer before accumulator\n _controller.incentivizer().syncAccount(account, currentOracleVersion);\n\n // value b->c\n accumulated = accumulated.add(\n _accumulators[account].syncTo(_accumulator, _positions[account], currentOracleVersion.version).sum()\n );\n }\n\n // settle collateral\n _controller.collateral().settleAccount(account, accumulated);\n\n emit AccountSettle(account, settleOracleVersion.version, currentOracleVersion.version);\n }\n\n /**\n * @notice Opens a taker position for `msg.sender`\n * @param amount Amount of the position to open\n */\n function openTake(UFixed18 amount) external {\n openTakeFor(msg.sender, amount);\n }\n\n /**\n * @notice Opens a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\n * @param account Account to open the position for\n * @param amount Amount of the position to open\n */\n function openTakeFor(address account, UFixed18 amount)\n public\n nonReentrant\n notPaused\n notClosed\n onlyAccountOrMultiInvoker(account)\n settleForAccount(account)\n takerInvariant\n positionInvariant(account)\n liquidationInvariant(account)\n maintenanceInvariant(account)\n {\n IOracleProvider.OracleVersion memory latestOracleVersion = atVersion(latestVersion());\n\n _positions[account].pre.openTake(latestOracleVersion.version, amount);\n _position.pre.openTake(latestOracleVersion.version, amount);\n\n UFixed18 positionFee = amount.mul(latestOracleVersion.price.abs()).mul(takerFee());\n if (!positionFee.isZero()) controller().collateral().settleAccount(account, Fixed18Lib.from(-1, positionFee));\n\n emit TakeOpened(account, latestOracleVersion.version, amount);\n }\n\n /**\n * @notice Closes a taker position for `msg.sender`\n * @param amount Amount of the position to close\n */\n function closeTake(UFixed18 amount) external {\n closeTakeFor(msg.sender, amount);\n }\n\n /**\n * @notice Closes a taker position for `account`. Deducts position fee based on notional value at `latestVersion`\n * @param account Account to close the position for\n * @param amount Amount of the position to close\n */\n function closeTakeFor(address account, UFixed18 amount)\n public\n nonReentrant\n notPaused\n onlyAccountOrMultiInvoker(account)\n settleForAccount(account)\n closeInvariant(account)\n liquidationInvariant(account)\n {\n _closeTake(account, amount);\n }\n\n function _closeTake(address account, UFixed18 amount) private {\n IOracleProvider.OracleVersion memory latestOracleVersion = atVersion(latestVersion());\n\n _positions[account].pre.closeTake(latestOracleVersion.version, amount);\n _position.pre.closeTake(latestOracleVersion.version, amount);\n\n UFixed18 positionFee = amount.mul(latestOracleVersion.price.abs()).mul(takerFee());\n if (!positionFee.isZero()) controller().collateral().settleAccount(account, Fixed18Lib.from(-1, positionFee));\n\n emit TakeClosed(account, latestOracleVersion.version, amount);\n }\n\n /**\n * @notice Opens a maker position for `msg.sender`\n * @param amount Amount of the position to open\n */\n function openMake(UFixed18 amount) external {\n openMakeFor(msg.sender, amount);\n }\n\n /**\n * @notice Opens a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\n * @param account Account to open position for\n * @param amount Amount of the position to open\n */\n function openMakeFor(address account, UFixed18 amount)\n public\n nonReentrant\n notPaused\n notClosed\n onlyAccountOrMultiInvoker(account)\n settleForAccount(account)\n nonZeroVersionInvariant\n makerInvariant\n positionInvariant(account)\n liquidationInvariant(account)\n maintenanceInvariant(account)\n {\n IOracleProvider.OracleVersion memory latestOracleVersion = atVersion(latestVersion());\n\n _positions[account].pre.openMake(latestOracleVersion.version, amount);\n _position.pre.openMake(latestOracleVersion.version, amount);\n\n UFixed18 positionFee = amount.mul(latestOracleVersion.price.abs()).mul(makerFee());\n if (!positionFee.isZero()) controller().collateral().settleAccount(account, Fixed18Lib.from(-1, positionFee));\n\n emit MakeOpened(account, latestOracleVersion.version, amount);\n }\n\n /**\n * @notice Closes a maker position for `msg.sender`\n * @param amount Amount of the position to close\n */\n function closeMake(UFixed18 amount) external {\n closeMakeFor(msg.sender, amount);\n }\n\n /**\n * @notice Closes a maker position for `account`. Deducts position fee based on notional value at `latestVersion`\n * @param account Account to close the position for\n * @param amount Amount of the position to close\n */\n function closeMakeFor(address account, UFixed18 amount)\n public\n nonReentrant\n notPaused\n onlyAccountOrMultiInvoker(account)\n settleForAccount(account)\n takerInvariant\n closeInvariant(account)\n liquidationInvariant(account)\n {\n _closeMake(account, amount);\n }\n\n function _closeMake(address account, UFixed18 amount) private {\n IOracleProvider.OracleVersion memory latestOracleVersion = atVersion(latestVersion());\n\n _positions[account].pre.closeMake(latestOracleVersion.version, amount);\n _position.pre.closeMake(latestOracleVersion.version, amount);\n\n UFixed18 positionFee = amount.mul(latestOracleVersion.price.abs()).mul(makerFee());\n if (!positionFee.isZero()) controller().collateral().settleAccount(account, Fixed18Lib.from(-1, positionFee));\n\n emit MakeClosed(account, latestOracleVersion.version, amount);\n }\n\n /**\n * @notice Closes all open and pending positions, locking for liquidation\n * @dev Only callable by the Collateral contract as part of the liquidation flow\n * @param account Account to close out\n */\n function closeAll(address account) external onlyCollateral notClosed settleForAccount(account) {\n AccountPosition storage accountPosition = _positions[account];\n Position memory p = accountPosition.position.next(_positions[account].pre);\n\n // Close all positions\n _closeMake(account, p.maker);\n _closeTake(account, p.taker);\n\n // Mark liquidation to lock position\n accountPosition.liquidation = true;\n }\n\n /**\n * @notice Returns the maintenance requirement for `account`\n * @param account Account to return for\n * @return The current maintenance requirement\n */\n function maintenance(address account) external view returns (UFixed18) {\n return _positions[account].maintenance();\n }\n\n /**\n * @notice Returns the maintenance requirement for `account` after next settlement\n * @dev Assumes no price change and no funding, used to protect user from over-opening\n * @param account Account to return for\n * @return The next maintenance requirement\n */\n function maintenanceNext(address account) external view returns (UFixed18) {\n return _positions[account].maintenanceNext();\n }\n\n /**\n * @notice Returns whether `account` has a completely zero'd position\n * @param account Account to return for\n * @return The the account is closed\n */\n function isClosed(address account) external view returns (bool) {\n return _positions[account].isClosed();\n }\n\n /**\n * @notice Returns whether `account` is currently locked for an in-progress liquidation\n * @param account Account to return for\n * @return Whether the account is in liquidation\n */\n function isLiquidating(address account) external view returns (bool) {\n return _positions[account].liquidation;\n }\n\n /**\n * @notice Returns `account`'s current position\n * @param account Account to return for\n * @return Current position of the account\n */\n function position(address account) external view returns (Position memory) {\n return _positions[account].position;\n }\n\n /**\n * @notice Returns `account`'s current pending-settlement position\n * @param account Account to return for\n * @return Current pre-position of the account\n */\n function pre(address account) external view returns (PrePosition memory) {\n return _positions[account].pre;\n }\n\n /**\n * @notice Returns the global latest settled oracle version\n * @return Latest settled oracle version of the product\n */\n function latestVersion() public view returns (uint256) {\n return _accumulator.latestVersion;\n }\n\n /**\n * @notice Returns the global position at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global position at oracle version\n */\n function positionAtVersion(uint256 oracleVersion) public view returns (Position memory) {\n return _position.positionAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns the current global pending-settlement position\n * @return Global pending-settlement position\n */\n function pre() external view returns (PrePosition memory) {\n return _position.pre;\n }\n\n /**\n * @notice Returns the global accumulator value at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global accumulator value at oracle version\n */\n function valueAtVersion(uint256 oracleVersion) external view returns (Accumulator memory) {\n return _accumulator.valueAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns the global accumulator share at oracleVersion `oracleVersion`\n * @dev Only valid for the version at which a global settlement occurred\n * @param oracleVersion Oracle version to return for\n * @return Global accumulator share at oracle version\n */\n function shareAtVersion(uint256 oracleVersion) external view returns (Accumulator memory) {\n return _accumulator.shareAtVersion(oracleVersion);\n }\n\n /**\n * @notice Returns `account`'s latest settled oracle version\n * @param account Account to return for\n * @return Latest settled oracle version of the account\n */\n function latestVersion(address account) public view returns (uint256) {\n return _accumulators[account].latestVersion;\n }\n\n /**\n * @notice Returns The per-second rate based on the provided `position`\n * @dev Handles 0-maker/taker edge cases\n * @param position_ Position to base utilization on\n * @return The per-second rate\n */\n function rate(Position calldata position_) public view returns (Fixed18) {\n UFixed18 utilization = position_.taker.unsafeDiv(position_.maker);\n Fixed18 annualizedRate = utilizationCurve().compute(utilization);\n return annualizedRate.div(Fixed18Lib.from(365 days));\n }\n\n /**\n * @notice Returns the minimum funding fee parameter with a capped range for safety\n * @dev Caps controller.minFundingFee() <= fundingFee() <= 1\n * @return Safe minimum funding fee parameter\n */\n function _boundedFundingFee() private view returns (UFixed18) {\n return fundingFee().max(controller().minFundingFee());\n }\n\n /**\n * @notice Updates product closed state\n * @dev only callable by product owner. Settles the product before flipping the flag\n * @param newClosed new closed value\n */\n function updateClosed(bool newClosed) external onlyProductOwner {\n IOracleProvider.OracleVersion memory oracleVersion = _settle();\n _closed.store(newClosed);\n emit ClosedUpdated(newClosed, oracleVersion.version);\n }\n\n /**\n * @notice Updates underlying product oracle\n * @dev only callable by product owner\n * @param newOracle new oracle address\n */\n function updateOracle(IOracleProvider newOracle) external onlyProductOwner {\n _updateOracle(address(newOracle), latestVersion());\n }\n\n /// @dev Limit total maker for guarded rollouts\n modifier makerInvariant() {\n _;\n\n Position memory next = positionAtVersion(latestVersion()).next(_position.pre);\n\n if (next.maker.gt(makerLimit())) revert ProductMakerOverLimitError();\n }\n\n /// @dev Limit maker short exposure to the range 0.0-1.0x of their position. Does not apply when in closeOnly state\n modifier takerInvariant() {\n _;\n\n if (closed()) return;\n\n Position memory next = positionAtVersion(latestVersion()).next(_position.pre);\n UFixed18 socializationFactor = next.socializationFactor();\n\n if (socializationFactor.lt(UFixed18Lib.ONE)) revert ProductInsufficientLiquidityError(socializationFactor);\n }\n\n /// @dev Ensure that the user has only taken a maker or taker position, but not both\n modifier positionInvariant(address account) {\n _;\n\n if (_positions[account].isDoubleSided()) revert ProductDoubleSidedError();\n }\n\n /// @dev Ensure that the user hasn't closed more than is open\n modifier closeInvariant(address account) {\n _;\n\n if (_positions[account].isOverClosed()) revert ProductOverClosedError();\n }\n\n /// @dev Ensure that the user will have sufficient margin for maintenance after next settlement\n modifier maintenanceInvariant(address account) {\n _;\n\n if (controller().collateral().liquidatableNext(account, IProduct(this)))\n revert ProductInsufficientCollateralError();\n }\n\n /// @dev Ensure that the user is not currently being liquidated\n modifier liquidationInvariant(address account) {\n if (_positions[account].liquidation) revert ProductInLiquidationError();\n\n _;\n }\n\n /// @dev Helper to fully settle an account's state\n modifier settleForAccount(address account) {\n IOracleProvider.OracleVersion memory _currentVersion = _settle();\n _settleAccount(account, _currentVersion);\n\n _;\n }\n\n /// @dev Ensure we have bootstraped the oracle before creating positions\n modifier nonZeroVersionInvariant() {\n if (latestVersion() == 0) revert ProductOracleBootstrappingError();\n\n _;\n }\n\n /// @dev Ensure the product is not closed\n modifier notClosed() {\n if (closed()) revert ProductClosedError();\n\n _;\n }\n}\n" + }, + "contracts/product/types/accumulator/AccountAccumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../../../interfaces/types/Accumulator.sol\";\nimport \"../position/AccountPosition.sol\";\nimport \"./VersionedAccumulator.sol\";\n\n/// @dev AccountAccumulator type\nstruct AccountAccumulator {\n /// @dev latest version that the account was synced too\n uint256 latestVersion;\n}\nusing AccountAccumulatorLib for AccountAccumulator global;\n\n/**\n * @title AccountAccumulatorLib\n * @notice Library that manages syncing an account-level accumulator.\n */\nlibrary AccountAccumulatorLib {\n /**\n * @notice Syncs the account to oracle version `versionTo`\n * @param self The struct to operate on\n * @param global Pointer to global accumulator\n * @param position Pointer to global position\n * @param versionTo Oracle version to sync account to\n * @return value The value accumulated sync last sync\n */\n function syncTo(\n AccountAccumulator storage self,\n VersionedAccumulator storage global,\n AccountPosition storage position,\n uint256 versionTo\n ) internal returns (Accumulator memory value) {\n Accumulator memory valueAccumulated = global.valueAtVersion(versionTo)\n .sub(global.valueAtVersion(self.latestVersion));\n value = position.position.mul(valueAccumulated);\n self.latestVersion = versionTo;\n }\n}\n" + }, + "contracts/product/types/accumulator/VersionedAccumulator.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../../../interfaces/IProduct.sol\";\nimport \"../../../interfaces/types/Accumulator.sol\";\nimport \"../position/VersionedPosition.sol\";\n\n/// @dev VersionedAccumulator type\nstruct VersionedAccumulator {\n /// @dev Latest synced oracle version\n uint256 latestVersion;\n\n /// @dev Mapping of accumulator value at each settled oracle version\n mapping(uint256 => PackedAccumulator) _valueAtVersion;\n\n /// @dev Mapping of accumulator share at each settled oracle version\n mapping(uint256 => PackedAccumulator) _shareAtVersion;\n}\nusing VersionedAccumulatorLib for VersionedAccumulator global;\n\n/**\n * @title VersionedAccumulatorLib\n * @notice Library that manages global versioned accumulator state.\n * @dev Manages two accumulators: value and share. The value accumulator measures the change in position value\n * over time. The share accumulator measures the change in liquidity ownership over time (for tracking\n * incentivization rewards).\n *\n * Both accumulators are stamped for historical lookup anytime there is a global settlement, which services\n * the delayed-position accounting. It is not guaranteed that every version will have a value stamped, but\n * only versions when a settlement occurred are needed for this historical computation.\n */\nlibrary VersionedAccumulatorLib {\n /**\n * @notice Returns the stamped value accumulator at `oracleVersion`\n * @param self The struct to operate on\n * @param oracleVersion The oracle version to retrieve the value at\n * @return The stamped value accumulator at the requested version\n */\n function valueAtVersion(VersionedAccumulator storage self, uint256 oracleVersion) internal view returns (Accumulator memory) {\n return self._valueAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Returns the stamped share accumulator at `oracleVersion`\n * @param self The struct to operate on\n * @param oracleVersion The oracle version to retrieve the share at\n * @return The stamped share accumulator at the requested version\n */\n function shareAtVersion(VersionedAccumulator storage self, uint256 oracleVersion) internal view returns (Accumulator memory) {\n return self._shareAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Globally accumulates all value (position + funding) and share since last oracle update\n * @param self The struct to operate on\n * @param fundingFee The funding fee rate for the product\n * @param position Pointer to global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedFee The total fee accrued from accumulation\n */\n function accumulate(\n VersionedAccumulator storage self,\n UFixed18 fundingFee,\n VersionedPosition storage position,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal returns (UFixed18 accumulatedFee) {\n Position memory latestPosition = position.positionAtVersion(latestOracleVersion.version);\n\n // accumulate funding\n Accumulator memory accumulatedPosition;\n (accumulatedPosition, accumulatedFee) =\n _accumulateFunding(fundingFee, latestPosition, latestOracleVersion, toOracleVersion);\n\n // accumulate position\n accumulatedPosition = accumulatedPosition.add(\n _accumulatePosition(latestPosition, latestOracleVersion, toOracleVersion));\n\n // accumulate position fee\n (Accumulator memory accumulatedPositionFee, UFixed18 protocolPositionFee) =\n _accumulatePositionFee(latestPosition, position.pre, latestOracleVersion);\n accumulatedPosition = accumulatedPosition.add(accumulatedPositionFee);\n accumulatedFee = accumulatedFee.add(protocolPositionFee);\n\n // accumulate share\n Accumulator memory accumulatedShare =\n _accumulateShare(latestPosition, latestOracleVersion, toOracleVersion);\n\n // save update\n self._valueAtVersion[toOracleVersion.version] = valueAtVersion(self, latestOracleVersion.version)\n .add(accumulatedPosition)\n .pack();\n self._shareAtVersion[toOracleVersion.version] = shareAtVersion(self, latestOracleVersion.version)\n .add(accumulatedShare)\n .pack();\n self.latestVersion = toOracleVersion.version;\n }\n\n /**\n * @notice Globally accumulates all funding since last oracle update\n * @dev If an oracle version is skipped due to no pre positions, funding will continue to be\n * pegged to the price of the last snapshotted oracleVersion until a new one is accumulated.\n * This is an acceptable approximation.\n * @param fundingFee The funding fee rate for the product\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedFunding The total amount accumulated from funding\n * @return accumulatedFee The total fee accrued from funding accumulation\n */\n function _accumulateFunding(\n UFixed18 fundingFee,\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private view returns (Accumulator memory accumulatedFunding, UFixed18 accumulatedFee) {\n if (_product().closed()) return (Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO), UFixed18Lib.ZERO);\n if (latestPosition.taker.isZero()) return (Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO), UFixed18Lib.ZERO);\n if (latestPosition.maker.isZero()) return (Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO), UFixed18Lib.ZERO);\n\n uint256 elapsed = toOracleVersion.timestamp - latestOracleVersion.timestamp;\n\n UFixed18 takerNotional = Fixed18Lib.from(latestPosition.taker).mul(latestOracleVersion.price).abs();\n UFixed18 socializedNotional = takerNotional.mul(latestPosition.socializationFactor());\n\n Fixed18 rateAccumulated = _product().rate(latestPosition)\n .mul(Fixed18Lib.from(UFixed18Lib.from(elapsed)));\n Fixed18 fundingAccumulated = rateAccumulated.mul(Fixed18Lib.from(socializedNotional));\n accumulatedFee = fundingAccumulated.abs().mul(fundingFee);\n\n Fixed18 fundingAccumulatedWithoutFee = Fixed18Lib.from(\n fundingAccumulated.sign(),\n fundingAccumulated.abs().sub(accumulatedFee)\n );\n\n bool makerPaysFunding = fundingAccumulated.sign() < 0;\n accumulatedFunding.maker = (makerPaysFunding ? fundingAccumulated : fundingAccumulatedWithoutFee)\n .div(Fixed18Lib.from(latestPosition.maker));\n accumulatedFunding.taker = (makerPaysFunding ? fundingAccumulatedWithoutFee : fundingAccumulated)\n .div(Fixed18Lib.from(latestPosition.taker)).mul(Fixed18Lib.NEG_ONE);\n }\n\n /**\n * @notice Globally accumulates position PNL since last oracle update\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedPosition The total amount accumulated from position PNL\n */\n function _accumulatePosition(\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private view returns (Accumulator memory accumulatedPosition) {\n if (_product().closed()) return Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO);\n if (latestPosition.taker.isZero()) return Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO);\n if (latestPosition.maker.isZero()) return Accumulator(Fixed18Lib.ZERO, Fixed18Lib.ZERO);\n\n Fixed18 oracleDelta = toOracleVersion.price.sub(latestOracleVersion.price);\n Fixed18 totalTakerDelta = oracleDelta.mul(Fixed18Lib.from(latestPosition.taker));\n Fixed18 socializedTakerDelta = totalTakerDelta.mul(Fixed18Lib.from(latestPosition.socializationFactor()));\n\n accumulatedPosition.maker = socializedTakerDelta.div(Fixed18Lib.from(latestPosition.maker)).mul(Fixed18Lib.NEG_ONE);\n accumulatedPosition.taker = socializedTakerDelta.div(Fixed18Lib.from(latestPosition.taker));\n }\n\n /**\n * @notice Globally accumulates position fees since last oracle update\n * @dev Position fees are calculated based on the price at `latestOracleVersion` as that is the price used to\n * calculate the user's fee total. In the event that settlement is occurring over multiple oracle versions\n * (i.e. from a -> b -> c) it is safe to use the latestOracleVersion because in the a -> b case, a is always\n * b - 1, and in the b -> c case the `PrePosition` is always empty so this is skipped.\n * @param latestPosition The latest global position\n * @param pre The global pre-position\n * @param latestOracleVersion The latest oracle version\n * @return accumulatedPosition The total amount accumulated from position PNL\n * @return fee The position fee that is retained by the protocol and product\n */\n function _accumulatePositionFee(\n Position memory latestPosition,\n PrePosition memory pre,\n IOracleProvider.OracleVersion memory latestOracleVersion\n ) private view returns (Accumulator memory accumulatedPosition, UFixed18 fee) {\n if (pre.isEmpty()) return (accumulatedPosition, fee);\n\n Position memory positionFee = pre.computeFee(latestOracleVersion);\n Position memory protocolFee = positionFee.mul(_product().positionFee());\n positionFee = positionFee.sub(protocolFee);\n fee = protocolFee.sum();\n\n // If there are makers to distribute the taker's position fee to, distribute. Otherwise give it to the protocol\n if (!latestPosition.maker.isZero()) {\n accumulatedPosition.maker = Fixed18Lib.from(positionFee.taker.div(latestPosition.maker));\n } else {\n fee = fee.add(positionFee.taker);\n }\n\n // If there are takers to distribute the maker's position fee to, distribute. Otherwise give it to the protocol\n if (!latestPosition.taker.isZero()) {\n accumulatedPosition.taker = Fixed18Lib.from(positionFee.maker.div(latestPosition.taker));\n } else {\n fee = fee.add(positionFee.maker);\n }\n }\n\n /**\n * @notice Globally accumulates position's share of the total market since last oracle update\n * @dev This is used to compute incentivization rewards based on market participation\n * @param latestPosition The latest global position\n * @param latestOracleVersion The oracle version to accumulate from\n * @param toOracleVersion The oracle version to accumulate to\n * @return accumulatedShare The total share amount accumulated per position\n */\n function _accumulateShare(\n Position memory latestPosition,\n IOracleProvider.OracleVersion memory latestOracleVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) private pure returns (Accumulator memory accumulatedShare) {\n uint256 elapsed = toOracleVersion.timestamp - latestOracleVersion.timestamp;\n\n accumulatedShare.maker = latestPosition.maker.isZero() ?\n Fixed18Lib.ZERO :\n Fixed18Lib.from(UFixed18Lib.from(elapsed).div(latestPosition.maker));\n accumulatedShare.taker = latestPosition.taker.isZero() ?\n Fixed18Lib.ZERO :\n Fixed18Lib.from(UFixed18Lib.from(elapsed).div(latestPosition.taker));\n }\n\n function _product() private view returns (IProduct) {\n return IProduct(address(this));\n }\n}\n" + }, + "contracts/product/types/position/AccountPosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../../../interfaces/IProduct.sol\";\nimport \"../../../interfaces/types/PrePosition.sol\";\n\n/// @dev AccountPosition type\nstruct AccountPosition {\n /// @dev The current settled position of the account\n Position position;\n\n /// @dev The current position delta pending-settlement\n PrePosition pre;\n\n /// @dev Whether the account is currently locked for liquidation\n bool liquidation;\n}\nusing AccountPositionLib for AccountPosition global;\n\n/**\n * @title AccountPositionLib\n * @notice Library that manages an account-level position.\n */\nlibrary AccountPositionLib {\n /**\n * @notice Settled the account's position to oracle version `toOracleVersion`\n * @param self The struct to operate on\n * @param toOracleVersion The oracle version to accumulate to\n */\n function settle(\n AccountPosition storage self,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal {\n bool settled;\n (self.position, settled) = self.position.settled(self.pre, toOracleVersion);\n if (settled) {\n delete self.pre;\n self.liquidation = false;\n }\n }\n\n /**\n * @notice Returns the current maintenance requirement for the account\n * @dev Must be called from a valid product to get the proper maintenance value\n * @param self The struct to operate on\n * @return Current maintenance requirement for the account\n */\n function maintenance(AccountPosition storage self) internal view returns (UFixed18) {\n return _maintenance(self.position);\n }\n\n /**\n * @notice Returns the maintenance requirement after the next oracle version settlement\n * @dev Includes the current pending-settlement position delta, assumes no price change\n * @param self The struct to operate on\n * @return Next maintenance requirement for the account\n */\n function maintenanceNext(AccountPosition storage self) internal view returns (UFixed18) {\n return _maintenance(self.position.next(self.pre));\n }\n\n /**\n * @notice Returns the maintenance requirement for a given `position`\n * @dev Internal helper\n * @param position The position to compete the maintenance requirement for\n * @return Next maintenance requirement for the account\n */\n function _maintenance(Position memory position) private view returns (UFixed18) {\n IProduct product = IProduct(address(this));\n Fixed18 oraclePrice = product.currentVersion().price;\n UFixed18 notionalMax = Fixed18Lib.from(position.max()).mul(oraclePrice).abs();\n return notionalMax.mul(product.maintenance());\n }\n\n /**\n * @notice Returns whether an account is completely closed, i.e. no position or pre-position\n * @param self The struct to operate on\n * @return Whether the account is closed\n */\n function isClosed(AccountPosition memory self) internal pure returns (bool) {\n return self.pre.isEmpty() && self.position.isEmpty();\n }\n\n /**\n * @notice Returns whether an account has opened position on both sides of the market (maker vs taker)\n * @dev Used to verify the invariant that a single account can only have a position on one side of the\n * market at a time\n * @param self The struct to operate on\n * @return Whether the account is currently doubled sided\n */\n function isDoubleSided(AccountPosition storage self) internal view returns (bool) {\n bool makerEmpty = self.position.maker.isZero() && self.pre.openPosition.maker.isZero() && self.pre.closePosition.maker.isZero();\n bool takerEmpty = self.position.taker.isZero() && self.pre.openPosition.taker.isZero() && self.pre.closePosition.taker.isZero();\n\n return !makerEmpty && !takerEmpty;\n }\n\n /**\n * @notice Returns whether the account's pending-settlement delta closes more position than is open\n * @dev Used to verify the invariant that an account cannot settle into having a negative position\n * @param self The struct to operate on\n * @return Whether the account is currently over closed\n */\n function isOverClosed(AccountPosition storage self) internal view returns (bool) {\n Position memory nextOpen = self.position.add(self.pre.openPosition);\n\n return self.pre.closePosition.maker.gt(nextOpen.maker) || self.pre.closePosition.taker.gt(nextOpen.taker);\n }\n}\n" + }, + "contracts/product/types/position/VersionedPosition.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"../../../interfaces/types/PrePosition.sol\";\nimport \"../../../interfaces/types/PackedPosition.sol\";\n\n//// @dev VersionedPosition type\nstruct VersionedPosition {\n /// @dev Mapping of global position at each version\n mapping(uint256 => PackedPosition) _positionAtVersion;\n\n /// @dev Current global pending-settlement position delta\n PrePosition pre;\n}\nusing VersionedPositionLib for VersionedPosition global;\n\n/**\n * @title VersionedPositionLib\n * @notice Library that manages global position state.\n * @dev Global position state is used to compute utilization rate and socialization, and to account for and\n * distribute fees globally.\n *\n * Positions are stamped for historical lookup anytime there is a global settlement, which services\n * the delayed-position accounting. It is not guaranteed that every version will have a value stamped, but\n * only versions when a settlement occurred are needed for this historical computation.\n */\nlibrary VersionedPositionLib {\n /**\n * @notice Returns the current global position\n * @return Current global position\n */\n function positionAtVersion(VersionedPosition storage self, uint256 oracleVersion) internal view returns (Position memory) {\n return self._positionAtVersion[oracleVersion].unpack();\n }\n\n /**\n * @notice Settled the global position to oracle version `toOracleVersion`\n * @param self The struct to operate on\n * @param latestVersion The latest settled oracle version\n * @param toOracleVersion The oracle version to settle to\n */\n function settle(\n VersionedPosition storage self,\n uint256 latestVersion,\n IOracleProvider.OracleVersion memory toOracleVersion\n ) internal {\n (Position memory newPosition, bool settled) =\n positionAtVersion(self, latestVersion).settled(self.pre, toOracleVersion);\n\n self._positionAtVersion[toOracleVersion.version] = newPosition.pack();\n if (settled) delete self.pre;\n }\n}\n" + }, + "contracts/product/UParamProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"../controller/UControllerProvider.sol\";\nimport \"../interfaces/IParamProvider.sol\";\nimport \"../interfaces/IProduct.sol\";\nimport \"../interfaces/types/PendingFeeUpdates.sol\";\n\n/**\n * @title UParamProvider\n * @notice Library for manage storing, surfacing, and upgrading a product's parameters.\n * @dev Uses an unstructured storage pattern to store the parameters which allows this\n provider to be safely used with upgradeable contracts. For certain paramters, a\n staged update pattern is used.\n */\nabstract contract UParamProvider is IParamProvider, UControllerProvider {\n /**\n * @notice Initializes the contract state\n * @param maintenance_ product maintenance ratio\n * @param fundingFee_ product funding fee\n * @param makerFee_ product maker fee\n * @param takerFee_ product taker fee\n * @param makerLimit_ product maker limit\n * @param utilizationCurve_ utilization curve definition\n */\n // solhint-disable-next-line func-name-mixedcase\n function __UParamProvider__initialize(\n UFixed18 maintenance_,\n UFixed18 fundingFee_,\n UFixed18 makerFee_,\n UFixed18 takerFee_,\n UFixed18 positionFee_,\n UFixed18 makerLimit_,\n JumpRateUtilizationCurve memory utilizationCurve_\n ) internal onlyInitializer {\n _updateMaintenance(maintenance_);\n _updateFundingFee(fundingFee_);\n _updateMakerFee(makerFee_);\n _updateTakerFee(takerFee_);\n _updatePositionFee(positionFee_);\n _updateMakerLimit(makerLimit_);\n _updateUtilizationCurve(utilizationCurve_);\n }\n\n /// @dev The maintenance value\n UFixed18Storage private constant _maintenance = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.maintenance\"));\n function maintenance() public view returns (UFixed18) { return _maintenance.read(); }\n\n /// @dev The funding fee value\n UFixed18Storage private constant _fundingFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.fundingFee\"));\n function fundingFee() public view returns (UFixed18) { return _fundingFee.read(); }\n\n /// @dev The maker fee value\n UFixed18Storage private constant _makerFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.makerFee\"));\n function makerFee() public view returns (UFixed18) { return _makerFee.read(); }\n\n /// @dev The taker fee value\n UFixed18Storage private constant _takerFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.takerFee\"));\n function takerFee() public view returns (UFixed18) { return _takerFee.read(); }\n\n /// @dev The positon fee share value\n UFixed18Storage private constant _positionFee = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.positionFee\"));\n function positionFee() public view returns (UFixed18) { return _positionFee.read(); }\n\n /// @dev The maker limit value\n UFixed18Storage private constant _makerLimit = UFixed18Storage.wrap(keccak256(\"equilibria.perennial.UParamProvider.makerLimit\"));\n function makerLimit() public view returns (UFixed18) { return _makerLimit.read(); }\n\n /// @dev The JumpRateUtilizationCurve params\n JumpRateUtilizationCurveStorage private constant _utilizationCurve =\n JumpRateUtilizationCurveStorage.wrap(keccak256(\"equilibria.perennial.UParamProvider.jumpRateUtilizationCurve\"));\n function utilizationCurve() public view returns (JumpRateUtilizationCurve memory) { return _utilizationCurve.read(); }\n\n /// @dev The pending fee updates value\n PendingFeeUpdatesStorage private constant _pendingFeeUpdates =\n PendingFeeUpdatesStorage.wrap(keccak256(\"equilibria.perennial.UParamProvider.pendingFeeUpdates\"));\n function pendingFeeUpdates() public view returns (PendingFeeUpdates memory) { return _pendingFeeUpdates.read(); }\n\n /**\n * @notice Updates the maintenance to `newMaintenance`\n * @param newMaintenance new maintenance value\n */\n function _updateMaintenance(UFixed18 newMaintenance) private {\n _maintenance.store(newMaintenance);\n emit MaintenanceUpdated(newMaintenance, _productVersion());\n }\n\n /**\n * @notice Updates the maintenance to `newMaintenance`\n * @dev only callable by product owner\n * @param newMaintenance new maintenance value\n */\n function updateMaintenance(UFixed18 newMaintenance) external onlyProductOwner settleProduct {\n _updateMaintenance(newMaintenance);\n }\n\n /**\n * @notice Updates the funding fee to `newFundingFee`\n * @param newFundingFee new funding fee value\n */\n function _updateFundingFee(UFixed18 newFundingFee) private {\n if (newFundingFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n _fundingFee.store(newFundingFee);\n emit FundingFeeUpdated(newFundingFee, _productVersion());\n }\n\n /**\n * @notice Updates the funding fee to `newFundingFee`\n * @dev only callable by product owner\n * @param newFundingFee new funding fee value\n */\n function updateFundingFee(UFixed18 newFundingFee) external onlyProductOwner settleProduct {\n _updateFundingFee(newFundingFee);\n }\n\n /**\n * @notice Updates the maker fee to `newMakerFee`\n * @param newMakerFee new maker fee value\n */\n function _updateMakerFee(UFixed18 newMakerFee) private {\n if (newMakerFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n _makerFee.store(newMakerFee);\n emit MakerFeeUpdated(newMakerFee, _productVersion());\n }\n\n /**\n * @notice Updates the pending maker fee to `newMakerFee`\n * @param newMakerFee new maker fee value\n */\n function _updatePendingMakerFee(UFixed18 newMakerFee) private {\n if (newMakerFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n PendingFeeUpdates memory pendingFees_ = pendingFeeUpdates();\n pendingFees_.updateMakerFee(newMakerFee);\n _pendingFeeUpdates.store(pendingFees_);\n emit PendingMakerFeeUpdated(newMakerFee);\n }\n\n /**\n * @notice Updates the maker fee to `newMakerFee`\n * @dev only callable by product owner\n * @param newMakerFee new maker fee value\n */\n function updateMakerFee(UFixed18 newMakerFee) external onlyProductOwner settleProduct {\n if (!_noPendingPositions()) {\n _updatePendingMakerFee(newMakerFee);\n } else {\n _updateMakerFee(newMakerFee);\n }\n }\n\n /**\n * @notice Updates the taker fee to `newTakerFee`\n * @param newTakerFee new taker fee value\n */\n function _updateTakerFee(UFixed18 newTakerFee) private {\n if (newTakerFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n _takerFee.store(newTakerFee);\n emit TakerFeeUpdated(newTakerFee, _productVersion());\n }\n\n /**\n * @notice Updates the pending taker fee to `newTakerFee`\n * @param newTakerFee new taker fee value\n */\n function _updatePendingTakerFee(UFixed18 newTakerFee) private {\n if (newTakerFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n PendingFeeUpdates memory pendingFees_ = pendingFeeUpdates();\n pendingFees_.updateTakerFee(newTakerFee);\n _pendingFeeUpdates.store(pendingFees_);\n emit PendingTakerFeeUpdated(newTakerFee);\n }\n\n /**\n * @notice Updates the taker fee to `newTakerFee`\n * @dev only callable by product owner\n * @param newTakerFee new taker fee value\n */\n function updateTakerFee(UFixed18 newTakerFee) external onlyProductOwner settleProduct {\n if (!_noPendingPositions()) {\n _updatePendingTakerFee(newTakerFee);\n } else {\n _updateTakerFee(newTakerFee);\n }\n }\n\n /**\n * @notice Updates the position fee to `newPositionFee`\n * @param newPositionFee new position fee value\n */\n function _updatePositionFee(UFixed18 newPositionFee) private {\n if (newPositionFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n _positionFee.store(newPositionFee);\n emit PositionFeeUpdated(newPositionFee, _productVersion());\n }\n\n /**\n * @notice Updates the pending position fee to `newPositionFee`\n * @param newPositionFee new position fee value\n */\n function _updatePendingPositionFee(UFixed18 newPositionFee) private {\n if (newPositionFee.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();\n PendingFeeUpdates memory pendingFees_ = pendingFeeUpdates();\n pendingFees_.updatePositionFee(newPositionFee);\n _pendingFeeUpdates.store(pendingFees_);\n emit PendingPositionFeeUpdated(newPositionFee);\n }\n\n /**\n * @notice Updates the position fee to `newPositionFee`\n * @dev only callable by product owner\n * @param newPositionFee new position fee value\n */\n function updatePositionFee(UFixed18 newPositionFee) external onlyProductOwner settleProduct {\n if (!_noPendingPositions()) {\n _updatePendingPositionFee(newPositionFee);\n } else {\n _updatePositionFee(newPositionFee);\n }\n }\n\n /**\n * @notice Updates the maker limit to `newMakerLimit`\n * @param newMakerLimit new maker limit value\n */\n function _updateMakerLimit(UFixed18 newMakerLimit) private {\n _makerLimit.store(newMakerLimit);\n emit MakerLimitUpdated(newMakerLimit, _productVersion());\n }\n\n /**\n * @notice Updates the maker limit to `newMakerLimit`\n * @dev only callable by product owner\n * @param newMakerLimit new maker limit value\n */\n function updateMakerLimit(UFixed18 newMakerLimit) external onlyProductOwner settleProduct {\n _updateMakerLimit(newMakerLimit);\n }\n\n /**\n * @notice Updates the utilization curve to `newUtilizationCurve`\n * @param newUtilizationCurve new utilization curve value\n */\n function _updateUtilizationCurve(JumpRateUtilizationCurve memory newUtilizationCurve) private {\n _utilizationCurve.store(newUtilizationCurve);\n emit JumpRateUtilizationCurveUpdated(newUtilizationCurve, _productVersion());\n }\n\n /**\n * @notice Updates the utilization curve to `newUtilizationCurve`\n * @dev only callable by product owner\n * @param newUtilizationCurve new utilization curve value\n */\n function updateUtilizationCurve(JumpRateUtilizationCurve calldata newUtilizationCurve) external onlyProductOwner settleProduct {\n _updateUtilizationCurve(newUtilizationCurve);\n }\n\n function _settleFeeUpdates() internal {\n PendingFeeUpdates memory pendingFeeUpdates_ = pendingFeeUpdates();\n if (!pendingFeeUpdates_.hasUpdates()) return;\n if (pendingFeeUpdates_.makerFeeUpdated) _updateMakerFee(pendingFeeUpdates_.makerFee());\n if (pendingFeeUpdates_.takerFeeUpdated) _updateTakerFee(pendingFeeUpdates_.takerFee());\n if (pendingFeeUpdates_.positionFeeUpdated) _updatePositionFee(pendingFeeUpdates_.positionFee());\n\n pendingFeeUpdates_.clear();\n _pendingFeeUpdates.store(pendingFeeUpdates_);\n }\n\n function _productVersion() private view returns (uint256) {\n // If this product is being constructed then return 0\n if (!Address.isContract(address(this))) return 0;\n return IProduct(address(this)).latestVersion();\n }\n\n /**\n * @notice Checks whether the Product's `pre` position is empty\n * @return Whether or not the pre position is empty\n */\n function _noPendingPositions() private view returns (bool) {\n return IProduct(address(this)).pre().isEmpty();\n }\n\n /// @dev Only allow the Product's coordinator owner to call\n modifier onlyProductOwner {\n uint256 coordinatorId = controller().coordinatorFor(IProduct(address(this)));\n if (controller().owner(coordinatorId) != msg.sender) revert NotOwnerError(coordinatorId);\n\n _;\n }\n\n /// @dev Settles the product\n modifier settleProduct {\n IProduct(address(this)).settle();\n\n _;\n }\n}\n" + }, + "contracts/product/UPayoffProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.13;\n\nimport \"@equilibria/root/control/unstructured/UInitializable.sol\";\nimport \"@equilibria/perennial-oracle/contracts/interfaces/IOracleProvider.sol\";\nimport \"@equilibria/root/storage/UStorage.sol\";\nimport \"../interfaces/IPayoffProvider.sol\";\nimport \"../interfaces/types/PayoffDefinition.sol\";\n\n/**\n * @title UPayoffProvider\n * @notice Library for manage storing, surfacing, and upgrading a payoff provider.\n * @dev Uses an unstructured storage pattern to store the oracle address and payoff definition which allows this\n provider to be safely used with upgradeable contracts.\n */\nabstract contract UPayoffProvider is IPayoffProvider, UInitializable {\n /// @dev The oracle contract address\n AddressStorage private constant _oracle =\n AddressStorage.wrap(keccak256(\"equilibria.perennial.UPayoffProvider.oracle\"));\n function oracle() public view returns (IOracleProvider) { return IOracleProvider(_oracle.read()); }\n\n /// @dev Payoff definition struct\n PayoffDefinitionStorage private constant _payoffDefinition =\n PayoffDefinitionStorage.wrap(keccak256(\"equilibria.perennial.UPayoffProvider.payoffDefinition\"));\n function payoffDefinition() public view returns (PayoffDefinition memory) { return _payoffDefinition.read(); }\n\n /**\n * @notice Initializes the contract state\n * @param oracle_ Oracle address\n * @param payoffDefinition_ Payoff provider\n */\n // solhint-disable-next-line func-name-mixedcase\n function __UPayoffProvider__initialize(IOracleProvider oracle_, PayoffDefinition calldata payoffDefinition_) internal onlyInitializer {\n _updateOracle(address(oracle_), 0);\n\n if (!payoffDefinition_.valid()) revert PayoffProviderInvalidPayoffDefinitionError();\n _payoffDefinition.store(payoffDefinition_);\n }\n\n /**\n * @notice Returns the current oracle version transformed by the payoff definition\n * @return Current oracle version transformed by the payoff definition\n */\n function currentVersion() public view returns (IOracleProvider.OracleVersion memory) {\n return _transform(oracle().currentVersion());\n }\n\n /**\n * @notice Returns the oracle version at `oracleVersion` transformed by the payoff definition\n * @param oracleVersion Oracle version to return for\n * @return Oracle version at `oracleVersion` with price transformed by payoff function\n */\n function atVersion(uint256 oracleVersion) public view returns (IOracleProvider.OracleVersion memory) {\n return _transform(oracle().atVersion(oracleVersion));\n }\n\n /**\n * @notice Updates oracle to newOracle address\n * @param newOracle New oracle address\n * @param oracleVersion Oracle version of update\n */\n function _updateOracle(address newOracle, uint256 oracleVersion) internal {\n if (!Address.isContract(newOracle)) revert PayoffProviderInvalidOracle();\n _oracle.store(newOracle);\n\n emit OracleUpdated(newOracle, oracleVersion);\n }\n\n /**\n * @notice Hook to call sync() on the oracle provider and transform the resulting oracle version\n */\n function _sync() internal returns (IOracleProvider.OracleVersion memory) {\n return _transform(oracle().sync());\n }\n\n /**\n * @notice Returns the transformed oracle version\n * @param oracleVersion Oracle version to transform\n * @return Transformed oracle version\n */\n function _transform(IOracleProvider.OracleVersion memory oracleVersion)\n internal view virtual returns (IOracleProvider.OracleVersion memory) {\n oracleVersion.price = payoffDefinition().transform(oracleVersion.price);\n return oracleVersion;\n }\n}\n" + } + }, + "settings": { + "viaIR": true, + "optimizer": { + "enabled": true, + "runs": 1, + "details": { + "yulDetails": { + "optimizerSteps": "dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul" + } + } + }, + "outputSelection": { + "*": { + "*": [ + "evm.deployedBytecode.sourceMap", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": ["ast"] + } + } + } +}