{
  "address": "0x0818E46C726810c2f7a1C513D0637a862bc0df6F",
  "abi": [
    {
      "inputs": [],
      "name": "ControllerInvalidIncentivizationFeeError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerInvalidLiquidationFeeError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerInvalidMinFundingFeeError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerInvalidProtocolFeeError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerNoZeroCoordinatorError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerNotContractAddressError",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "controllerId",
          "type": "uint256"
        }
      ],
      "name": "ControllerNotOwnerError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "ControllerNotPauserError",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "controllerId",
          "type": "uint256"
        }
      ],
      "name": "ControllerNotPendingOwnerError",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "version",
          "type": "uint256"
        }
      ],
      "name": "UInitializableAlreadyInitializedError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "UInitializableNotInitializingError",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "UInitializableZeroVersionError",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "contract ICollateral",
          "name": "newCollateral",
          "type": "address"
        }
      ],
      "name": "CollateralUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "CoordinatorCreated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "CoordinatorOwnerUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "newPendingOwner",
          "type": "address"
        }
      ],
      "name": "CoordinatorPendingOwnerUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "newTreasury",
          "type": "address"
        }
      ],
      "name": "CoordinatorTreasuryUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "newIncentivizationFee",
          "type": "uint256"
        }
      ],
      "name": "IncentivizationFeeUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "contract IIncentivizer",
          "name": "newIncentivizer",
          "type": "address"
        }
      ],
      "name": "IncentivizerUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "version",
          "type": "uint256"
        }
      ],
      "name": "Initialized",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "newLiquidationFee",
          "type": "uint256"
        }
      ],
      "name": "LiquidationFeeUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "newMinCollateral",
          "type": "uint256"
        }
      ],
      "name": "MinCollateralUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "newMinFundingFee",
          "type": "uint256"
        }
      ],
      "name": "MinFundingFeeUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "bool",
          "name": "newPaused",
          "type": "bool"
        }
      ],
      "name": "PausedUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "newPauser",
          "type": "address"
        }
      ],
      "name": "PauserUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "contract IBeacon",
          "name": "newProductBeacon",
          "type": "address"
        }
      ],
      "name": "ProductBeaconUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        },
        {
          "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": "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"
            }
          ],
          "indexed": false,
          "internalType": "struct IProduct.ProductInfo",
          "name": "productInfo",
          "type": "tuple"
        }
      ],
      "name": "ProductCreated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newProgramsPerProduct",
          "type": "uint256"
        }
      ],
      "name": "ProgramsPerProductUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "UFixed18",
          "name": "newProtocolFee",
          "type": "uint256"
        }
      ],
      "name": "ProtocolFeeUpdated",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        }
      ],
      "name": "acceptCoordinatorOwner",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "collateral",
      "outputs": [
        {
          "internalType": "contract ICollateral",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IProduct",
          "name": "",
          "type": "address"
        }
      ],
      "name": "coordinatorFor",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        }
      ],
      "name": "coordinators",
      "outputs": [
        {
          "components": [
            {
              "internalType": "address",
              "name": "pendingOwner",
              "type": "address"
            },
            {
              "internalType": "address",
              "name": "owner",
              "type": "address"
            },
            {
              "internalType": "address",
              "name": "treasury",
              "type": "address"
            }
          ],
          "internalType": "struct IController.Coordinator",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "createCoordinator",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "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": "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": "createProduct",
      "outputs": [
        {
          "internalType": "contract IProduct",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "incentivizationFee",
      "outputs": [
        {
          "internalType": "UFixed18",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "incentivizer",
      "outputs": [
        {
          "internalType": "contract IIncentivizer",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract ICollateral",
          "name": "collateral_",
          "type": "address"
        },
        {
          "internalType": "contract IIncentivizer",
          "name": "incentivizer_",
          "type": "address"
        },
        {
          "internalType": "contract IBeacon",
          "name": "productBeacon_",
          "type": "address"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        }
      ],
      "name": "isProduct",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "liquidationFee",
      "outputs": [
        {
          "internalType": "UFixed18",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "minCollateral",
      "outputs": [
        {
          "internalType": "UFixed18",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "minFundingFee",
      "outputs": [
        {
          "internalType": "UFixed18",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        }
      ],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        }
      ],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "paused",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "pauser",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        }
      ],
      "name": "pendingOwner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "pendingOwner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "productBeacon",
      "outputs": [
        {
          "internalType": "contract IBeacon",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "programsPerProduct",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "protocolFee",
      "outputs": [
        {
          "internalType": "UFixed18",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IProduct",
          "name": "product",
          "type": "address"
        }
      ],
      "name": "treasury",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        }
      ],
      "name": "treasury",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "treasury",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract ICollateral",
          "name": "newCollateral",
          "type": "address"
        }
      ],
      "name": "updateCollateral",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "newPendingOwner",
          "type": "address"
        }
      ],
      "name": "updateCoordinatorPendingOwner",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "coordinatorId",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "newTreasury",
          "type": "address"
        }
      ],
      "name": "updateCoordinatorTreasury",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UFixed18",
          "name": "newIncentivizationFee",
          "type": "uint256"
        }
      ],
      "name": "updateIncentivizationFee",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IIncentivizer",
          "name": "newIncentivizer",
          "type": "address"
        }
      ],
      "name": "updateIncentivizer",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UFixed18",
          "name": "newLiquidationFee",
          "type": "uint256"
        }
      ],
      "name": "updateLiquidationFee",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UFixed18",
          "name": "newMinCollateral",
          "type": "uint256"
        }
      ],
      "name": "updateMinCollateral",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UFixed18",
          "name": "newMinFundingFee",
          "type": "uint256"
        }
      ],
      "name": "updateMinFundingFee",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bool",
          "name": "newPaused",
          "type": "bool"
        }
      ],
      "name": "updatePaused",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newPauser",
          "type": "address"
        }
      ],
      "name": "updatePauser",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IBeacon",
          "name": "newProductBeacon",
          "type": "address"
        }
      ],
      "name": "updateProductBeacon",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newProgramsPerProduct",
          "type": "uint256"
        }
      ],
      "name": "updateProgramsPerProduct",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "UFixed18",
          "name": "newProtocolFee",
          "type": "uint256"
        }
      ],
      "name": "updateProtocolFee",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0xdff42b3125b73e7b0c9ca4039db1980766755dc5c46d18b26d446b0ab3c0c09e",
  "receipt": {
    "to": null,
    "from": "0x66a7fDB96C583c59597de16d8b2B989231415339",
    "contractAddress": "0x0818E46C726810c2f7a1C513D0637a862bc0df6F",
    "transactionIndex": 0,
    "gasUsed": "2574331",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x3cae7601da04adf827992a094d939f2335cb34d67e9721988a37d48c898490b5",
    "transactionHash": "0xdff42b3125b73e7b0c9ca4039db1980766755dc5c46d18b26d446b0ab3c0c09e",
    "logs": [],
    "blockNumber": 33203732,
    "cumulativeGasUsed": "2574331",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "numDeployments": 1,
  "solcInputHash": "dd52f03d8fef7833844e4ba864fd9fba",
  "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"ControllerInvalidIncentivizationFeeError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerInvalidLiquidationFeeError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerInvalidMinFundingFeeError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerInvalidProtocolFeeError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerNoZeroCoordinatorError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerNotContractAddressError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"controllerId\",\"type\":\"uint256\"}],\"name\":\"ControllerNotOwnerError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ControllerNotPauserError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"controllerId\",\"type\":\"uint256\"}],\"name\":\"ControllerNotPendingOwnerError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UInitializableAlreadyInitializedError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableNotInitializingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UInitializableZeroVersionError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ICollateral\",\"name\":\"newCollateral\",\"type\":\"address\"}],\"name\":\"CollateralUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"CoordinatorCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"CoordinatorOwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingOwner\",\"type\":\"address\"}],\"name\":\"CoordinatorPendingOwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasury\",\"type\":\"address\"}],\"name\":\"CoordinatorTreasuryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newIncentivizationFee\",\"type\":\"uint256\"}],\"name\":\"IncentivizationFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IIncentivizer\",\"name\":\"newIncentivizer\",\"type\":\"address\"}],\"name\":\"IncentivizerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newLiquidationFee\",\"type\":\"uint256\"}],\"name\":\"LiquidationFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMinCollateral\",\"type\":\"uint256\"}],\"name\":\"MinCollateralUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newMinFundingFee\",\"type\":\"uint256\"}],\"name\":\"MinFundingFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"PausedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauser\",\"type\":\"address\"}],\"name\":\"PauserUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IBeacon\",\"name\":\"newProductBeacon\",\"type\":\"address\"}],\"name\":\"ProductBeaconUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"},{\"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\":\"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\"}],\"indexed\":false,\"internalType\":\"struct IProduct.ProductInfo\",\"name\":\"productInfo\",\"type\":\"tuple\"}],\"name\":\"ProductCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newProgramsPerProduct\",\"type\":\"uint256\"}],\"name\":\"ProgramsPerProductUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"UFixed18\",\"name\":\"newProtocolFee\",\"type\":\"uint256\"}],\"name\":\"ProtocolFeeUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"acceptCoordinatorOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"coordinatorFor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"coordinators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pendingOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"treasury\",\"type\":\"address\"}],\"internalType\":\"struct IController.Coordinator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createCoordinator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"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\":\"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\":\"createProduct\",\"outputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"incentivizationFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"incentivizer\",\"outputs\":[{\"internalType\":\"contract IIncentivizer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"collateral_\",\"type\":\"address\"},{\"internalType\":\"contract IIncentivizer\",\"name\":\"incentivizer_\",\"type\":\"address\"},{\"internalType\":\"contract IBeacon\",\"name\":\"productBeacon_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"}],\"name\":\"isProduct\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidationFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minCollateral\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minFundingFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"}],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"productBeacon\",\"outputs\":[{\"internalType\":\"contract IBeacon\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"programsPerProduct\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFee\",\"outputs\":[{\"internalType\":\"UFixed18\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IProduct\",\"name\":\"product\",\"type\":\"address\"}],\"name\":\"treasury\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"}],\"name\":\"treasury\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasury\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ICollateral\",\"name\":\"newCollateral\",\"type\":\"address\"}],\"name\":\"updateCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newPendingOwner\",\"type\":\"address\"}],\"name\":\"updateCoordinatorPendingOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coordinatorId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newTreasury\",\"type\":\"address\"}],\"name\":\"updateCoordinatorTreasury\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newIncentivizationFee\",\"type\":\"uint256\"}],\"name\":\"updateIncentivizationFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IIncentivizer\",\"name\":\"newIncentivizer\",\"type\":\"address\"}],\"name\":\"updateIncentivizer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newLiquidationFee\",\"type\":\"uint256\"}],\"name\":\"updateLiquidationFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMinCollateral\",\"type\":\"uint256\"}],\"name\":\"updateMinCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newMinFundingFee\",\"type\":\"uint256\"}],\"name\":\"updateMinFundingFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"updatePaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauser\",\"type\":\"address\"}],\"name\":\"updatePauser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IBeacon\",\"name\":\"newProductBeacon\",\"type\":\"address\"}],\"name\":\"updateProductBeacon\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newProgramsPerProduct\",\"type\":\"uint256\"}],\"name\":\"updateProgramsPerProduct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"UFixed18\",\"name\":\"newProtocolFee\",\"type\":\"uint256\"}],\"name\":\"updateProtocolFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptCoordinatorOwner(uint256)\":{\"details\":\"Must be called by the coordinator's pending owner\",\"params\":{\"coordinatorId\":\"Coordinator to update\"}},\"coordinators(uint256)\":{\"params\":{\"coordinatorId\":\"Coordinator to return for\"},\"returns\":{\"_0\":\"Coordinator state\"}},\"createCoordinator()\":{\"details\":\"Can only be called by the protocol owner\",\"returns\":{\"_0\":\"New coordinator ID\"}},\"createProduct(uint256,(string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"details\":\"Can only be called by the coordinator owner\",\"params\":{\"coordinatorId\":\"Coordinator that will own the product\",\"productInfo\":\"Product params used to initialize the product\"},\"returns\":{\"_0\":\"New product contract address\"}},\"initialize(address,address,address)\":{\"details\":\"Must be called atomically as part of the upgradeable proxy deployment to      avoid front-running\",\"params\":{\"collateral_\":\"Collateral contract address\",\"incentivizer_\":\"Incentivizer contract address\",\"productBeacon_\":\"Product implementation beacon address\"}},\"isProduct(address)\":{\"params\":{\"product\":\"Contract address to check\"},\"returns\":{\"_0\":\"Whether a contract is a product\"}},\"owner()\":{\"returns\":{\"_0\":\"Owner of the protocol\"}},\"owner(address)\":{\"params\":{\"product\":\"Product to return for\"},\"returns\":{\"_0\":\"Owner of the product\"}},\"owner(uint256)\":{\"params\":{\"coordinatorId\":\"Coordinator to return for\"},\"returns\":{\"_0\":\"Owner of the coordinator\"}},\"pendingOwner()\":{\"returns\":{\"_0\":\"Owner of the protocol\"}},\"pendingOwner(uint256)\":{\"params\":{\"coordinatorId\":\"Coordinator to return for\"},\"returns\":{\"_0\":\"Pending owner of the coordinator\"}},\"treasury()\":{\"details\":\"Defaults to the `owner` when `treasury` is unset\",\"returns\":{\"_0\":\"Treasury of the protocol\"}},\"treasury(address)\":{\"details\":\"Defaults to the `owner` when `treasury` is unset\",\"params\":{\"product\":\"Product to return for\"},\"returns\":{\"_0\":\"Treasury of the product\"}},\"treasury(uint256)\":{\"details\":\"Defaults to the `owner` when `treasury` is unset\",\"params\":{\"coordinatorId\":\"Coordinator to return for\"},\"returns\":{\"_0\":\"Treasury of the coordinator\"}},\"updateCollateral(address)\":{\"params\":{\"newCollateral\":\"New Collateral contract address\"}},\"updateCoordinatorPendingOwner(uint256,address)\":{\"details\":\"Must be called by the coordinator's current owner\",\"params\":{\"coordinatorId\":\"Coordinator to update\",\"newPendingOwner\":\"New pending owner address\"}},\"updateCoordinatorTreasury(uint256,address)\":{\"details\":\"Must be called by the coordinator's current owner. Defaults to the coordinator `owner` if set to address(0)\",\"params\":{\"coordinatorId\":\"Coordinator to update\",\"newTreasury\":\"New treasury address\"}},\"updateIncentivizationFee(uint256)\":{\"params\":{\"newIncentivizationFee\":\"New incentivization fee\"}},\"updateIncentivizer(address)\":{\"params\":{\"newIncentivizer\":\"New Incentivizer contract address\"}},\"updateLiquidationFee(uint256)\":{\"params\":{\"newLiquidationFee\":\"New liquidation fee\"}},\"updateMinCollateral(uint256)\":{\"params\":{\"newMinCollateral\":\"New minimum allowed collateral amount\"}},\"updateMinFundingFee(uint256)\":{\"params\":{\"newMinFundingFee\":\"New minimum allowed funding fee\"}},\"updatePaused(bool)\":{\"params\":{\"newPaused\":\"New protocol paused state\"}},\"updatePauser(address)\":{\"params\":{\"newPauser\":\"New protocol pauser address\"}},\"updateProductBeacon(address)\":{\"params\":{\"newProductBeacon\":\"New Product implementation beacon address\"}},\"updateProgramsPerProduct(uint256)\":{\"params\":{\"newProgramsPerProduct\":\"New maximum incentivization programs per product allowed\"}},\"updateProtocolFee(uint256)\":{\"params\":{\"newProtocolFee\":\"New protocol-product fee split\"}}},\"stateVariables\":{\"_collateral\":{\"details\":\"Collateral contract address for the protocol\"},\"_coordinators\":{\"details\":\"List of product coordinators\"},\"_incentivizationFee\":{\"details\":\"Fee on incentivization programs\"},\"_incentivizer\":{\"details\":\"Incentivizer contract address for the protocol\"},\"_liquidationFee\":{\"details\":\"Fee on maintenance for liquidation\"},\"_minCollateral\":{\"details\":\"Minimum allowable collateral amount per user account\"},\"_minFundingFee\":{\"details\":\"Minimum allowable funding fee for a product\"},\"_paused\":{\"details\":\"The paused status of the protocol\"},\"_pauser\":{\"details\":\"Protocol pauser address. address(0) defaults to owner(0)\"},\"_productBeacon\":{\"details\":\"Product implementation beacon address for the protocol\"},\"_programsPerProduct\":{\"details\":\"Maximum incentivization programs per product allowed\"},\"_protocolFee\":{\"details\":\"Percent of collected fees that go to the protocol treasury vs the product treasury\"},\"coordinatorFor\":{\"details\":\"Mapping of the coordinator for each  product\"}},\"title\":\"Controller\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptCoordinatorOwner(uint256)\":{\"notice\":\"Accepts ownership over an existing coordinator\"},\"coordinators(uint256)\":{\"notice\":\"Returns coordinator state for coordinator `coordinatorId`\"},\"createCoordinator()\":{\"notice\":\"Creates a new coordinator with `msg.sender` as the owner\"},\"createProduct(uint256,(string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))\":{\"notice\":\"Creates a new product market with `provider`\"},\"initialize(address,address,address)\":{\"notice\":\"Initializes the contract state\"},\"isProduct(address)\":{\"notice\":\"Returns whether a contract is a product\"},\"owner()\":{\"notice\":\"Returns the owner of the protocol\"},\"owner(address)\":{\"notice\":\"Returns the owner of the product `product`\"},\"owner(uint256)\":{\"notice\":\"Returns the owner of the coordinator `coordinatorId`\"},\"pendingOwner()\":{\"notice\":\"Returns the pending owner of the protocol\"},\"pendingOwner(uint256)\":{\"notice\":\"Returns the pending owner of the coordinator `coordinatorId`\"},\"treasury()\":{\"notice\":\"Returns the treasury of the protocol\"},\"treasury(address)\":{\"notice\":\"Returns the treasury of the product `product`\"},\"treasury(uint256)\":{\"notice\":\"Returns the treasury of the coordinator `coordinatorId`\"},\"updateCollateral(address)\":{\"notice\":\"Updates the Collateral contract address\"},\"updateCoordinatorPendingOwner(uint256,address)\":{\"notice\":\"Updates the pending owner of an existing coordinator\"},\"updateCoordinatorTreasury(uint256,address)\":{\"notice\":\"Updates the treasury of an existing coordinator\"},\"updateIncentivizationFee(uint256)\":{\"notice\":\"Updates the incentivization fee\"},\"updateIncentivizer(address)\":{\"notice\":\"Updates the Incentivizer contract address\"},\"updateLiquidationFee(uint256)\":{\"notice\":\"Updates the liquidation fee\"},\"updateMinCollateral(uint256)\":{\"notice\":\"Updates the minimum allowed collateral amount per user account\"},\"updateMinFundingFee(uint256)\":{\"notice\":\"Updates the minimum allowed funding fee\"},\"updatePaused(bool)\":{\"notice\":\"Updates the protocol paused state\"},\"updatePauser(address)\":{\"notice\":\"Updates the protocol pauser address. Zero address defaults to owner(0)\"},\"updateProductBeacon(address)\":{\"notice\":\"Updates the Product implementation beacon address\"},\"updateProgramsPerProduct(uint256)\":{\"notice\":\"Updates the maximum incentivization programs per product allowed\"},\"updateProtocolFee(uint256)\":{\"notice\":\"Updates the protocol-product fee split\"}},\"notice\":\"Manages creating new products and global protocol parameters.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/controller/Controller.sol\":\"Controller\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"@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 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\",\"keccak256\":\"0xde0f20d468ba8b91addfc356e13f2c74a4dc8abe68be323942217c723775d9c1\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0xd2743d8fcc220ed2ccdc0bba1db0a3e107741bd5c0cac47ca8c0b5a00ba2fd7f\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0x60d159f9ddf0dbe81124ecad58bba734b4cf82877637ff8d9d7f3e92f2da4ded\",\"license\":\"Apache-2.0\"},\"@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}\",\"keccak256\":\"0xae202813874bc306d51b3dab8194c86f6483bb20bf1f673ddaee16aa8de567ff\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0x613587461ef3437ef33229cdda7d34ea746278721baf06e20b2e43977f43174d\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0xb52960cc8e3132e45d342bbbb1c6a96219022cd8557997933bd8250170268b64\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0xb5c5cd32d6530b2fe75228b6be32ebcb7762f6d7988b85a6b85a289ce8256d51\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0x8ebef1e6c717f565b9ed545a876b5692b4007e6485c99f39d363f7405e591792\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0xe2b8491d1b5aa93f7e059e1a8f156b0ab37fef9ed973be97a64f2eabfc2cc172\",\"license\":\"Apache-2.0\"},\"@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\",\"keccak256\":\"0x6b12afaece814f0ab186200a4729e93eb685a21d3e9b5a3372ff283a7ad5dc23\",\"license\":\"Apache-2.0\"},\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n    /**\\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n     * address.\\n     *\\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n     * function revert if invoked through a proxy.\\n     */\\n    function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n    // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n    /**\\n     * @dev Storage slot with the address of the current implementation.\\n     * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n     * validated in the constructor.\\n     */\\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n    /**\\n     * @dev Emitted when the implementation is upgraded.\\n     */\\n    event Upgraded(address indexed implementation);\\n\\n    /**\\n     * @dev Returns the current implementation address.\\n     */\\n    function _getImplementation() internal view returns (address) {\\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n    }\\n\\n    /**\\n     * @dev Stores a new address in the EIP1967 implementation slot.\\n     */\\n    function _setImplementation(address newImplementation) private {\\n        require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n    }\\n\\n    /**\\n     * @dev Perform implementation upgrade\\n     *\\n     * Emits an {Upgraded} event.\\n     */\\n    function _upgradeTo(address newImplementation) internal {\\n        _setImplementation(newImplementation);\\n        emit Upgraded(newImplementation);\\n    }\\n\\n    /**\\n     * @dev Perform implementation upgrade with additional setup call.\\n     *\\n     * Emits an {Upgraded} event.\\n     */\\n    function _upgradeToAndCall(\\n        address newImplementation,\\n        bytes memory data,\\n        bool forceCall\\n    ) internal {\\n        _upgradeTo(newImplementation);\\n        if (data.length > 0 || forceCall) {\\n            Address.functionDelegateCall(newImplementation, data);\\n        }\\n    }\\n\\n    /**\\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n     *\\n     * Emits an {Upgraded} event.\\n     */\\n    function _upgradeToAndCallUUPS(\\n        address newImplementation,\\n        bytes memory data,\\n        bool forceCall\\n    ) internal {\\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n            _setImplementation(newImplementation);\\n        } else {\\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n                require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n            } catch {\\n                revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n            }\\n            _upgradeToAndCall(newImplementation, data, forceCall);\\n        }\\n    }\\n\\n    /**\\n     * @dev Storage slot with the admin of the contract.\\n     * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n     * validated in the constructor.\\n     */\\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n    /**\\n     * @dev Emitted when the admin account has changed.\\n     */\\n    event AdminChanged(address previousAdmin, address newAdmin);\\n\\n    /**\\n     * @dev Returns the current admin.\\n     */\\n    function _getAdmin() internal view returns (address) {\\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n    }\\n\\n    /**\\n     * @dev Stores a new address in the EIP1967 admin slot.\\n     */\\n    function _setAdmin(address newAdmin) private {\\n        require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n    }\\n\\n    /**\\n     * @dev Changes the admin of the proxy.\\n     *\\n     * Emits an {AdminChanged} event.\\n     */\\n    function _changeAdmin(address newAdmin) internal {\\n        emit AdminChanged(_getAdmin(), newAdmin);\\n        _setAdmin(newAdmin);\\n    }\\n\\n    /**\\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n     */\\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n    /**\\n     * @dev Emitted when the beacon is upgraded.\\n     */\\n    event BeaconUpgraded(address indexed beacon);\\n\\n    /**\\n     * @dev Returns the current beacon.\\n     */\\n    function _getBeacon() internal view returns (address) {\\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n    }\\n\\n    /**\\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\\n     */\\n    function _setBeacon(address newBeacon) private {\\n        require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n        require(\\n            Address.isContract(IBeacon(newBeacon).implementation()),\\n            \\\"ERC1967: beacon implementation is not a contract\\\"\\n        );\\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n    }\\n\\n    /**\\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n     *\\n     * Emits a {BeaconUpgraded} event.\\n     */\\n    function _upgradeBeaconToAndCall(\\n        address newBeacon,\\n        bytes memory data,\\n        bool forceCall\\n    ) internal {\\n        _setBeacon(newBeacon);\\n        emit BeaconUpgraded(newBeacon);\\n        if (data.length > 0 || forceCall) {\\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xabf3f59bc0e5423eae45e459dbe92e7052c6983628d39008590edc852a62f94a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n    /**\\n     * @dev Delegates the current call to `implementation`.\\n     *\\n     * This function does not return to its internal call site, it will return directly to the external caller.\\n     */\\n    function _delegate(address implementation) internal virtual {\\n        assembly {\\n            // Copy msg.data. We take full control of memory in this inline assembly\\n            // block because it will not return to Solidity code. We overwrite the\\n            // Solidity scratch pad at memory position 0.\\n            calldatacopy(0, 0, calldatasize())\\n\\n            // Call the implementation.\\n            // out and outsize are 0 because we don't know the size yet.\\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n            // Copy the returned data.\\n            returndatacopy(0, 0, returndatasize())\\n\\n            switch result\\n            // delegatecall returns 0 on error.\\n            case 0 {\\n                revert(0, returndatasize())\\n            }\\n            default {\\n                return(0, returndatasize())\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\\n     * and {_fallback} should delegate.\\n     */\\n    function _implementation() internal view virtual returns (address);\\n\\n    /**\\n     * @dev Delegates the current call to the address returned by `_implementation()`.\\n     *\\n     * This function does not return to its internal call site, it will return directly to the external caller.\\n     */\\n    function _fallback() internal virtual {\\n        _beforeFallback();\\n        _delegate(_implementation());\\n    }\\n\\n    /**\\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n     * function in the contract matches the call data.\\n     */\\n    fallback() external payable virtual {\\n        _fallback();\\n    }\\n\\n    /**\\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n     * is empty.\\n     */\\n    receive() external payable virtual {\\n        _fallback();\\n    }\\n\\n    /**\\n     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n     * call, or as part of the Solidity `fallback` or `receive` functions.\\n     *\\n     * If overridden should call `super._beforeFallback()`.\\n     */\\n    function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\\n *\\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\\n * conflict with the storage layout of the implementation behind the proxy.\\n *\\n * _Available since v3.4._\\n */\\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\\n    /**\\n     * @dev Initializes the proxy with `beacon`.\\n     *\\n     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\\n     * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\\n     * constructor.\\n     *\\n     * Requirements:\\n     *\\n     * - `beacon` must be a contract with the interface {IBeacon}.\\n     */\\n    constructor(address beacon, bytes memory data) payable {\\n        assert(_BEACON_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.beacon\\\")) - 1));\\n        _upgradeBeaconToAndCall(beacon, data, false);\\n    }\\n\\n    /**\\n     * @dev Returns the current beacon address.\\n     */\\n    function _beacon() internal view virtual returns (address) {\\n        return _getBeacon();\\n    }\\n\\n    /**\\n     * @dev Returns the current implementation address of the associated beacon.\\n     */\\n    function _implementation() internal view virtual override returns (address) {\\n        return IBeacon(_getBeacon()).implementation();\\n    }\\n\\n    /**\\n     * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\\n     *\\n     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\\n     *\\n     * Requirements:\\n     *\\n     * - `beacon` must be a contract.\\n     * - The implementation returned by `beacon` must be a contract.\\n     */\\n    function _setBeacon(address beacon, bytes memory data) internal virtual {\\n        _upgradeBeaconToAndCall(beacon, data, false);\\n    }\\n}\\n\",\"keccak256\":\"0x54878f0d2f40b5e13f84977bcd3c71d4c38581414e7efb4909cb16dd3ace392f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n *     function _getImplementation() internal view returns (address) {\\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n *     }\\n *\\n *     function _setImplementation(address newImplementation) internal {\\n *         require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n *     }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n    struct AddressSlot {\\n        address value;\\n    }\\n\\n    struct BooleanSlot {\\n        bool value;\\n    }\\n\\n    struct Bytes32Slot {\\n        bytes32 value;\\n    }\\n\\n    struct Uint256Slot {\\n        uint256 value;\\n    }\\n\\n    /**\\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n     */\\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n        assembly {\\n            r.slot := slot\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n     */\\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n        assembly {\\n            r.slot := slot\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n     */\\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n        assembly {\\n            r.slot := slot\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n     */\\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n        assembly {\\n            r.slot := slot\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\"},\"contracts/controller/Controller.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.15;\\n\\nimport \\\"@equilibria/root/control/unstructured/UInitializable.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\\\";\\nimport \\\"../interfaces/IController.sol\\\";\\nimport \\\"../interfaces/ICollateral.sol\\\";\\nimport \\\"../interfaces/IIncentivizer.sol\\\";\\nimport \\\"../interfaces/IProduct.sol\\\";\\n\\n/**\\n * @title Controller\\n * @notice Manages creating new products and global protocol parameters.\\n */\\ncontract Controller is IController, UInitializable {\\n    /// @dev Collateral contract address for the protocol\\n    AddressStorage private constant _collateral = AddressStorage.wrap(keccak256(\\\"equilibria.perennial.Controller.collateral\\\"));\\n    function collateral() public view returns (ICollateral) { return ICollateral(_collateral.read()); }\\n\\n    /// @dev Incentivizer contract address for the protocol\\n    AddressStorage private constant _incentivizer = AddressStorage.wrap(keccak256(\\\"equilibria.perennial.Controller.incentivizer\\\"));\\n    function incentivizer() public view returns (IIncentivizer) { return IIncentivizer(_incentivizer.read()); }\\n\\n    /// @dev Product implementation beacon address for the protocol\\n    AddressStorage private constant _productBeacon = AddressStorage.wrap(keccak256(\\\"equilibria.perennial.Controller.productBeacon\\\"));\\n    function productBeacon() public view returns (IBeacon) { return IBeacon(_productBeacon.read()); }\\n\\n    /// @dev Percent of collected fees that go to the protocol treasury vs the product treasury\\n    UFixed18Storage private constant _protocolFee = UFixed18Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.protocolFee\\\"));\\n    function protocolFee() public view returns (UFixed18) { return _protocolFee.read(); }\\n\\n    /// @dev Minimum allowable funding fee for a product\\n    UFixed18Storage private constant _minFundingFee = UFixed18Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.minFundingFee\\\"));\\n    function minFundingFee() public view returns (UFixed18) { return _minFundingFee.read(); }\\n\\n    /// @dev Fee on maintenance for liquidation\\n    UFixed18Storage private constant _liquidationFee = UFixed18Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.liquidationFee\\\"));\\n    function liquidationFee() public view returns (UFixed18) { return _liquidationFee.read(); }\\n\\n    /// @dev Fee on incentivization programs\\n    UFixed18Storage private constant _incentivizationFee = UFixed18Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.incentivizationFee\\\"));\\n    function incentivizationFee() public view returns (UFixed18) { return _incentivizationFee.read(); }\\n\\n    /// @dev Minimum allowable collateral amount per user account\\n    UFixed18Storage private constant _minCollateral = UFixed18Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.minCollateral\\\"));\\n    function minCollateral() public view returns (UFixed18) { return _minCollateral.read(); }\\n\\n    /// @dev Maximum incentivization programs per product allowed\\n    Uint256Storage private constant _programsPerProduct = Uint256Storage.wrap(keccak256(\\\"equilibria.perennial.Controller.programsPerProduct\\\"));\\n    function programsPerProduct() public view returns (uint256) { return _programsPerProduct.read(); }\\n\\n    /// @dev Protocol pauser address. address(0) defaults to owner(0)\\n    AddressStorage private constant _pauser = AddressStorage.wrap(keccak256(\\\"equilibria.perennial.Controller.pauser\\\"));\\n    function pauser() public view returns (address) {\\n        address pauser_ = _pauser.read();\\n        return pauser_ == address(0) ? owner() : pauser_;\\n    }\\n\\n    /// @dev The paused status of the protocol\\n    BoolStorage private constant _paused = BoolStorage.wrap(keccak256(\\\"equilibria.perennial.Controller.paused\\\"));\\n    function paused() public view returns (bool) { return _paused.read(); }\\n\\n    /// @dev List of product coordinators\\n    Coordinator[] private _coordinators;\\n\\n    /// @dev Mapping of the coordinator for each  product\\n    mapping(IProduct => uint256) public coordinatorFor;\\n\\n    /**\\n     * @notice Initializes the contract state\\n     * @dev Must be called atomically as part of the upgradeable proxy deployment to\\n     *      avoid front-running\\n     * @param collateral_ Collateral contract address\\n     * @param incentivizer_ Incentivizer contract address\\n     * @param productBeacon_ Product implementation beacon address\\n     */\\n    function initialize(\\n        ICollateral collateral_,\\n        IIncentivizer incentivizer_,\\n        IBeacon productBeacon_\\n    ) external initializer(1) {\\n        _createCoordinator();\\n\\n        updateCollateral(collateral_);\\n        updateIncentivizer(incentivizer_);\\n        updateProductBeacon(productBeacon_);\\n    }\\n\\n    /**\\n     * @notice Creates a new coordinator with `msg.sender` as the owner\\n     * @dev Can only be called by the protocol owner\\n     * @return New coordinator ID\\n     */\\n    function createCoordinator() external returns (uint256) {\\n        return _createCoordinator();\\n    }\\n\\n    /**\\n     * @notice Creates a new coordinator with `msg.sender` as the owner\\n     * @dev `treasury` and `pauser` initialize as the 0-address, defaulting to the `owner`\\n     * @return New coordinator ID\\n     */\\n    function _createCoordinator() private returns (uint256) {\\n        uint256 coordinatorId = _coordinators.length;\\n\\n        _coordinators.push(Coordinator({\\n            pendingOwner: address(0),\\n            owner: msg.sender,\\n            treasury: address(0)\\n        }));\\n\\n        emit CoordinatorCreated(coordinatorId, msg.sender);\\n\\n        return coordinatorId;\\n    }\\n\\n    /**\\n     * @notice Updates the pending owner of an existing coordinator\\n     * @dev Must be called by the coordinator's current owner\\n     * @param coordinatorId Coordinator to update\\n     * @param newPendingOwner New pending owner address\\n     */\\n    function updateCoordinatorPendingOwner(uint256 coordinatorId, address newPendingOwner) external onlyOwner(coordinatorId) {\\n        _coordinators[coordinatorId].pendingOwner = newPendingOwner;\\n        emit CoordinatorPendingOwnerUpdated(coordinatorId, newPendingOwner);\\n    }\\n\\n    /**\\n     * @notice Accepts ownership over an existing coordinator\\n     * @dev Must be called by the coordinator's pending owner\\n     * @param coordinatorId Coordinator to update\\n     */\\n    function acceptCoordinatorOwner(uint256 coordinatorId) external {\\n        Coordinator storage coordinator = _coordinators[coordinatorId];\\n        address newPendingOwner = coordinator.pendingOwner;\\n\\n        if (msg.sender != newPendingOwner) revert ControllerNotPendingOwnerError(coordinatorId);\\n\\n        coordinator.pendingOwner = address(0);\\n        coordinator.owner = newPendingOwner;\\n        emit CoordinatorOwnerUpdated(coordinatorId, newPendingOwner);\\n    }\\n\\n    /**\\n     * @notice Updates the treasury of an existing coordinator\\n     * @dev Must be called by the coordinator's current owner. Defaults to the coordinator `owner` if set to address(0)\\n     * @param coordinatorId Coordinator to update\\n     * @param newTreasury New treasury address\\n     */\\n    function updateCoordinatorTreasury(uint256 coordinatorId, address newTreasury) external onlyOwner(coordinatorId) {\\n        _coordinators[coordinatorId].treasury = newTreasury;\\n        emit CoordinatorTreasuryUpdated(coordinatorId, newTreasury);\\n    }\\n\\n    /**\\n     * @notice Creates a new product market with `provider`\\n     * @dev Can only be called by the coordinator owner\\n     * @param coordinatorId Coordinator that will own the product\\n     * @param productInfo Product params used to initialize the product\\n     * @return New product contract address\\n     */\\n    function createProduct(uint256 coordinatorId, IProduct.ProductInfo calldata productInfo)\\n    external onlyOwner(coordinatorId) returns (IProduct) {\\n        if (coordinatorId == 0) revert ControllerNoZeroCoordinatorError();\\n\\n        BeaconProxy newProductProxy = new BeaconProxy(address(productBeacon()), abi.encodeCall(IProduct.initialize, productInfo));\\n        IProduct newProduct = IProduct(address(newProductProxy));\\n        coordinatorFor[newProduct] = coordinatorId;\\n        emit ProductCreated(newProduct, productInfo);\\n\\n        return newProduct;\\n    }\\n\\n    /**\\n     * @notice Updates the Collateral contract address\\n     * @param newCollateral New Collateral contract address\\n     */\\n    function updateCollateral(ICollateral newCollateral) public onlyOwner(0) {\\n        if (!Address.isContract(address(newCollateral))) revert ControllerNotContractAddressError();\\n        _collateral.store(address(newCollateral));\\n        emit CollateralUpdated(newCollateral);\\n    }\\n\\n    /**\\n     * @notice Updates the Incentivizer contract address\\n     * @param newIncentivizer New Incentivizer contract address\\n     */\\n    function updateIncentivizer(IIncentivizer newIncentivizer) public onlyOwner(0) {\\n        if (!Address.isContract(address(newIncentivizer))) revert ControllerNotContractAddressError();\\n        _incentivizer.store(address(newIncentivizer));\\n        emit IncentivizerUpdated(newIncentivizer);\\n    }\\n\\n    /**\\n     * @notice Updates the Product implementation beacon address\\n     * @param newProductBeacon New Product implementation beacon address\\n     */\\n    function updateProductBeacon(IBeacon newProductBeacon) public onlyOwner(0) {\\n        if (!Address.isContract(address(newProductBeacon))) revert ControllerNotContractAddressError();\\n        _productBeacon.store(address(newProductBeacon));\\n        emit ProductBeaconUpdated(newProductBeacon);\\n    }\\n\\n    /**\\n     * @notice Updates the protocol-product fee split\\n     * @param newProtocolFee New protocol-product fee split\\n     */\\n    function updateProtocolFee(UFixed18 newProtocolFee) public onlyOwner(0) {\\n        if (newProtocolFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidProtocolFeeError();\\n\\n        _protocolFee.store(newProtocolFee);\\n        emit ProtocolFeeUpdated(newProtocolFee);\\n    }\\n\\n    /**\\n     * @notice Updates the minimum allowed funding fee\\n     * @param newMinFundingFee New minimum allowed funding fee\\n     */\\n    function updateMinFundingFee(UFixed18 newMinFundingFee) public onlyOwner(0) {\\n        if (newMinFundingFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidMinFundingFeeError();\\n\\n        _minFundingFee.store(newMinFundingFee);\\n        emit MinFundingFeeUpdated(newMinFundingFee);\\n    }\\n\\n    /**\\n     * @notice Updates the liquidation fee\\n     * @param newLiquidationFee New liquidation fee\\n     */\\n    function updateLiquidationFee(UFixed18 newLiquidationFee) public onlyOwner(0) {\\n        if (newLiquidationFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidLiquidationFeeError();\\n\\n        _liquidationFee.store(newLiquidationFee);\\n        emit LiquidationFeeUpdated(newLiquidationFee);\\n    }\\n\\n    /**\\n     * @notice Updates the incentivization fee\\n     * @param newIncentivizationFee New incentivization fee\\n     */\\n    function updateIncentivizationFee(UFixed18 newIncentivizationFee) public onlyOwner(0) {\\n        if (newIncentivizationFee.gt(UFixed18Lib.ONE)) revert ControllerInvalidIncentivizationFeeError();\\n\\n        _incentivizationFee.store(newIncentivizationFee);\\n        emit IncentivizationFeeUpdated(newIncentivizationFee);\\n    }\\n\\n    /**\\n     * @notice Updates the minimum allowed collateral amount per user account\\n     * @param newMinCollateral New minimum allowed collateral amount\\n     */\\n    function updateMinCollateral(UFixed18 newMinCollateral) public onlyOwner(0) {\\n        _minCollateral.store(newMinCollateral);\\n        emit MinCollateralUpdated(newMinCollateral);\\n    }\\n\\n    /**\\n     * @notice Updates the maximum incentivization programs per product allowed\\n     * @param newProgramsPerProduct New maximum incentivization programs per product allowed\\n     */\\n    function updateProgramsPerProduct(uint256 newProgramsPerProduct) public onlyOwner(0) {\\n        _programsPerProduct.store(newProgramsPerProduct);\\n        emit ProgramsPerProductUpdated(newProgramsPerProduct);\\n    }\\n\\n    /**\\n     * @notice Updates the protocol pauser address. Zero address defaults to owner(0)\\n     * @param newPauser New protocol pauser address\\n     */\\n    function updatePauser(address newPauser) public onlyOwner(0) {\\n        _pauser.store(newPauser);\\n        emit PauserUpdated(newPauser);\\n    }\\n\\n    /**\\n     * @notice Updates the protocol paused state\\n     * @param newPaused New protocol paused state\\n     */\\n    function updatePaused(bool newPaused) public onlyPauser {\\n        _paused.store(newPaused);\\n        emit PausedUpdated(newPaused);\\n    }\\n\\n    /**\\n     * @notice Returns whether a contract is a product\\n     * @param product Contract address to check\\n     * @return Whether a contract is a product\\n     */\\n    function isProduct(IProduct product) external view returns (bool) {\\n        return coordinatorFor[product] != 0;\\n    }\\n\\n    /**\\n     * @notice Returns coordinator state for coordinator `coordinatorId`\\n     * @param coordinatorId Coordinator to return for\\n     * @return Coordinator state\\n     */\\n    function coordinators(uint256 coordinatorId) external view returns (Coordinator memory) {\\n        return _coordinators[coordinatorId];\\n    }\\n\\n    /**\\n     * @notice Returns the pending owner of the protocol\\n     * @return Owner of the protocol\\n     */\\n    function pendingOwner() public view returns (address) {\\n        return pendingOwner(0);\\n    }\\n\\n    /**\\n     * @notice Returns the pending owner of the coordinator `coordinatorId`\\n     * @param coordinatorId Coordinator to return for\\n     * @return Pending owner of the coordinator\\n     */\\n    function pendingOwner(uint256 coordinatorId) public view returns (address) {\\n        return _coordinators[coordinatorId].pendingOwner;\\n    }\\n\\n    /**\\n     * @notice Returns the owner of the protocol\\n     * @return Owner of the protocol\\n     */\\n    function owner() public view returns (address) {\\n        return owner(0);\\n    }\\n\\n    /**\\n     * @notice Returns the owner of the coordinator `coordinatorId`\\n     * @param coordinatorId Coordinator to return for\\n     * @return Owner of the coordinator\\n     */\\n    function owner(uint256 coordinatorId) public view returns (address) {\\n        return _coordinators[coordinatorId].owner;\\n    }\\n\\n    /**\\n     * @notice Returns the owner of the product `product`\\n     * @param product Product to return for\\n     * @return Owner of the product\\n     */\\n    function owner(IProduct product) external view returns (address) {\\n        return owner(coordinatorFor[product]);\\n    }\\n\\n    /**\\n     * @notice Returns the treasury of the protocol\\n     * @dev Defaults to the `owner` when `treasury` is unset\\n     * @return Treasury of the protocol\\n     */\\n    function treasury() external view returns (address) {\\n        return treasury(0);\\n    }\\n\\n    /**\\n     * @notice Returns the treasury of the coordinator `coordinatorId`\\n     * @dev Defaults to the `owner` when `treasury` is unset\\n     * @param coordinatorId Coordinator to return for\\n     * @return Treasury of the coordinator\\n     */\\n    function treasury(uint256 coordinatorId) public view returns (address) {\\n        address _treasury = _coordinators[coordinatorId].treasury;\\n        return _treasury == address(0) ? owner(coordinatorId) : _treasury;\\n    }\\n\\n    /**\\n     * @notice Returns the treasury of the product `product`\\n     * @dev Defaults to the `owner` when `treasury` is unset\\n     * @param product Product to return for\\n     * @return Treasury of the product\\n     */\\n    function treasury(IProduct product) external view returns (address) {\\n        return treasury(coordinatorFor[product]);\\n    }\\n\\n    /// @dev Only allow owner of `coordinatorId` to call\\n    modifier onlyOwner(uint256 coordinatorId) {\\n        if (msg.sender != owner(coordinatorId)) revert ControllerNotOwnerError(coordinatorId);\\n\\n        _;\\n    }\\n\\n    /// @dev Only allow the pauser to call\\n    modifier onlyPauser {\\n        if (msg.sender != pauser()) revert ControllerNotPauserError();\\n\\n        _;\\n    }\\n}\\n\",\"keccak256\":\"0x40cde49450e3c3e476490d5eddd34e5ad96956de89e7a18cfa900da5ab5696d4\",\"license\":\"Apache-2.0\"},\"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\\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 account, 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\",\"keccak256\":\"0xa5e7fdda92702f748e6eb8701e522450035a98a05e5fc1cf66d51c52e397d914\",\"license\":\"Apache-2.0\"},\"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\",\"keccak256\":\"0xd73df106d032e976fd959ee6713240e36f54277ce5f215eaec8d5a2c6720a86b\",\"license\":\"Apache-2.0\"},\"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 \\\"./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 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 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 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\",\"keccak256\":\"0xaabd3740f2265499eea7aad9bd94f9892f53241e5dccce9a50c0e43ed2a6a7cc\",\"license\":\"Apache-2.0\"},\"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 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\",\"keccak256\":\"0x2f95de90dbb3ad35dbfef304f765a622bffff9229868d2898eca8d49c78e8c2c\",\"license\":\"Apache-2.0\"},\"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\\\";\\n\\ninterface IParamProvider {\\n    event MaintenanceUpdated(UFixed18 newMaintenance);\\n    event FundingFeeUpdated(UFixed18 newFundingFee);\\n    event MakerFeeUpdated(UFixed18 newMakerFee);\\n    event TakerFeeUpdated(UFixed18 newTakerFee);\\n    event MakerLimitUpdated(UFixed18 newMakerLimit);\\n    event JumpRateUtilizationCurveUpdated(\\n        Fixed18 minRate,\\n        Fixed18 maxRate,\\n        Fixed18 targetRate,\\n        UFixed18 targetUtilization\\n    );\\n\\n    error ParamProviderInvalidMakerFee();\\n    error ParamProviderInvalidTakerFee();\\n    error ParamProviderInvalidFundingFee();\\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 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}\\n\",\"keccak256\":\"0x2e2d40d0cf55f167118867e41f740b9b40614d05da50fc9bc33a8cede3eaf03e\",\"license\":\"Apache-2.0\"},\"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    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\",\"keccak256\":\"0xb83d80d624aa9431763f80ecb4bf0214803e25334a7419d954f929e5d0ee7467\",\"license\":\"Apache-2.0\"},\"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 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 ProductNotOwnerError();\\n    error ProductInvalidOracle();\\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 closeTake(UFixed18 amount) external;\\n    function openMake(UFixed18 amount) external;\\n    function closeMake(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}\\n\",\"keccak256\":\"0xe1e80b818eadf4cdb070362e40c7cf3863b50c4f944816af27848e319f587241\",\"license\":\"Apache-2.0\"},\"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\",\"keccak256\":\"0x7ccd0a72aa593cefb9f4337cf312799f357b82fcb3f0379de0dc503d1cb7e387\",\"license\":\"Apache-2.0\"},\"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\",\"keccak256\":\"0xd83f2822d4f6c818087a232b54007730992c34ff77377fc307a282f886e7cf65\",\"license\":\"Apache-2.0\"},\"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\",\"keccak256\":\"0x04968e6794f6244cb3415cea111d640273a81faea957872988d0cb580f45df1e\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/types/PayoffDefinition.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity 0.8.15;\\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 }\\n    }\\n}\\n\",\"keccak256\":\"0x4d3897f408f77381c5ae9990391465c8fd511ddf6ff3b39f6cb69d8c2bd554df\",\"license\":\"Apache-2.0\"},\"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 Fee accrued from opening or closing the position\\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 view returns (Position memory, UFixed18, bool) {\\n        return pre.canSettle(toOracleVersion) ? (next(self, pre), pre.computeFee(toOracleVersion), true) : (self, UFixed18Lib.ZERO, 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\",\"keccak256\":\"0x027fe392c4f56bf012ba2ca462fcf23e69f2c3b9d283c14089771813437af991\",\"license\":\"Apache-2.0\"},\"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     * @dev Can be \\\"empty\\\" even with a non-zero oracleVersion if a position is opened and\\n     *      closed in the same version netting out to a zero 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     * @dev Nets out open and close deltas to minimize the size of each\\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        _netMake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the maker side of the close position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\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        _netMake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the taker side of the open position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\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        _netTake(self);\\n    }\\n\\n    /**\\n     * @notice Increments the taker side of the close position delta\\n     * @dev Nets out open and close deltas to minimize the size of each\\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        _netTake(self);\\n    }\\n\\n    /**\\n     * @notice Nets out the open and close on the maker side of the position delta\\n     * @param self The struct to operate on\\n     */\\n    function _netMake(PrePosition storage self) private {\\n        if (self.openPosition.maker.gt(self.closePosition.maker)) {\\n            self.openPosition.maker = self.openPosition.maker.sub(self.closePosition.maker);\\n            self.closePosition.maker = UFixed18Lib.ZERO;\\n        } else {\\n            self.closePosition.maker = self.closePosition.maker.sub(self.openPosition.maker);\\n            self.openPosition.maker = UFixed18Lib.ZERO;\\n        }\\n    }\\n\\n    /**\\n     * @notice Nets out the open and close on the taker side of the position delta\\n     * @param self The struct to operate on\\n     */\\n    function _netTake(PrePosition storage self) private {\\n        if (self.openPosition.taker.gt(self.closePosition.taker)) {\\n            self.openPosition.taker = self.openPosition.taker.sub(self.closePosition.taker);\\n            self.closePosition.taker = UFixed18Lib.ZERO;\\n        } else {\\n            self.closePosition.taker = self.closePosition.taker.sub(self.openPosition.taker);\\n            self.openPosition.taker = UFixed18Lib.ZERO;\\n        }\\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 !isEmpty(self) && 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 toOracleVersion The oracle version at which settlement takes place\\n     * @return positionFee The maker / taker fee incurred\\n     */\\n    function computeFee(\\n        PrePosition memory self,\\n        IOracleProvider.OracleVersion memory toOracleVersion\\n    ) internal view returns (UFixed18) {\\n        Position memory positionDelta = self.openPosition.add(self.closePosition);\\n\\n        (UFixed18 makerNotional, UFixed18 takerNotional) = (\\n            Fixed18Lib.from(positionDelta.maker).mul(toOracleVersion.price).abs(),\\n            Fixed18Lib.from(positionDelta.taker).mul(toOracleVersion.price).abs()\\n        );\\n\\n        IProduct product = IProduct(address(this));\\n        return makerNotional.mul(product.makerFee()).add(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\",\"keccak256\":\"0xa6f83f7b5f8139ec874235c406debd086a152977493c08b7f280df6f1737fb96\",\"license\":\"Apache-2.0\"},\"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\",\"keccak256\":\"0x280fcaf931b49abaec46b95ccbabaaf856a4b8e8d036413c9c3b3af25585d161\",\"license\":\"Apache-2.0\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50612de7806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620002e45760003560e01c80637a7da0041162000199578063a36a363011620000e9578063d809aa611162000097578063e30c3978116200007a578063e30c39781462000638578063e975c0c31462000642578063f8dfc2cc146200064c57600080fd5b8063d809aa611462000617578063d8dfeb45146200062e57600080fd5b8063b0e21e8a11620000cc578063b0e21e8a14620005ec578063ba2de9bc14620005f6578063c0c53b8b146200060057600080fd5b8063a36a363014620005cb578063af2757b714620005d557600080fd5b80638da5cb5b11620001475780639fd0506d116200012a5780639fd0506d1462000593578063a123c33e146200059d578063a1eef78e14620005b457600080fd5b80638da5cb5b14620005725780638fbf1803146200057c57600080fd5b80637d254e66116200017c5780637d254e66146200050a5780637d49c1b7146200052d5780637fd29192146200053757600080fd5b80637a7da00414620004dc5780637c01369014620004f357600080fd5b80634c5430a0116200025557806365e821e5116200020357806366c0623911620001e657806366c0623914620004b15780636fc6407c14620004bb57806375907f2814620004c557600080fd5b806365e821e51462000483578063666e1b39146200049a57600080fd5b80635c975abb11620002385780635c975abb14620004075780635f1cc005146200042257806361d027b3146200047957600080fd5b80634c5430a014620003d9578063554bab3c14620003f057600080fd5b80632d809cb611620002b35780633ceda01111620002965780633ceda01114620003925780634256dd7814620003ab578063478739ca14620003c257600080fd5b80632d809cb61462000371578063391d0c9c146200038857600080fd5b806308cdc2a814620002e95780630d57036114620003025780632933d89114620003435780632b800e3b146200035a575b600080fd5b62000300620002fa36600462001df6565b62000663565b005b620003196200031336600462001e1a565b62000734565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620003006200035436600462001e6c565b62000926565b620003196200036b36600462001e6c565b620009fe565b620003196200038236600462001eac565b62000a42565b6200031962000a79565b6200039c62000aa9565b6040519081526020016200033a565b62000300620003bc36600462001e6c565b62000ad4565b62000300620003d336600462001e6c565b62000bf1565b62000319620003ea36600462001e6c565b62000d0e565b620003006200040136600462001eac565b62000d73565b6200041162000e5a565b60405190151581526020016200033a565b620004396200043336600462001e6c565b62000e85565b60408051825173ffffffffffffffffffffffffffffffffffffffff908116825260208085015182169083015292820151909216908201526060016200033a565b6200031962000f13565b620003006200049436600462001eac565b62000f21565b62000319620004ab36600462001eac565b62001057565b6200039c62001088565b6200031962001094565b62000300620004d636600462001e6c565b620010bf565b62000300620004ed36600462001eac565b620011dc565b620003006200050436600462001eac565b62001312565b6200039c6200051b36600462001eac565b60016020526000908152604090205481565b6200039c62001448565b620004116200054836600462001eac565b73ffffffffffffffffffffffffffffffffffffffff16600090815260016020526040902054151590565b6200031962001473565b620003006200058d36600462001e6c565b62001481565b6200031962001587565b62000319620005ae36600462001e6c565b620015e9565b62000300620005c536600462001e6c565b62001630565b6200039c62001701565b62000300620005e636600462001ecc565b6200172c565b6200039c6200183c565b6200039c62001867565b620003006200061136600462001ef4565b62001892565b620003006200062836600462001e6c565b620019d1565b6200031962001aee565b6200031962001b19565b6200039c62001b27565b620003006200065d36600462001ecc565b62001b52565b6200066d62001587565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620006d2576040517f84f8637600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006fc7ff201e8b56b5ea8f1176ce6f2699cbe9659ba7491e9460c9d358ddf61400b5de3829055565b60405181151581527f31311016d7204faff81880133e3db244ae8a8b9ce15e83e2432258226d15f9429060200160405180910390a150565b6000826200074281620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620007af576040517ff0a882b5000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b83600003620007ea576040517f7244bc7800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000620007f662000a79565b8460405160240162000809919062002150565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff0b4095900000000000000000000000000000000000000000000000000000000179052516200088b9062001de8565b620008989291906200225b565b604051809103906000f080158015620008b5573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8116600081815260016020526040908190208890555191925082917f09d535073bc2dc21c8fd680a2141218a65fb0acc46e88b9e5d96f114b734b004906200091590889062002150565b60405180910390a295945050505050565b60006200093381620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146200099c576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620009c67f2859911faffd405cbcc22bdad2f67b54a86355c092452044dbab4f656aec3dc9839055565b6040518281527fd19fe8ad9152af12b174a60210fb798db0767d63973ebb97298dc44d67a5c82d906020015b60405180910390a15050565b600080828154811062000a155762000a15620022ef565b600091825260209091206003909102015473ffffffffffffffffffffffffffffffffffffffff1692915050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205462000a739062000d0e565b92915050565b600062000aa47f81565bc82d6e7196d38320713fd94f897c0e1a4c83974a2fbbbf9fbb55a6d8a75490565b905090565b600062000aa47f1f7147efa84c5ef8ccb713891d25247c732a9d5765ebc3bb6cb30d1f17d277f05490565b600062000ae181620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000b4a576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000b5e82670de0b6b3a764000062001c65565b1562000b96576040517f3c5df10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000bc07f7b1a264a02657d43e78b10f2a591a99a0fdf8a165fb72bbf762d965e9973f64e839055565b6040518281527fd10d75876659a287a59a6ccfa2e3fff42f84d94b542837acd30bc184d562de4090602001620009f2565b600062000bfe81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000c67576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000c7b82670de0b6b3a764000062001c65565b1562000cb3576040517f0c6b0ec800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000cdd7f6f35922f1b8609c81847a86ce8bb2528f73d722df88772b050ac89d3bc48707d839055565b6040518281527fdf7e6bc55eeb2668bd338e44a5abb721b1f98ad51f7a00baaa1b62f9383862d790602001620009f2565b6000806000838154811062000d275762000d27620022ef565b600091825260209091206002600390920201015473ffffffffffffffffffffffffffffffffffffffff169050801562000d61578062000d6c565b62000d6c83620015e9565b9392505050565b600062000d8081620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000de9576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000e137fc641ae699093d5be5b0b167620fe782b911b5015c8c9f6e14207530ddda0d020839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fa4336c0cb1e245b95ad204faed7e940d6dc999684fd8b5e1ff597a0c4efca8ab90602001620009f2565b600062000aa47ff201e8b56b5ea8f1176ce6f2699cbe9659ba7491e9460c9d358ddf61400b5de35490565b60408051606081018252600080825260208201819052918101919091526000828154811062000eb85762000eb8620022ef565b6000918252602091829020604080516060810182526003909302909101805473ffffffffffffffffffffffffffffffffffffffff90811684526001820154811694840194909452600201549092169181019190915292915050565b600062000aa4600062000d0e565b600062000f2e81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000f97576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b62000fe6576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010107fcbd1a41d9e21eb02a3acb8d57f9495422d3837dd84bf5dfbc51964fe540cff41839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527f18c973e70eca8db74eab2a3e0de3c4bffcc46c45f6f17f600e2d4d4f744e2a2b90602001620009f2565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205462000a7390620015e9565b600062000aa462001c7d565b600062000aa47fcbd1a41d9e21eb02a3acb8d57f9495422d3837dd84bf5dfbc51964fe540cff415490565b6000620010cc81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001135576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b6200114982670de0b6b3a764000062001c65565b1562001181576040517fb4c4f79900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620011ab7fdf23e6978beb49efbffd02ffd26ec2f120b1e5be191aa5749bafaa170026fb09839055565b6040518281527f1a35ca75fc5ab34ae3487b3507e7453b6e4c15a69f2392939fbbcf8f64558ad190602001620009f2565b6000620011e981620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001252576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b620012a1576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620012cb7f9a67237eef0f801c1f3a0e6be772257326890fecbd39f68c5f7bb69ca7c408c3839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fa0fe5cb0e8843811ca9f6123983dcdfd45a33b61892b9b8f380ed444078e299a90602001620009f2565b60006200131f81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001388576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b620013d7576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014017f81565bc82d6e7196d38320713fd94f897c0e1a4c83974a2fbbbf9fbb55a6d8a7839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527f36466d973cc33c9b726f867d2fc1f8cd56d58de206993f62ccba543a3429ea6290602001620009f2565b600062000aa47fd665791d8a3246c9a2360cb3de854da1c9536240e0380f1f5c2dd0e6b8b7c8605490565b600062000aa46000620015e9565b6000808281548110620014985762001498620022ef565b60009182526020909120600390910201805490915073ffffffffffffffffffffffffffffffffffffffff1633811462001501576040517f07f41a5f00000000000000000000000000000000000000000000000000000000815260048101849052602401620007a6565b81547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116835560018301805473ffffffffffffffffffffffffffffffffffffffff841692168217905560405190815283907f87c983c6a4d6d9a68e6d99934d1fb50f760858298c06f8ed6b316f534e06faf4906020015b60405180910390a2505050565b600080620015b37fc641ae699093d5be5b0b167620fe782b911b5015c8c9f6e14207530ddda0d0205490565b905073ffffffffffffffffffffffffffffffffffffffff811615620015d95780620015e3565b620015e362001473565b91505090565b6000808281548110620016005762001600620022ef565b600091825260209091206001600390920201015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60006200163d81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620016a6576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620016d07fd665791d8a3246c9a2360cb3de854da1c9536240e0380f1f5c2dd0e6b8b7c860839055565b6040518281527f7e6452dce5202ad16be30ea14955296f7157b95e4ca48b73fc54d54601185adf90602001620009f2565b600062000aa47fdf23e6978beb49efbffd02ffd26ec2f120b1e5be191aa5749bafaa170026fb095490565b816200173881620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620017a1576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b8160008481548110620017b857620017b8620022ef565b60009182526020918290206003919091020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff938416179055604051918416825284917f0bffd4439c17923ee1b2b093be5394c42dcab0d9394e349a8d6a059c239ba60391016200157a565b600062000aa47f7b1a264a02657d43e78b10f2a591a99a0fdf8a165fb72bbf762d965e9973f64e5490565b600062000aa47f2859911faffd405cbcc22bdad2f67b54a86355c092452044dbab4f656aec3dc95490565b600180620018be7f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b5490565b10620018fa576040517f1e7a9d9500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620019247f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b829055565b60017fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556200195262001c7d565b506200195e84620011dc565b620019698362000f21565b620019748262001312565b60007fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556040518181527fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f329060200160405180910390a150505050565b6000620019de81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001a47576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62001a5b82670de0b6b3a764000062001c65565b1562001a93576040517f7c3ceda900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001abd7f1f7147efa84c5ef8ccb713891d25247c732a9d5765ebc3bb6cb30d1f17d277f0839055565b6040518281527f852c049e335a49416ecbcb0128935cc3832c307d450d206f0a2d0bf2b28ba2db90602001620009f2565b600062000aa47f9a67237eef0f801c1f3a0e6be772257326890fecbd39f68c5f7bb69ca7c408c35490565b600062000aa46000620009fe565b600062000aa47f6f35922f1b8609c81847a86ce8bb2528f73d722df88772b050ac89d3bc48707d5490565b8162001b5e81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001bc7576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b816000848154811062001bde5762001bde620022ef565b60009182526020918290206003919091020160020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff938416179055604051918416825284917fffd31ccade46a73a57d8efd7d740bbf6aa67e50a158c98ad82a06ad31556cef491016200157a565b600062001c73838362001daf565b6002149392505050565b600080546040805160608101825283815233602080830182815283850187815260018701885587805293517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5636003880290810180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9485161790915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482018054851691841691909117905594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5659095018054909216941693909317909255915191825282917f645c9ae30d6a6aa6b2dace770fa0cfac2d8d44b9b036510e0a16aab39e6b5931910160405180910390a2919050565b600082828082111562001dc85760029250505062000a73565b8082101562001ddd5760009250505062000a73565b506001949350505050565b610a93806200231f83390190565b60006020828403121562001e0957600080fd5b8135801515811462000d6c57600080fd5b6000806040838503121562001e2e57600080fd5b82359150602083013567ffffffffffffffff81111562001e4d57600080fd5b83016101e0818603121562001e6157600080fd5b809150509250929050565b60006020828403121562001e7f57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811462001ea957600080fd5b50565b60006020828403121562001ebf57600080fd5b813562000d6c8162001e86565b6000806040838503121562001ee057600080fd5b82359150602083013562001e618162001e86565b60008060006060848603121562001f0a57600080fd5b833562001f178162001e86565b9250602084013562001f298162001e86565b9150604084013562001f3b8162001e86565b809150509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262001f7c57600080fd5b830160208101925035905067ffffffffffffffff81111562001f9d57600080fd5b80360382131562001fad57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6002811062001ea957600080fd5b6002811062001ea9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8035620020508162001ffd565b6200205b816200200b565b825260208101356200206d8162001ffd565b62002078816200200b565b602083015260408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008116808214620020b257600080fd5b80604085015250505050565b8035620020cb8162001e86565b919050565b8035600f81900b8114620020cb57600080fd5b620020ee81620020d0565b600f0b82526200210160208201620020d0565b600f0b60208301526200211760408201620020d0565b600f0b604083015260608101356fffffffffffffffffffffffffffffffff81168082146200214457600080fd5b80606085015250505050565b60208152600062002162838462001f46565b6101e060208501526200217b6102008501828462001fb4565b9150506200218d602085018562001f46565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0858403016040860152620021c483828462001fb4565b92505050620021da606084016040860162002043565b620021e860a08501620020be565b73ffffffffffffffffffffffffffffffffffffffff811660c08501525060c084013560e084015261010060e085013581850152610120818601358186015261014091508086013582860152506101608186013581860152620022516101808601828801620020e3565b5090949350505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b81811015620022a75785810183015185820160600152820162002289565b81811115620022ba576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405260405162000a9338038062000a938339810160408190526200002691620004c6565b6200005360017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5162000594565b60008051602062000a4c83398151915214620000735762000073620005ba565b620000818282600062000089565b505062000641565b62000094836200015e565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a2600082511180620000d65750805b15620001595762000157836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200011f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001459190620005d0565b83620002ff60201b620000291760201c565b505b505050565b62000174816200032e60201b620000551760201c565b620001d45760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6200024e816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000217573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200023d9190620005d0565b6200032e60201b620000551760201c565b620002b55760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401620001cb565b80620002de60008051602062000a4c83398151915260001b6200033d60201b620000711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b606062000327838360405180606001604052806027815260200162000a6c6027913962000340565b9392505050565b6001600160a01b03163b151590565b90565b60606001600160a01b0384163b620003aa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401620001cb565b600080856001600160a01b031685604051620003c79190620005ee565b600060405180830381855af49150503d806000811462000404576040519150601f19603f3d011682016040523d82523d6000602084013e62000409565b606091505b5090925090506200041c82828662000426565b9695505050505050565b606083156200043757508162000327565b825115620004485782518084602001fd5b8160405162461bcd60e51b8152600401620001cb91906200060c565b80516001600160a01b03811681146200047c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004b45781810151838201526020016200049a565b83811115620001575750506000910152565b60008060408385031215620004da57600080fd5b620004e58362000464565b60208401519092506001600160401b03808211156200050357600080fd5b818501915085601f8301126200051857600080fd5b8151818111156200052d576200052d62000481565b604051601f8201601f19908116603f0116810190838211818310171562000558576200055862000481565b816040528281528860208487010111156200057257600080fd5b6200058583602083016020880162000497565b80955050505050509250929050565b600082821015620005b557634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b600060208284031215620005e357600080fd5b620003278262000464565b600082516200060281846020870162000497565b9190910192915050565b60208152600082518060208401526200062d81604085016020870162000497565b601f01601f19169190910160400192915050565b6103fb80620006516000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b610127565b565b606061004e838360405180606001604052806027815260200161039f6027913961014b565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d505473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012291906102cb565b905090565b3660008037600080366000845af43d6000803e808015610146573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b6101f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161021e9190610331565b600060405180830381855af49150503d8060008114610259576040519150601f19603f3d011682016040523d82523d6000602084013e61025e565b606091505b509150915061026e828286610278565b9695505050505050565b6060831561028757508161004e565b8251156102975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ed919061034d565b6000602082840312156102dd57600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461004e57600080fd5b60005b8381101561031c578181015183820152602001610304565b8381111561032b576000848401525b50505050565b60008251610343818460208701610301565b9190910192915050565b602081526000825180602084015261036c816040850160208701610301565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208ce966e1385eefb01b44b0d1cdba417199b04aa2fe5c746c59969a22757b9b3664736f6c634300080f0033a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212207b63003df7f905db73bc6dfd429e1f3244bef25c4f88af0412ba6d9c9e0e7f9064736f6c634300080f0033",
  "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620002e45760003560e01c80637a7da0041162000199578063a36a363011620000e9578063d809aa611162000097578063e30c3978116200007a578063e30c39781462000638578063e975c0c31462000642578063f8dfc2cc146200064c57600080fd5b8063d809aa611462000617578063d8dfeb45146200062e57600080fd5b8063b0e21e8a11620000cc578063b0e21e8a14620005ec578063ba2de9bc14620005f6578063c0c53b8b146200060057600080fd5b8063a36a363014620005cb578063af2757b714620005d557600080fd5b80638da5cb5b11620001475780639fd0506d116200012a5780639fd0506d1462000593578063a123c33e146200059d578063a1eef78e14620005b457600080fd5b80638da5cb5b14620005725780638fbf1803146200057c57600080fd5b80637d254e66116200017c5780637d254e66146200050a5780637d49c1b7146200052d5780637fd29192146200053757600080fd5b80637a7da00414620004dc5780637c01369014620004f357600080fd5b80634c5430a0116200025557806365e821e5116200020357806366c0623911620001e657806366c0623914620004b15780636fc6407c14620004bb57806375907f2814620004c557600080fd5b806365e821e51462000483578063666e1b39146200049a57600080fd5b80635c975abb11620002385780635c975abb14620004075780635f1cc005146200042257806361d027b3146200047957600080fd5b80634c5430a014620003d9578063554bab3c14620003f057600080fd5b80632d809cb611620002b35780633ceda01111620002965780633ceda01114620003925780634256dd7814620003ab578063478739ca14620003c257600080fd5b80632d809cb61462000371578063391d0c9c146200038857600080fd5b806308cdc2a814620002e95780630d57036114620003025780632933d89114620003435780632b800e3b146200035a575b600080fd5b62000300620002fa36600462001df6565b62000663565b005b620003196200031336600462001e1a565b62000734565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620003006200035436600462001e6c565b62000926565b620003196200036b36600462001e6c565b620009fe565b620003196200038236600462001eac565b62000a42565b6200031962000a79565b6200039c62000aa9565b6040519081526020016200033a565b62000300620003bc36600462001e6c565b62000ad4565b62000300620003d336600462001e6c565b62000bf1565b62000319620003ea36600462001e6c565b62000d0e565b620003006200040136600462001eac565b62000d73565b6200041162000e5a565b60405190151581526020016200033a565b620004396200043336600462001e6c565b62000e85565b60408051825173ffffffffffffffffffffffffffffffffffffffff908116825260208085015182169083015292820151909216908201526060016200033a565b6200031962000f13565b620003006200049436600462001eac565b62000f21565b62000319620004ab36600462001eac565b62001057565b6200039c62001088565b6200031962001094565b62000300620004d636600462001e6c565b620010bf565b62000300620004ed36600462001eac565b620011dc565b620003006200050436600462001eac565b62001312565b6200039c6200051b36600462001eac565b60016020526000908152604090205481565b6200039c62001448565b620004116200054836600462001eac565b73ffffffffffffffffffffffffffffffffffffffff16600090815260016020526040902054151590565b6200031962001473565b620003006200058d36600462001e6c565b62001481565b6200031962001587565b62000319620005ae36600462001e6c565b620015e9565b62000300620005c536600462001e6c565b62001630565b6200039c62001701565b62000300620005e636600462001ecc565b6200172c565b6200039c6200183c565b6200039c62001867565b620003006200061136600462001ef4565b62001892565b620003006200062836600462001e6c565b620019d1565b6200031962001aee565b6200031962001b19565b6200039c62001b27565b620003006200065d36600462001ecc565b62001b52565b6200066d62001587565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620006d2576040517f84f8637600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006fc7ff201e8b56b5ea8f1176ce6f2699cbe9659ba7491e9460c9d358ddf61400b5de3829055565b60405181151581527f31311016d7204faff81880133e3db244ae8a8b9ce15e83e2432258226d15f9429060200160405180910390a150565b6000826200074281620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620007af576040517ff0a882b5000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b83600003620007ea576040517f7244bc7800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000620007f662000a79565b8460405160240162000809919062002150565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff0b4095900000000000000000000000000000000000000000000000000000000179052516200088b9062001de8565b620008989291906200225b565b604051809103906000f080158015620008b5573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8116600081815260016020526040908190208890555191925082917f09d535073bc2dc21c8fd680a2141218a65fb0acc46e88b9e5d96f114b734b004906200091590889062002150565b60405180910390a295945050505050565b60006200093381620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146200099c576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620009c67f2859911faffd405cbcc22bdad2f67b54a86355c092452044dbab4f656aec3dc9839055565b6040518281527fd19fe8ad9152af12b174a60210fb798db0767d63973ebb97298dc44d67a5c82d906020015b60405180910390a15050565b600080828154811062000a155762000a15620022ef565b600091825260209091206003909102015473ffffffffffffffffffffffffffffffffffffffff1692915050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205462000a739062000d0e565b92915050565b600062000aa47f81565bc82d6e7196d38320713fd94f897c0e1a4c83974a2fbbbf9fbb55a6d8a75490565b905090565b600062000aa47f1f7147efa84c5ef8ccb713891d25247c732a9d5765ebc3bb6cb30d1f17d277f05490565b600062000ae181620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000b4a576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000b5e82670de0b6b3a764000062001c65565b1562000b96576040517f3c5df10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000bc07f7b1a264a02657d43e78b10f2a591a99a0fdf8a165fb72bbf762d965e9973f64e839055565b6040518281527fd10d75876659a287a59a6ccfa2e3fff42f84d94b542837acd30bc184d562de4090602001620009f2565b600062000bfe81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000c67576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000c7b82670de0b6b3a764000062001c65565b1562000cb3576040517f0c6b0ec800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000cdd7f6f35922f1b8609c81847a86ce8bb2528f73d722df88772b050ac89d3bc48707d839055565b6040518281527fdf7e6bc55eeb2668bd338e44a5abb721b1f98ad51f7a00baaa1b62f9383862d790602001620009f2565b6000806000838154811062000d275762000d27620022ef565b600091825260209091206002600390920201015473ffffffffffffffffffffffffffffffffffffffff169050801562000d61578062000d6c565b62000d6c83620015e9565b9392505050565b600062000d8081620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000de9576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62000e137fc641ae699093d5be5b0b167620fe782b911b5015c8c9f6e14207530ddda0d020839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fa4336c0cb1e245b95ad204faed7e940d6dc999684fd8b5e1ff597a0c4efca8ab90602001620009f2565b600062000aa47ff201e8b56b5ea8f1176ce6f2699cbe9659ba7491e9460c9d358ddf61400b5de35490565b60408051606081018252600080825260208201819052918101919091526000828154811062000eb85762000eb8620022ef565b6000918252602091829020604080516060810182526003909302909101805473ffffffffffffffffffffffffffffffffffffffff90811684526001820154811694840194909452600201549092169181019190915292915050565b600062000aa4600062000d0e565b600062000f2e81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000f97576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b62000fe6576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010107fcbd1a41d9e21eb02a3acb8d57f9495422d3837dd84bf5dfbc51964fe540cff41839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527f18c973e70eca8db74eab2a3e0de3c4bffcc46c45f6f17f600e2d4d4f744e2a2b90602001620009f2565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205462000a7390620015e9565b600062000aa462001c7d565b600062000aa47fcbd1a41d9e21eb02a3acb8d57f9495422d3837dd84bf5dfbc51964fe540cff415490565b6000620010cc81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001135576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b6200114982670de0b6b3a764000062001c65565b1562001181576040517fb4c4f79900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620011ab7fdf23e6978beb49efbffd02ffd26ec2f120b1e5be191aa5749bafaa170026fb09839055565b6040518281527f1a35ca75fc5ab34ae3487b3507e7453b6e4c15a69f2392939fbbcf8f64558ad190602001620009f2565b6000620011e981620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001252576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b620012a1576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620012cb7f9a67237eef0f801c1f3a0e6be772257326890fecbd39f68c5f7bb69ca7c408c3839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fa0fe5cb0e8843811ca9f6123983dcdfd45a33b61892b9b8f380ed444078e299a90602001620009f2565b60006200131f81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001388576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b73ffffffffffffffffffffffffffffffffffffffff82163b620013d7576040517fe939acbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014017f81565bc82d6e7196d38320713fd94f897c0e1a4c83974a2fbbbf9fbb55a6d8a7839055565b60405173ffffffffffffffffffffffffffffffffffffffff831681527f36466d973cc33c9b726f867d2fc1f8cd56d58de206993f62ccba543a3429ea6290602001620009f2565b600062000aa47fd665791d8a3246c9a2360cb3de854da1c9536240e0380f1f5c2dd0e6b8b7c8605490565b600062000aa46000620015e9565b6000808281548110620014985762001498620022ef565b60009182526020909120600390910201805490915073ffffffffffffffffffffffffffffffffffffffff1633811462001501576040517f07f41a5f00000000000000000000000000000000000000000000000000000000815260048101849052602401620007a6565b81547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116835560018301805473ffffffffffffffffffffffffffffffffffffffff841692168217905560405190815283907f87c983c6a4d6d9a68e6d99934d1fb50f760858298c06f8ed6b316f534e06faf4906020015b60405180910390a2505050565b600080620015b37fc641ae699093d5be5b0b167620fe782b911b5015c8c9f6e14207530ddda0d0205490565b905073ffffffffffffffffffffffffffffffffffffffff811615620015d95780620015e3565b620015e362001473565b91505090565b6000808281548110620016005762001600620022ef565b600091825260209091206001600390920201015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60006200163d81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620016a6576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620016d07fd665791d8a3246c9a2360cb3de854da1c9536240e0380f1f5c2dd0e6b8b7c860839055565b6040518281527f7e6452dce5202ad16be30ea14955296f7157b95e4ca48b73fc54d54601185adf90602001620009f2565b600062000aa47fdf23e6978beb49efbffd02ffd26ec2f120b1e5be191aa5749bafaa170026fb095490565b816200173881620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614620017a1576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b8160008481548110620017b857620017b8620022ef565b60009182526020918290206003919091020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff938416179055604051918416825284917f0bffd4439c17923ee1b2b093be5394c42dcab0d9394e349a8d6a059c239ba60391016200157a565b600062000aa47f7b1a264a02657d43e78b10f2a591a99a0fdf8a165fb72bbf762d965e9973f64e5490565b600062000aa47f2859911faffd405cbcc22bdad2f67b54a86355c092452044dbab4f656aec3dc95490565b600180620018be7f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b5490565b10620018fa576040517f1e7a9d9500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b620019247f5db5abc19987c2b3729df7961b62b6bb0bae886dd47e3ce25bb3a3af34c6d80b829055565b60017fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556200195262001c7d565b506200195e84620011dc565b620019698362000f21565b620019748262001312565b60007fad57d7911b7e3d6c3c79a68ba909a7f4ba41f9485e5207b12dee0d0c6af5398c556040518181527fbe9b076dc5b65990cca9dd9d7366682482e7817a6f6bc7f4faf4dc32af497f329060200160405180910390a150505050565b6000620019de81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001a47576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b62001a5b82670de0b6b3a764000062001c65565b1562001a93576040517f7c3ceda900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001abd7f1f7147efa84c5ef8ccb713891d25247c732a9d5765ebc3bb6cb30d1f17d277f0839055565b6040518281527f852c049e335a49416ecbcb0128935cc3832c307d450d206f0a2d0bf2b28ba2db90602001620009f2565b600062000aa47f9a67237eef0f801c1f3a0e6be772257326890fecbd39f68c5f7bb69ca7c408c35490565b600062000aa46000620009fe565b600062000aa47f6f35922f1b8609c81847a86ce8bb2528f73d722df88772b050ac89d3bc48707d5490565b8162001b5e81620015e9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462001bc7576040517ff0a882b500000000000000000000000000000000000000000000000000000000815260048101829052602401620007a6565b816000848154811062001bde5762001bde620022ef565b60009182526020918290206003919091020160020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff938416179055604051918416825284917fffd31ccade46a73a57d8efd7d740bbf6aa67e50a158c98ad82a06ad31556cef491016200157a565b600062001c73838362001daf565b6002149392505050565b600080546040805160608101825283815233602080830182815283850187815260018701885587805293517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5636003880290810180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9485161790915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482018054851691841691909117905594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5659095018054909216941693909317909255915191825282917f645c9ae30d6a6aa6b2dace770fa0cfac2d8d44b9b036510e0a16aab39e6b5931910160405180910390a2919050565b600082828082111562001dc85760029250505062000a73565b8082101562001ddd5760009250505062000a73565b506001949350505050565b610a93806200231f83390190565b60006020828403121562001e0957600080fd5b8135801515811462000d6c57600080fd5b6000806040838503121562001e2e57600080fd5b82359150602083013567ffffffffffffffff81111562001e4d57600080fd5b83016101e0818603121562001e6157600080fd5b809150509250929050565b60006020828403121562001e7f57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811462001ea957600080fd5b50565b60006020828403121562001ebf57600080fd5b813562000d6c8162001e86565b6000806040838503121562001ee057600080fd5b82359150602083013562001e618162001e86565b60008060006060848603121562001f0a57600080fd5b833562001f178162001e86565b9250602084013562001f298162001e86565b9150604084013562001f3b8162001e86565b809150509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262001f7c57600080fd5b830160208101925035905067ffffffffffffffff81111562001f9d57600080fd5b80360382131562001fad57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6002811062001ea957600080fd5b6002811062001ea9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8035620020508162001ffd565b6200205b816200200b565b825260208101356200206d8162001ffd565b62002078816200200b565b602083015260408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008116808214620020b257600080fd5b80604085015250505050565b8035620020cb8162001e86565b919050565b8035600f81900b8114620020cb57600080fd5b620020ee81620020d0565b600f0b82526200210160208201620020d0565b600f0b60208301526200211760408201620020d0565b600f0b604083015260608101356fffffffffffffffffffffffffffffffff81168082146200214457600080fd5b80606085015250505050565b60208152600062002162838462001f46565b6101e060208501526200217b6102008501828462001fb4565b9150506200218d602085018562001f46565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0858403016040860152620021c483828462001fb4565b92505050620021da606084016040860162002043565b620021e860a08501620020be565b73ffffffffffffffffffffffffffffffffffffffff811660c08501525060c084013560e084015261010060e085013581850152610120818601358186015261014091508086013582860152506101608186013581860152620022516101808601828801620020e3565b5090949350505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b81811015620022a75785810183015185820160600152820162002289565b81811115620022ba576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405260405162000a9338038062000a938339810160408190526200002691620004c6565b6200005360017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5162000594565b60008051602062000a4c83398151915214620000735762000073620005ba565b620000818282600062000089565b505062000641565b62000094836200015e565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a2600082511180620000d65750805b15620001595762000157836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200011f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001459190620005d0565b83620002ff60201b620000291760201c565b505b505050565b62000174816200032e60201b620000551760201c565b620001d45760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6200024e816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000217573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200023d9190620005d0565b6200032e60201b620000551760201c565b620002b55760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401620001cb565b80620002de60008051602062000a4c83398151915260001b6200033d60201b620000711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b606062000327838360405180606001604052806027815260200162000a6c6027913962000340565b9392505050565b6001600160a01b03163b151590565b90565b60606001600160a01b0384163b620003aa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401620001cb565b600080856001600160a01b031685604051620003c79190620005ee565b600060405180830381855af49150503d806000811462000404576040519150601f19603f3d011682016040523d82523d6000602084013e62000409565b606091505b5090925090506200041c82828662000426565b9695505050505050565b606083156200043757508162000327565b825115620004485782518084602001fd5b8160405162461bcd60e51b8152600401620001cb91906200060c565b80516001600160a01b03811681146200047c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004b45781810151838201526020016200049a565b83811115620001575750506000910152565b60008060408385031215620004da57600080fd5b620004e58362000464565b60208401519092506001600160401b03808211156200050357600080fd5b818501915085601f8301126200051857600080fd5b8151818111156200052d576200052d62000481565b604051601f8201601f19908116603f0116810190838211818310171562000558576200055862000481565b816040528281528860208487010111156200057257600080fd5b6200058583602083016020880162000497565b80955050505050509250929050565b600082821015620005b557634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b600060208284031215620005e357600080fd5b620003278262000464565b600082516200060281846020870162000497565b9190910192915050565b60208152600082518060208401526200062d81604085016020870162000497565b601f01601f19169190910160400192915050565b6103fb80620006516000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b610127565b565b606061004e838360405180606001604052806027815260200161039f6027913961014b565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d505473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012291906102cb565b905090565b3660008037600080366000845af43d6000803e808015610146573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b6101f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168560405161021e9190610331565b600060405180830381855af49150503d8060008114610259576040519150601f19603f3d011682016040523d82523d6000602084013e61025e565b606091505b509150915061026e828286610278565b9695505050505050565b6060831561028757508161004e565b8251156102975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ed919061034d565b6000602082840312156102dd57600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461004e57600080fd5b60005b8381101561031c578181015183820152602001610304565b8381111561032b576000848401525b50505050565b60008251610343818460208701610301565b9190910192915050565b602081526000825180602084015261036c816040850160208701610301565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208ce966e1385eefb01b44b0d1cdba417199b04aa2fe5c746c59969a22757b9b3664736f6c634300080f0033a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212207b63003df7f905db73bc6dfd429e1f3244bef25c4f88af0412ba6d9c9e0e7f9064736f6c634300080f0033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "acceptCoordinatorOwner(uint256)": {
        "details": "Must be called by the coordinator's pending owner",
        "params": {
          "coordinatorId": "Coordinator to update"
        }
      },
      "coordinators(uint256)": {
        "params": {
          "coordinatorId": "Coordinator to return for"
        },
        "returns": {
          "_0": "Coordinator state"
        }
      },
      "createCoordinator()": {
        "details": "Can only be called by the protocol owner",
        "returns": {
          "_0": "New coordinator ID"
        }
      },
      "createProduct(uint256,(string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))": {
        "details": "Can only be called by the coordinator owner",
        "params": {
          "coordinatorId": "Coordinator that will own the product",
          "productInfo": "Product params used to initialize the product"
        },
        "returns": {
          "_0": "New product contract address"
        }
      },
      "initialize(address,address,address)": {
        "details": "Must be called atomically as part of the upgradeable proxy deployment to      avoid front-running",
        "params": {
          "collateral_": "Collateral contract address",
          "incentivizer_": "Incentivizer contract address",
          "productBeacon_": "Product implementation beacon address"
        }
      },
      "isProduct(address)": {
        "params": {
          "product": "Contract address to check"
        },
        "returns": {
          "_0": "Whether a contract is a product"
        }
      },
      "owner()": {
        "returns": {
          "_0": "Owner of the protocol"
        }
      },
      "owner(address)": {
        "params": {
          "product": "Product to return for"
        },
        "returns": {
          "_0": "Owner of the product"
        }
      },
      "owner(uint256)": {
        "params": {
          "coordinatorId": "Coordinator to return for"
        },
        "returns": {
          "_0": "Owner of the coordinator"
        }
      },
      "pendingOwner()": {
        "returns": {
          "_0": "Owner of the protocol"
        }
      },
      "pendingOwner(uint256)": {
        "params": {
          "coordinatorId": "Coordinator to return for"
        },
        "returns": {
          "_0": "Pending owner of the coordinator"
        }
      },
      "treasury()": {
        "details": "Defaults to the `owner` when `treasury` is unset",
        "returns": {
          "_0": "Treasury of the protocol"
        }
      },
      "treasury(address)": {
        "details": "Defaults to the `owner` when `treasury` is unset",
        "params": {
          "product": "Product to return for"
        },
        "returns": {
          "_0": "Treasury of the product"
        }
      },
      "treasury(uint256)": {
        "details": "Defaults to the `owner` when `treasury` is unset",
        "params": {
          "coordinatorId": "Coordinator to return for"
        },
        "returns": {
          "_0": "Treasury of the coordinator"
        }
      },
      "updateCollateral(address)": {
        "params": {
          "newCollateral": "New Collateral contract address"
        }
      },
      "updateCoordinatorPendingOwner(uint256,address)": {
        "details": "Must be called by the coordinator's current owner",
        "params": {
          "coordinatorId": "Coordinator to update",
          "newPendingOwner": "New pending owner address"
        }
      },
      "updateCoordinatorTreasury(uint256,address)": {
        "details": "Must be called by the coordinator's current owner. Defaults to the coordinator `owner` if set to address(0)",
        "params": {
          "coordinatorId": "Coordinator to update",
          "newTreasury": "New treasury address"
        }
      },
      "updateIncentivizationFee(uint256)": {
        "params": {
          "newIncentivizationFee": "New incentivization fee"
        }
      },
      "updateIncentivizer(address)": {
        "params": {
          "newIncentivizer": "New Incentivizer contract address"
        }
      },
      "updateLiquidationFee(uint256)": {
        "params": {
          "newLiquidationFee": "New liquidation fee"
        }
      },
      "updateMinCollateral(uint256)": {
        "params": {
          "newMinCollateral": "New minimum allowed collateral amount"
        }
      },
      "updateMinFundingFee(uint256)": {
        "params": {
          "newMinFundingFee": "New minimum allowed funding fee"
        }
      },
      "updatePaused(bool)": {
        "params": {
          "newPaused": "New protocol paused state"
        }
      },
      "updatePauser(address)": {
        "params": {
          "newPauser": "New protocol pauser address"
        }
      },
      "updateProductBeacon(address)": {
        "params": {
          "newProductBeacon": "New Product implementation beacon address"
        }
      },
      "updateProgramsPerProduct(uint256)": {
        "params": {
          "newProgramsPerProduct": "New maximum incentivization programs per product allowed"
        }
      },
      "updateProtocolFee(uint256)": {
        "params": {
          "newProtocolFee": "New protocol-product fee split"
        }
      }
    },
    "stateVariables": {
      "_collateral": {
        "details": "Collateral contract address for the protocol"
      },
      "_coordinators": {
        "details": "List of product coordinators"
      },
      "_incentivizationFee": {
        "details": "Fee on incentivization programs"
      },
      "_incentivizer": {
        "details": "Incentivizer contract address for the protocol"
      },
      "_liquidationFee": {
        "details": "Fee on maintenance for liquidation"
      },
      "_minCollateral": {
        "details": "Minimum allowable collateral amount per user account"
      },
      "_minFundingFee": {
        "details": "Minimum allowable funding fee for a product"
      },
      "_paused": {
        "details": "The paused status of the protocol"
      },
      "_pauser": {
        "details": "Protocol pauser address. address(0) defaults to owner(0)"
      },
      "_productBeacon": {
        "details": "Product implementation beacon address for the protocol"
      },
      "_programsPerProduct": {
        "details": "Maximum incentivization programs per product allowed"
      },
      "_protocolFee": {
        "details": "Percent of collected fees that go to the protocol treasury vs the product treasury"
      },
      "coordinatorFor": {
        "details": "Mapping of the coordinator for each  product"
      }
    },
    "title": "Controller",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "acceptCoordinatorOwner(uint256)": {
        "notice": "Accepts ownership over an existing coordinator"
      },
      "coordinators(uint256)": {
        "notice": "Returns coordinator state for coordinator `coordinatorId`"
      },
      "createCoordinator()": {
        "notice": "Creates a new coordinator with `msg.sender` as the owner"
      },
      "createProduct(uint256,(string,string,(uint8,uint8,bytes30),address,uint256,uint256,uint256,uint256,uint256,(int128,int128,int128,uint128)))": {
        "notice": "Creates a new product market with `provider`"
      },
      "initialize(address,address,address)": {
        "notice": "Initializes the contract state"
      },
      "isProduct(address)": {
        "notice": "Returns whether a contract is a product"
      },
      "owner()": {
        "notice": "Returns the owner of the protocol"
      },
      "owner(address)": {
        "notice": "Returns the owner of the product `product`"
      },
      "owner(uint256)": {
        "notice": "Returns the owner of the coordinator `coordinatorId`"
      },
      "pendingOwner()": {
        "notice": "Returns the pending owner of the protocol"
      },
      "pendingOwner(uint256)": {
        "notice": "Returns the pending owner of the coordinator `coordinatorId`"
      },
      "treasury()": {
        "notice": "Returns the treasury of the protocol"
      },
      "treasury(address)": {
        "notice": "Returns the treasury of the product `product`"
      },
      "treasury(uint256)": {
        "notice": "Returns the treasury of the coordinator `coordinatorId`"
      },
      "updateCollateral(address)": {
        "notice": "Updates the Collateral contract address"
      },
      "updateCoordinatorPendingOwner(uint256,address)": {
        "notice": "Updates the pending owner of an existing coordinator"
      },
      "updateCoordinatorTreasury(uint256,address)": {
        "notice": "Updates the treasury of an existing coordinator"
      },
      "updateIncentivizationFee(uint256)": {
        "notice": "Updates the incentivization fee"
      },
      "updateIncentivizer(address)": {
        "notice": "Updates the Incentivizer contract address"
      },
      "updateLiquidationFee(uint256)": {
        "notice": "Updates the liquidation fee"
      },
      "updateMinCollateral(uint256)": {
        "notice": "Updates the minimum allowed collateral amount per user account"
      },
      "updateMinFundingFee(uint256)": {
        "notice": "Updates the minimum allowed funding fee"
      },
      "updatePaused(bool)": {
        "notice": "Updates the protocol paused state"
      },
      "updatePauser(address)": {
        "notice": "Updates the protocol pauser address. Zero address defaults to owner(0)"
      },
      "updateProductBeacon(address)": {
        "notice": "Updates the Product implementation beacon address"
      },
      "updateProgramsPerProduct(uint256)": {
        "notice": "Updates the maximum incentivization programs per product allowed"
      },
      "updateProtocolFee(uint256)": {
        "notice": "Updates the protocol-product fee split"
      }
    },
    "notice": "Manages creating new products and global protocol parameters.",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 11565,
        "contract": "contracts/controller/Controller.sol:Controller",
        "label": "_coordinators",
        "offset": 0,
        "slot": "0",
        "type": "t_array(t_struct(Coordinator)14688_storage)dyn_storage"
      },
      {
        "astId": 11571,
        "contract": "contracts/controller/Controller.sol:Controller",
        "label": "coordinatorFor",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_contract(IProduct)16058,t_uint256)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_struct(Coordinator)14688_storage)dyn_storage": {
        "base": "t_struct(Coordinator)14688_storage",
        "encoding": "dynamic_array",
        "label": "struct IController.Coordinator[]",
        "numberOfBytes": "32"
      },
      "t_contract(IProduct)16058": {
        "encoding": "inplace",
        "label": "contract IProduct",
        "numberOfBytes": "20"
      },
      "t_mapping(t_contract(IProduct)16058,t_uint256)": {
        "encoding": "mapping",
        "key": "t_contract(IProduct)16058",
        "label": "mapping(contract IProduct => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_struct(Coordinator)14688_storage": {
        "encoding": "inplace",
        "label": "struct IController.Coordinator",
        "members": [
          {
            "astId": 14681,
            "contract": "contracts/controller/Controller.sol:Controller",
            "label": "pendingOwner",
            "offset": 0,
            "slot": "0",
            "type": "t_address"
          },
          {
            "astId": 14684,
            "contract": "contracts/controller/Controller.sol:Controller",
            "label": "owner",
            "offset": 0,
            "slot": "1",
            "type": "t_address"
          },
          {
            "astId": 14687,
            "contract": "contracts/controller/Controller.sol:Controller",
            "label": "treasury",
            "offset": 0,
            "slot": "2",
            "type": "t_address"
          }
        ],
        "numberOfBytes": "96"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}
