{"file_path":"src/contracts/facilitators/gsm/Gsm4626.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {IERC20} from 'aave-v3-origin/contracts/dependencies/openzeppelin/contracts/IERC20.sol';\nimport {GPv2SafeERC20} from 'aave-v3-origin/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol';\nimport {SafeCast} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol';\nimport {IGhoFacilitator} from 'src/contracts/gho/interfaces/IGhoFacilitator.sol';\nimport {IGhoToken} from 'src/contracts/gho/interfaces/IGhoToken.sol';\nimport {IGsmPriceStrategy} from 'src/contracts/facilitators/gsm/priceStrategy/interfaces/IGsmPriceStrategy.sol';\nimport {IGsm4626} from 'src/contracts/facilitators/gsm/interfaces/IGsm4626.sol';\nimport {IGhoReserve} from 'src/contracts/facilitators/gsm/interfaces/IGhoReserve.sol';\nimport {Gsm} from 'src/contracts/facilitators/gsm/Gsm.sol';\n\n/**\n * @title Gsm4626\n * @author Aave\n * @notice GHO Stability Module for ERC4626 vault shares. It provides buy/sell facilities to go to/from an ERC4626\n * vault share to/from GHO.\n * @dev Aimed to be used with ERC4626 vault shares as underlying asset. Users can use the ERC4626 vault share to\n * buy/sell GHO and the generated yield is redirected to the GHO Treasury in form of GHO.\n * @dev To be covered by a proxy contract.\n */\ncontract Gsm4626 is Gsm, IGsm4626 {\n  using GPv2SafeERC20 for IERC20;\n  using SafeCast for uint256;\n\n  /**\n   * @dev Constructor\n   * @param ghoToken The address of the GHO token contract\n   * @param underlyingAsset The address of the ERC4626 vault\n   * @param priceStrategy The address of the price strategy\n   */\n  constructor(\n    address ghoToken,\n    address underlyingAsset,\n    address priceStrategy\n  ) Gsm(ghoToken, underlyingAsset, priceStrategy) {\n    // Intentionally left blank\n  }\n\n  /// @inheritdoc IGsm4626\n  function backWithGho(\n    uint256 amount\n  ) external notSeized onlyRole(CONFIGURATOR_ROLE) returns (uint256) {\n    require(amount > 0, 'INVALID_AMOUNT');\n\n    uint256 usedGho = _getUsed();\n    (, uint256 deficit) = _getCurrentBacking(usedGho);\n    require(deficit > 0, 'NO_CURRENT_DEFICIT_BACKING');\n\n    uint256 ghoToBack = amount > deficit ? deficit : amount;\n\n    IGhoToken(GHO_TOKEN).transferFrom(msg.sender, address(this), ghoToBack);\n    IGhoReserve(_ghoReserve).restore(ghoToBack);\n\n    emit BackingProvided(msg.sender, GHO_TOKEN, ghoToBack, ghoToBack, deficit - ghoToBack);\n    return ghoToBack;\n  }\n\n  /// @inheritdoc IGsm4626\n  function backWithUnderlying(\n    uint256 amount\n  ) external notSeized onlyRole(CONFIGURATOR_ROLE) returns (uint256) {\n    require(amount > 0, 'INVALID_AMOUNT');\n\n    (, uint256 deficit) = _getCurrentBacking(_getUsed());\n    require(deficit > 0, 'NO_CURRENT_DEFICIT_BACKING');\n\n    uint128 deficitInUnderlying = IGsmPriceStrategy(PRICE_STRATEGY)\n      .getGhoPriceInAsset(deficit, false)\n      .toUint128();\n\n    if (amount >= deficitInUnderlying) {\n      _currentExposure += deficitInUnderlying;\n      IERC20(UNDERLYING_ASSET).safeTransferFrom(msg.sender, address(this), deficitInUnderlying);\n\n      emit BackingProvided(msg.sender, UNDERLYING_ASSET, deficitInUnderlying, deficit, 0);\n      return deficitInUnderlying;\n    } else {\n      uint256 amountInGho = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(amount, false);\n\n      _currentExposure += uint128(amount);\n      IERC20(UNDERLYING_ASSET).safeTransferFrom(msg.sender, address(this), amount);\n\n      emit BackingProvided(\n        msg.sender,\n        UNDERLYING_ASSET,\n        amount,\n        amountInGho,\n        deficit - amountInGho\n      );\n      return amount;\n    }\n  }\n\n  /// @inheritdoc IGsm4626\n  function getCurrentBacking() external view returns (uint256, uint256) {\n    return _getCurrentBacking(_getUsed());\n  }\n\n  /// @inheritdoc IGhoFacilitator\n  function distributeFeesToTreasury() public override(Gsm, IGhoFacilitator) {\n    _cumulateYieldInGho();\n    super.distributeFeesToTreasury();\n  }\n\n  /// @inheritdoc Gsm\n  function _beforeBuyAsset(address, uint256, address) internal override {\n    _cumulateYieldInGho();\n  }\n\n  /// @inheritdoc Gsm\n  function _beforeSellAsset(address, uint256, address) internal override {}\n\n  /**\n   * @dev Cumulates yield in form of GHO, aimed to be redirected to the treasury\n   * @dev It mints GHO backed by the excess of underlying produced by the ERC4626 yield\n   * @dev If the GHO amount exceeds the amount available, it will mint up to the remaining limit\n   */\n  function _cumulateYieldInGho() internal {\n    (uint256 ghoLimit, uint256 ghoUsed) = _getUsage();\n    uint256 ghoAvailableToMint = ghoLimit > ghoUsed ? ghoLimit - ghoUsed : 0;\n    (uint256 ghoExcess, ) = _getCurrentBacking(ghoUsed);\n    if (ghoExcess > 0 && ghoAvailableToMint > 0) {\n      ghoExcess = ghoExcess > ghoAvailableToMint ? ghoAvailableToMint : ghoExcess;\n      _accruedFees += uint128(ghoExcess);\n      IGhoReserve(_ghoReserve).use(ghoExcess);\n    }\n  }\n\n  /**\n   * @dev Calculates the excess or deficit of GHO minted, reflective of GSM backing\n   * @param usedGho The amount of GHO currently used by the GSM\n   * @return The excess amount of GHO used, relative to the value of the underlying\n   * @return The deficit of GHO used, relative to the value of the underlying\n   */\n  function _getCurrentBacking(uint256 usedGho) internal view returns (uint256, uint256) {\n    uint256 ghoToBack = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(\n      _currentExposure,\n      false\n    );\n    if (ghoToBack >= usedGho) {\n      return (ghoToBack - usedGho, 0);\n    } else {\n      return (0, usedGho - ghoToBack);\n    }\n  }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b506004361061030c5760003560e01c80638fa468901161019d578063b295a00e116100e9578063cea9d26f116100a2578063dc49a07b1161007c578063dc49a07b1461075b578063e28178cc14610763578063e602539314610774578063f493ca701461079b57600080fd5b8063cea9d26f14610720578063d547741f14610733578063d853015e1461074657600080fd5b8063b295a00e146106b9578063c350de6c146106c1578063c431280e146106d4578063c876a2a7146106e7578063cab46bc6146106fa578063cea462131461070d57600080fd5b80639b745aec11610156578063aa278b0311610130578063aa278b0314610645578063aa443ac014610658578063ab16b58a1461066b578063b1c660f71461069257600080fd5b80639b745aec146105f2578063a217fddf1461060a578063a9c3ebda1461061257600080fd5b80638fa468901461058357806391362b871461059e57806391d14854146105b1578063954c1c0d146105c45780639abeb940146105d75780639b5c9261146105df57600080fd5b80634101d9f41161025c5780637630b2b31161021557806380bc659a116101ef57806380bc659a146105105780638a96e304146105225780638bcd9797146105495780638dbf6c811461057057600080fd5b80637630b2b3146104d857806378cf12b2146104e95780637ecebe00146104f057600080fd5b80634101d9f414610456578063430b09521461047b578063476cce031461048e5780635921c8e014610496578063605297e1146104a95780636400a4af146104b157600080fd5b8063236fc8ad116102c9578063353f03bd116102a3578063353f03bd146103ec5780633644e5151461041357806336568abe1461041b57806340fb07a01461042e57600080fd5b8063236fc8ad146103a4578063248a9ca3146103b65780632f2ff15d146103d957600080fd5b806301ffc9a71461031157806310ce051614610339578063110934d61461034157806316d8887a146103575780631f3da1501461037e5780631fde40bb1461038f575b600080fd5b61032461031f366004613cf6565b6107ae565b60405190151581526020015b60405180910390f35b6103246107e5565b610349610811565b604051908152602001610330565b6103497f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c1681565b6039546001600160801b0316610349565b6103a261039d366004613d3c565b610863565b005b603754600160a01b900460ff16610324565b6103496103c4366004613d57565b60009081526020819052604090206001015490565b6103a26103e7366004613d70565b610888565b6103497f6dac4cc0544e34aa1a4ed2862f6de78290e3f18f00fe77179ee8ef34de9dfa2481565b6103496108b2565b6103a2610429366004613d70565b6108bc565b61044161043c366004613d70565b61093b565b60408051928352602083019190915201610330565b6037546001600160a01b03165b6040516001600160a01b039091168152602001610330565b6103a2610489366004613db3565b6109ab565b6104416109cc565b6103496104a4366004613d57565b6109e7565b610349610bde565b6103497ff570a3b94987b56be9e62084f59006353309fa95357dfbc6d3ea78cce6382d1381565b603a546001600160a01b0316610463565b6001610349565b6103496104fe366004613d3c565b60356020526000908152604090205481565b603754600160a81b900460ff16610324565b6103497fcfb9ac928a9a202b47d70fc2e62c0dade955274336ca821ed60aeb2142af92e681565b6103497fbf63066482b01a20567880b14a2934fecb21c925e6bcc0a0a091c59723fa9c0681565b6103a261057e366004613d3c565b610d83565b6038546040516001600160801b039091168152602001610330565b6103a26105ac366004613dce565b610da4565b6103246105bf366004613d70565b610ec4565b6104416105d2366004613e22565b610eed565b6103496110dd565b6103496105ed366004613d57565b6110e7565b603854600160801b90046001600160801b0316610349565b610349600081565b610625610620366004613d57565b611341565b604080519485526020850193909352918301526060820152608001610330565b610625610653366004613d57565b611598565b610441610666366004613d70565b6117dd565b6104637f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f81565b6104637f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f81565b610349611841565b6103496106cf366004613d57565b61184b565b6106256106e2366004613d57565b611c75565b6103a26106f5366004613d3c565b611c93565b6103a2610708366004613ed6565b611cb4565b61062561071b366004613d57565b611de3565b6103a261072e366004613ef3565b611df2565b6103a2610741366004613d70565b6120d7565b61034960008051602061424b83398151915281565b6103a26120fc565b6036546001600160a01b0316610463565b6104637f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e81565b6104416107a9366004613e22565b61210e565b60006001600160e01b03198216637965db0b60e01b14806107df57506301ffc9a760e01b6001600160e01b03198316145b92915050565b603754600090600160a01b900460ff1615801561080c5750603754600160a81b900460ff16155b905090565b6038546000906001600160801b03600160801b82048116911611610836576000610855565b603854610855906001600160801b03600160801b820481169116613f45565b6001600160801b0316905090565b60008051602061424b83398151915261087b81612295565b610884826122a2565b5050565b6000828152602081905260409020600101546108a381612295565b6108ad838361231a565b505050565b600061080c61239e565b6001600160a01b03811633146109315760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61088482826124c5565b6037546000908190600160a01b900460ff161561096a5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156109945760405162461bcd60e51b815260040161092890613f90565b61099f33858561252a565b915091505b9250929050565b60008051602061424b8339815191526109c381612295565b61088482612807565b6000806109df6109da612869565b6128d7565b915091509091565b60007f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c16610a1381612295565b603754600160a81b900460ff16610a5d5760405162461bcd60e51b815260206004820152600e60248201526d11d4d357d393d517d4d15256915160921b6044820152606401610928565b60008311610a7d5760405162461bcd60e51b815260040161092890613fb4565b6000610a87612869565b905080841115610a95578093505b6040516323b872dd60e01b8152336004820152306024820152604481018590527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c9190613fdc565b50603a54604051639bea62ad60e01b8152600481018690526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b158015610b7357600080fd5b505af1158015610b87573d6000803e3d6000fd5b503392507f40812dae8a8ddfad8bbf45f53c5cdbca587edc4238cbcc7537ae84e204b1c8ae9150869050610bbb8185613ff9565b6040805192835260208301919091520160405180910390a2839250505b50919050565b603754600090600160a81b900460ff1615610c0b5760405162461bcd60e51b815260040161092890613f90565b7f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c16610c3581612295565b6037805460ff60a81b1916600160a81b179055603880546001600160801b03169055610c616000612807565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b0316906370a0823190602401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec919061400c565b90508015610d2e57603654610d2e906001600160a01b037f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e81169116836129b4565b6036546001600160a01b0316337fe51b546a59a5440500bc9464ab1cb969d07a4508292c32e540ac0f37b644aca883610d65612869565b6040805192835260208301919091520160405180910390a391505090565b60008051602061424b833981519152610d9b81612295565b61088482612a45565b60025460019060ff1680610db75750303b155b80610dc3575060015481115b610e265760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610928565b60025460ff16158015610e47576002805460ff191660019081179091558290555b6001600160a01b038616610e6d5760405162461bcd60e51b815260040161092890614025565b610e7860008761231a565b610e9060008051602061424b8339815191528761231a565b610e99856122a2565b610ea284612807565b610eab83612a45565b8015610ebc576002805460ff191690555b505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6037546000908190600160a01b900460ff1615610f1c5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff1615610f465760405162461bcd60e51b815260040161092890613f90565b42851015610f965760405162461bcd60e51b815260206004820152601a60248201527f5349474e41545552455f444541444c494e455f455850495245440000000000006044820152606401610928565b6001600160a01b0388166000908152603560205260408120805461103f917fcfb9ac928a9a202b47d70fc2e62c0dade955274336ca821ed60aeb2142af92e6918c918c918c9187610fe683614055565b909155506040805160208101969096526001600160a01b03948516908601526060850192909252909116608083015260a082015260c0810188905260e00160405160208183030381529060405280519060200120612bed565b9050611082898287878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3b92505050565b6110c25760405162461bcd60e51b815260206004820152601160248201527014d251d3905515549157d2539590531251607a1b6044820152606401610928565b6110cd89898961252a565b9250925050965096945050505050565b600061080c612869565b603754600090600160a81b900460ff16156111145760405162461bcd60e51b815260040161092890613f90565b60008051602061424b83398151915261112c81612295565b6000831161114c5760405162461bcd60e51b815260040161092890613fb4565b6000611156612869565b90506000611163826128d7565b915050600081116111b65760405162461bcd60e51b815260206004820152601a60248201527f4e4f5f43555252454e545f444546494349545f4241434b494e470000000000006044820152606401610928565b60008186116111c557856111c7565b815b6040516323b872dd60e01b8152336004820152306024820152604481018290529091507f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6001600160a01b0316906323b872dd906064016020604051808303816000875af115801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190613fdc565b50603a54604051639bea62ad60e01b8152600481018390526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b1580156112a857600080fd5b505af11580156112bc573d6000803e3d6000fd5b50506001600160a01b037f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f1691503390507f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea3838061131a8188613ff9565b6040805193845260208401929092529082015260600160405180910390a395945050505050565b6037546000908190819081906001600160a01b03161515818161136457866113d1565b6037546040516318fdd06b60e01b8152600481018990526001600160a01b03909116906318fdd06b90602401602060405180830381865afa1580156113ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d1919061400c565b604051635ded74a560e01b815260048101829052600160248201529091506000906001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f1690635ded74a590604401602060405180830381865afa158015611443573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611467919061400c565b6040516329ede30f60e21b8152600481018290526000602482018190529192506001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f169063a7b78c3c90604401602060405180830381865afa1580156114d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fc919061400c565b905060008461150c576000611579565b60375460405163959d6d2960e01b8152600481018490526001600160a01b039091169063959d6d2990602401602060405180830381865afa158015611555573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611579919061400c565b9050826115868284613ff9565b909b909a509198509650945050505050565b6037546000908190819081906001600160a01b0316151581816115bb5786611628565b6037546040516352510fd160e11b8152600481018990526001600160a01b039091169063a4a21fa290602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611628919061400c565b604051635ded74a560e01b8152600481018290526000602482018190529192506001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f1690635ded74a590604401602060405180830381865afa158015611699573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bd919061400c565b6040516329ede30f60e21b815260048101829052600160248201529091506000906001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f169063a7b78c3c90604401602060405180830381865afa15801561172f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611753919061400c565b90506000846117635760006117d0565b6037546040516345d6494d60e01b8152600481018490526001600160a01b03909116906345d6494d90602401602060405180830381865afa1580156117ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d0919061400c565b905082611586828461406e565b6037546000908190600160a01b900460ff161561180c5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156118365760405162461bcd60e51b815260040161092890613f90565b61099f338585612d7f565b600061080c613043565b603754600090600160a81b900460ff16156118785760405162461bcd60e51b815260040161092890613f90565b60008051602061424b83398151915261189081612295565b600083116118b05760405162461bcd60e51b815260040161092890613fb4565b60006118bd6109da612869565b915050600081116119105760405162461bcd60e51b815260206004820152601a60248201527f4e4f5f43555252454e545f444546494349545f4241434b494e470000000000006044820152606401610928565b604051635ded74a560e01b815260048101829052600060248201819052906119ac906001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f1690635ded74a590604401602060405180830381865afa158015611983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a7919061400c565b613074565b9050806001600160801b03168510611ad75780603860108282829054906101000a90046001600160801b03166119e29190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550611a4f3330836001600160801b03167f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b03166130e1909392919063ffffffff16565b604080516001600160801b03831681526020810184905260008183015290517f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b03169133917f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea39181900360600190a36001600160801b03169250610bd89050565b6040516329ede30f60e21b815260048101869052600060248201819052907f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f6001600160a01b03169063a7b78c3c90604401602060405180830381865afa158015611b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6a919061400c565b905085603860108282829054906101000a90046001600160801b0316611b909190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550611bf43330887f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b03166130e1909392919063ffffffff16565b6001600160a01b037f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e16337f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea38884611c4c8189613ff9565b6040805193845260208401929092529082015260600160405180910390a3859450505050610bd8565b600080600080611c8485613183565b93509350935093509193509193565b60008051602061424b833981519152611cab81612295565b610884826133f6565b7f6dac4cc0544e34aa1a4ed2862f6de78290e3f18f00fe77179ee8ef34de9dfa24611cde81612295565b8115611d3857603754600160a01b900460ff1615611d335760405162461bcd60e51b815260206004820152601260248201527123a9a6afa0a62922a0a22cafa32927ad22a760711b6044820152606401610928565b611d88565b603754600160a01b900460ff16611d885760405162461bcd60e51b815260206004820152601460248201527323a9a6afa0a62922a0a22cafaaa7232927ad22a760611b6044820152606401610928565b60378054831515600160a01b0260ff60a01b1990911617905560405133907f2aa23821d2fd7524b53239d5f8398ea59652bbfea171645c0da0dbe82afb5d4390611dd790851515815260200190565b60405180910390a25050565b600080600080611c8485613448565b7fbf63066482b01a20567880b14a2934fecb21c925e6bcc0a0a091c59723fa9c06611e1c81612295565b60008211611e3c5760405162461bcd60e51b815260040161092890613fb4565b7f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6001600160a01b0316846001600160a01b031603611f4b576039546040516370a0823160e01b81523060048201526000916001600160801b0316906001600160a01b038716906370a0823190602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed919061400c565b611ef79190613ff9565b905082811015611f495760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f47484f5f544f5f5245534355450000000000006044820152606401610928565b505b7f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b0316846001600160a01b031603612070576038546040516370a0823160e01b8152306004820152600091600160801b90046001600160801b0316906001600160a01b038716906370a0823190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612003919061400c565b61200d9190613ff9565b90508281101561206e5760405162461bcd60e51b815260206004820152602660248201527f494e53554646494349454e545f45584f47454e4f55535f41535345545f544f5f60448201526552455343554560d01b6064820152608401610928565b505b6120846001600160a01b03851684846129b4565b826001600160a01b0316846001600160a01b03167f77023e19c7343ad491fd706c36335ca0e738340a91f29b1fd81e2673d44896c4846040516120c991815260200190565b60405180910390a350505050565b6000828152602081905260409020600101546120f281612295565b6108ad83836124c5565b6121046136a5565b61210c6137a9565b565b6037546000908190600160a01b900460ff161561213d5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156121675760405162461bcd60e51b815260040161092890613f90565b428510156121b75760405162461bcd60e51b815260206004820152601a60248201527f5349474e41545552455f444541444c494e455f455850495245440000000000006044820152606401610928565b6001600160a01b03881660009081526035602052604081208054612207917ff570a3b94987b56be9e62084f59006353309fa95357dfbc6d3ea78cce6382d13918c918c918c9187610fe683614055565b905061224a898287878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3b92505050565b61228a5760405162461bcd60e51b815260206004820152601160248201527014d251d3905515549157d2539590531251607a1b6044820152606401610928565b6110cd898989612d7f565b61229f81336138cb565b50565b6001600160a01b0381166122c85760405162461bcd60e51b815260040161092890614025565b603680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f13f4413d8d93a259bd6c10f35095371f30ed50f81a73407e52e9f02000d5d16b90600090a35050565b6123248282610ec4565b610884576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561235a3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000306001600160a01b037f000000000000000000000000320be97b4d10b6d20a05cae53a479fa2a0187e8e161480156123f757507f000000000000000000000000000000000000000000000000000000000000000146145b1561242157507f0e512f343c4d7440b1036669b20e70dde8a43864811ee9b9914c90547fbac33a90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f75b3310af9b713b9bc9fef8cd0b585229d2e229644a8175e6b110c4f932640a8828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6124cf8282610ec4565b15610884576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008060008060008061253c88613448565b935093509350935061254f898589613924565b6000841161256f5760405162461bcd60e51b815260040161092890613fb4565b603854600160801b90046001600160801b03168411156125ea5760405162461bcd60e51b815260206004820152603060248201527f494e53554646494349454e545f415641494c41424c455f45584f47454e4f555360448201526f5f41535345545f4c495155494449545960801b6064820152608401610928565b83603860108282829054906101000a90046001600160801b031661260e9190613f45565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061263b81613074565b603980546000906126569084906001600160801b0316614081565b82546001600160801b039182166101009390930a9283029190920219909116179055506040516323b872dd60e01b81526001600160a01b038a81166004830152306024830152604482018590527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f16906323b872dd906064016020604051808303816000875af11580156126ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127129190613fdc565b50603a54604051639bea62ad60e01b8152600481018490526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b15801561275957600080fd5b505af115801561276d573d6000803e3d6000fd5b506127a79250506001600160a01b037f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e16905088866129b4565b60408051858152602081018590529081018290526001600160a01b0380891691908b16907f35b18eb91d0f8ce2968fdf81c1ed9ac429776c7260cdb8bf35c314564e714f66906060015b60405180910390a3509197909650945050505050565b603880546001600160801b038381166001600160801b031983168117909355604080519190921680825260208201939093527fe0f222fd3dc07d1f2556e7d34819cc5fe0ab68fedb472dc2de611aa3398409ce91015b60405180910390a15050565b603a5460405163c701e30560e01b81523060048201526000916001600160a01b03169063c701e305906024015b602060405180830381865afa1580156128b3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080c919061400c565b6038546040516329ede30f60e21b8152600160801b9091046001600160801b0316600482015260006024820181905290819081907f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f6001600160a01b03169063a7b78c3c90604401602060405180830381865afa15801561295c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612980919061400c565b905083811061299e576129938482613ff9565b946000945092505050565b60006129aa8286613ff9565b9250925050915091565b60405163a9059cbb60e01b8082526001600160a01b0384166004830152602482018390529060008060448382895af16129f1573d6000803e3d6000fd5b506129fb8461392c565b612a3f5760405162461bcd60e51b815260206004820152601560248201527423a83b191d103330b4b632b2103a3930b739b332b960591b6044820152606401610928565b50505050565b6001600160a01b038116612a6b5760405162461bcd60e51b815260040161092890614025565b603a80546001600160a01b038381166001600160a01b031983161790925560405163095ea7b360e01b81529082166004820181905260006024830152917f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f169063095ea7b3906044016020604051808303816000875af1158015612af3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b179190613fdc565b5060405163095ea7b360e01b81526001600160a01b03838116600483015260001960248301527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f169063095ea7b3906044016020604051808303816000875af1158015612b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bac9190613fdc565b50604080516001600160a01b038084168252841660208201527f2c08a25f68366783e094daa7889fc9e62fd3baeebb3cc5e7ff37a53d52336ac8910161285d565b60006107df612bfa61239e565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612c4a85856139d2565b90925090506000816004811115612c6357612c636140a1565b148015612c815750856001600160a01b0316826001600160a01b0316145b15612c9157600192505050612d78565b600080876001600160a01b0316631626ba7e60e01b8888604051602401612cb9929190614107565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612cf79190614128565b600060405180830381855afa9150503d8060008114612d32576040519150601f19603f3d011682016040523d82523d6000602084013e612d37565b606091505b5091509150818015612d4a575080516020145b8015612d7157508051630b135d3f60e11b90612d6f908301602090810190840161400c565b145b9450505050505b9392505050565b600080600080600080612d9188613183565b935093509350935060008411612db95760405162461bcd60e51b815260040161092890613fb4565b6038546001600160801b0380821691612ddb918791600160801b90041661406e565b1115612e335760405162461bcd60e51b815260206004820152602160248201527f45584f47454e4f55535f41535345545f4558504f535552455f544f4f5f4849476044820152600960fb1b6064820152608401610928565b83603860108282829054906101000a90046001600160801b0316612e579190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612e8481613074565b60398054600090612e9f9084906001600160801b0316614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612f038930867f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e6001600160a01b03166130e1909392919063ffffffff16565b603a546040516355ada22b60e11b8152600481018490526001600160a01b039091169063ab5b445690602401600060405180830381600087803b158015612f4957600080fd5b505af1158015612f5d573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038a81166004830152602482018790527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f16925063a9059cbb91506044016020604051808303816000875af1158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff49190613fdc565b5060408051858152602081018490529081018290526001600160a01b0380891691908b16907fefd9053c6d75eeb7635ae405072e58d5d1588e1ee0db5d212e6afcb529b975e3906060016127f1565b603a54604051630e71473960e11b81523060048201526000916001600160a01b031690631ce28e7290602401612896565b60006001600160801b038211156130dd5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610928565b5090565b6040516323b872dd60e01b8082526001600160a01b038581166004840152841660248301526044820183905290600080606483828a5af1613126573d6000803e3d6000fd5b506131308561392c565b61317c5760405162461bcd60e51b815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d000000000000006044820152606401610928565b5050505050565b6037546040516329ede30f60e21b815260048101839052600060248201819052918291829182916001600160a01b0391821615159183917f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f9091169063a7b78c3c90604401602060405180830381865afa158015613205573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613229919061400c565b90506000826132395760006132a6565b60375460405163959d6d2960e01b8152600481018490526001600160a01b039091169063959d6d2990602401602060405180830381865afa158015613282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132a6919061400c565b905060006132b48284613ff9565b90506000846132c35781613330565b6037546040516318fdd06b60e01b8152600481018490526001600160a01b03909116906318fdd06b90602401602060405180830381865afa15801561330c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613330919061400c565b604051635ded74a560e01b815260048101829052600160248201529091506000906001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f1690635ded74a590604401602060405180830381865afa1580156133a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c6919061400c565b905060006133d48484613ff9565b9050816133e18285613ff9565b909d909c50929a509850909650505050505050565b603780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8a53d8a38ee2969ab6c2a4793fc6d15aac23906030c4943495dd2e843b48f9d690600090a35050565b6037546040516329ede30f60e21b815260048101839052600160248201526000918291829182916001600160a01b0391821615159183917f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f9091169063a7b78c3c90604401602060405180830381865afa1580156134ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ee919061400c565b90506000826134fe57600061356b565b6037546040516345d6494d60e01b8152600481018490526001600160a01b03909116906345d6494d90602401602060405180830381865afa158015613547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061356b919061400c565b90506000613579828461406e565b905060008461358857816135f5565b6037546040516352510fd160e11b8152600481018490526001600160a01b039091169063a4a21fa290602401602060405180830381865afa1580156135d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f5919061400c565b604051635ded74a560e01b8152600481018290526000602482018190529192506001600160a01b037f000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f1690635ded74a590604401602060405180830381865afa158015613666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368a919061400c565b905060006136988385613ff9565b9050816133e1828561406e565b6000806136b0613a14565b9150915060008183116136c45760006136ce565b6136ce8284613ff9565b905060006136db836128d7565b5090506000811180156136ee5750600082115b15612a3f578181116137005780613702565b815b6039805491925082916000906137229084906001600160801b0316614081565b82546001600160801b039182166101009390930a928302919092021990911617905550603a546040516355ada22b60e11b8152600481018390526001600160a01b039091169063ab5b445690602401600060405180830381600087803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050505050505050565b6039546001600160801b0316801561229f57603980546001600160801b031916905560365460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390527f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f9091169063a9059cbb906044016020604051808303816000875af115801561383f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138639190613fdc565b506036546040518281526001600160a01b037f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f81169216907fb29fcda740927812f5a71075b62e132bead3769a455319c29b9a1cc461a654759060200160405180910390a350565b6138d58282610ec4565b610884576138e281613a84565b6138ed836020613a96565b6040516020016138fe929190614144565b60408051601f198184030181529082905262461bcd60e51b8252610928916004016141b9565b6108ad6136a5565b6000613951565b62461bcd60e51b600052602060045280602452508060445260646000fd5b3d801561399057602081146139c15761398b7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f613933565b610bd8565b823b6139b8576139b87311d41d8c8e881b9bdd08184818dbdb9d1c9858dd60621b6014613933565b60019150610bd8565b3d6000803e50506000511515919050565b6000808251604103613a085760208301516040840151606085015160001a6139fc87828585613c32565b945094505050506109a4565b506000905060026109a4565b603a54604051632cdcd8af60e11b815230600482015260009182916001600160a01b03909116906359b9b15e906024016040805180830381865afa158015613a60573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109df91906141cc565b60606107df6001600160a01b03831660145b60606000613aa58360026141f0565b613ab090600261406e565b67ffffffffffffffff811115613ac857613ac8614207565b6040519080825280601f01601f191660200182016040528015613af2576020820181803683370190505b509050600360fc1b81600081518110613b0d57613b0d61421d565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613b3c57613b3c61421d565b60200101906001600160f81b031916908160001a9053506000613b608460026141f0565b613b6b90600161406e565b90505b6001811115613be3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613b9f57613b9f61421d565b1a60f81b828281518110613bb557613bb561421d565b60200101906001600160f81b031916908160001a90535060049490941c93613bdc81614233565b9050613b6e565b508315612d785760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610928565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613c695750600090506003613ced565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613cbd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613ce657600060019250925050613ced565b9150600090505b94509492505050565b600060208284031215613d0857600080fd5b81356001600160e01b031981168114612d7857600080fd5b80356001600160a01b0381168114613d3757600080fd5b919050565b600060208284031215613d4e57600080fd5b612d7882613d20565b600060208284031215613d6957600080fd5b5035919050565b60008060408385031215613d8357600080fd5b82359150613d9360208401613d20565b90509250929050565b80356001600160801b0381168114613d3757600080fd5b600060208284031215613dc557600080fd5b612d7882613d9c565b60008060008060808587031215613de457600080fd5b613ded85613d20565b9350613dfb60208601613d20565b9250613e0960408601613d9c565b9150613e1760608601613d20565b905092959194509250565b60008060008060008060a08789031215613e3b57600080fd5b613e4487613d20565b955060208701359450613e5960408801613d20565b935060608701359250608087013567ffffffffffffffff80821115613e7d57600080fd5b818901915089601f830112613e9157600080fd5b813581811115613ea057600080fd5b8a6020828501011115613eb257600080fd5b6020830194508093505050509295509295509295565b801515811461229f57600080fd5b600060208284031215613ee857600080fd5b8135612d7881613ec8565b600080600060608486031215613f0857600080fd5b613f1184613d20565b9250613f1f60208501613d20565b9150604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115613f6557613f65613f2f565b5092915050565b6020808252600a908201526923a9a6afa32927ad22a760b11b604082015260600190565b6020808252600a908201526911d4d357d4d15256915160b21b604082015260600190565b6020808252600e908201526d1253959053125117d05353d5539560921b604082015260600190565b600060208284031215613fee57600080fd5b8151612d7881613ec8565b818103818111156107df576107df613f2f565b60006020828403121561401e57600080fd5b5051919050565b60208082526016908201527516915493d7d05111149154d4d7d393d517d59053125160521b604082015260600190565b60006001820161406757614067613f2f565b5060010190565b808201808211156107df576107df613f2f565b6001600160801b03818116838216019080821115613f6557613f65613f2f565b634e487b7160e01b600052602160045260246000fd5b60005b838110156140d25781810151838201526020016140ba565b50506000910152565b600081518084526140f38160208601602086016140b7565b601f01601f19169290920160200192915050565b82815260406020820152600061412060408301846140db565b949350505050565b6000825161413a8184602087016140b7565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161417c8160178501602088016140b7565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516141ad8160288401602088016140b7565b01602801949350505050565b602081526000612d7860208301846140db565b600080604083850312156141df57600080fd5b505080516020909101519092909150565b80820281158282048414176107df576107df613f2f565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008161424257614242613f2f565b50600019019056fe3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0a164736f6c6343000816000a","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"none","useLiteralContent":false},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["forge-std/=lib/forge-std/src/","aave-v3-origin/=lib/aave-v3-origin/src/","aave-v3-origin-tests/=lib/aave-v3-origin/tests/","solidity-utils/=lib/aave-v3-origin/lib/solidity-utils/src/","@openzeppelin/contracts-upgradeable/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/","ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","halmos-cheatcodes/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/"],"viaIR":false},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f",{"internalType":"address","name":"ghoToken","type":"address"}],["0xD4fa2D31b7968E448877f69A96DE69f5de8cD23E",{"internalType":"address","name":"underlyingAsset","type":"address"}],["0xEE73e0c5Cc8E4cAf400baB5239860696Ff44D64f",{"internalType":"address","name":"priceStrategy","type":"address"}]],"compiler_version":"v0.8.22+commit.4fc1097e","is_verified_via_verifier_alliance":false,"verified_at":"2026-03-05T12:17:09.011042Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101a060405260006001553480156200001757600080fd5b50604051620046f5380380620046f58339810160408190526200003a91620002cc565b604080518082018252600381526247534d60e81b60208083019182528351808501855260018152603160f81b908201529151902060e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a081815285517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818701819052818801959095526060810193909352608080840192909252308382018190528651808503909201825260c09384019096528051940193909320909252919052610120528282826001600160a01b0383166200016b5760405162461bcd60e51b815260206004820152601660248201527f5a45524f5f414444524553535f4e4f545f56414c49440000000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216620001c35760405162461bcd60e51b815260206004820152601660248201527f5a45524f5f414444524553535f4e4f545f56414c494400000000000000000000604482015260640162000162565b816001600160a01b0316816001600160a01b031663e60253936040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200020c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000232919062000316565b6001600160a01b0316146200028a5760405162461bcd60e51b815260206004820152601660248201527f494e56414c49445f50524943455f535452415445475900000000000000000000604482015260640162000162565b6001600160a01b0392831661014052908216610160521661018052506200033b915050565b80516001600160a01b0381168114620002c757600080fd5b919050565b600080600060608486031215620002e257600080fd5b620002ed84620002af565b9250620002fd60208501620002af565b91506200030d60408501620002af565b90509250925092565b6000602082840312156200032957600080fd5b6200033482620002af565b9392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516142776200047e60003960008181610670015281816113fc0152818161149101528181611652015281816116e80152818161193c01528181611af70152818161290d015281816131bc0152818161335b01528181613481015261361f01526000818161077901528181610c7901528181610d0501528181611a1701528181611a7001528181611bbc01528181611bfe01528181611f4d0152818161277e0152612ecb01526000818161069701528181610ab7015281816111ec015281816112c801528181611e3e015281816126a501528181612aaa01528181612b3f01528181612f85015281816137f40152613877015260006124280152600061247701526000612452015260006123ab015260006123d5015260006123ff01526142776000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c80638fa468901161019d578063b295a00e116100e9578063cea9d26f116100a2578063dc49a07b1161007c578063dc49a07b1461075b578063e28178cc14610763578063e602539314610774578063f493ca701461079b57600080fd5b8063cea9d26f14610720578063d547741f14610733578063d853015e1461074657600080fd5b8063b295a00e146106b9578063c350de6c146106c1578063c431280e146106d4578063c876a2a7146106e7578063cab46bc6146106fa578063cea462131461070d57600080fd5b80639b745aec11610156578063aa278b0311610130578063aa278b0314610645578063aa443ac014610658578063ab16b58a1461066b578063b1c660f71461069257600080fd5b80639b745aec146105f2578063a217fddf1461060a578063a9c3ebda1461061257600080fd5b80638fa468901461058357806391362b871461059e57806391d14854146105b1578063954c1c0d146105c45780639abeb940146105d75780639b5c9261146105df57600080fd5b80634101d9f41161025c5780637630b2b31161021557806380bc659a116101ef57806380bc659a146105105780638a96e304146105225780638bcd9797146105495780638dbf6c811461057057600080fd5b80637630b2b3146104d857806378cf12b2146104e95780637ecebe00146104f057600080fd5b80634101d9f414610456578063430b09521461047b578063476cce031461048e5780635921c8e014610496578063605297e1146104a95780636400a4af146104b157600080fd5b8063236fc8ad116102c9578063353f03bd116102a3578063353f03bd146103ec5780633644e5151461041357806336568abe1461041b57806340fb07a01461042e57600080fd5b8063236fc8ad146103a4578063248a9ca3146103b65780632f2ff15d146103d957600080fd5b806301ffc9a71461031157806310ce051614610339578063110934d61461034157806316d8887a146103575780631f3da1501461037e5780631fde40bb1461038f575b600080fd5b61032461031f366004613cf6565b6107ae565b60405190151581526020015b60405180910390f35b6103246107e5565b610349610811565b604051908152602001610330565b6103497f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c1681565b6039546001600160801b0316610349565b6103a261039d366004613d3c565b610863565b005b603754600160a01b900460ff16610324565b6103496103c4366004613d57565b60009081526020819052604090206001015490565b6103a26103e7366004613d70565b610888565b6103497f6dac4cc0544e34aa1a4ed2862f6de78290e3f18f00fe77179ee8ef34de9dfa2481565b6103496108b2565b6103a2610429366004613d70565b6108bc565b61044161043c366004613d70565b61093b565b60408051928352602083019190915201610330565b6037546001600160a01b03165b6040516001600160a01b039091168152602001610330565b6103a2610489366004613db3565b6109ab565b6104416109cc565b6103496104a4366004613d57565b6109e7565b610349610bde565b6103497ff570a3b94987b56be9e62084f59006353309fa95357dfbc6d3ea78cce6382d1381565b603a546001600160a01b0316610463565b6001610349565b6103496104fe366004613d3c565b60356020526000908152604090205481565b603754600160a81b900460ff16610324565b6103497fcfb9ac928a9a202b47d70fc2e62c0dade955274336ca821ed60aeb2142af92e681565b6103497fbf63066482b01a20567880b14a2934fecb21c925e6bcc0a0a091c59723fa9c0681565b6103a261057e366004613d3c565b610d83565b6038546040516001600160801b039091168152602001610330565b6103a26105ac366004613dce565b610da4565b6103246105bf366004613d70565b610ec4565b6104416105d2366004613e22565b610eed565b6103496110dd565b6103496105ed366004613d57565b6110e7565b603854600160801b90046001600160801b0316610349565b610349600081565b610625610620366004613d57565b611341565b604080519485526020850193909352918301526060820152608001610330565b610625610653366004613d57565b611598565b610441610666366004613d70565b6117dd565b6104637f000000000000000000000000000000000000000000000000000000000000000081565b6104637f000000000000000000000000000000000000000000000000000000000000000081565b610349611841565b6103496106cf366004613d57565b61184b565b6106256106e2366004613d57565b611c75565b6103a26106f5366004613d3c565b611c93565b6103a2610708366004613ed6565b611cb4565b61062561071b366004613d57565b611de3565b6103a261072e366004613ef3565b611df2565b6103a2610741366004613d70565b6120d7565b61034960008051602061424b83398151915281565b6103a26120fc565b6036546001600160a01b0316610463565b6104637f000000000000000000000000000000000000000000000000000000000000000081565b6104416107a9366004613e22565b61210e565b60006001600160e01b03198216637965db0b60e01b14806107df57506301ffc9a760e01b6001600160e01b03198316145b92915050565b603754600090600160a01b900460ff1615801561080c5750603754600160a81b900460ff16155b905090565b6038546000906001600160801b03600160801b82048116911611610836576000610855565b603854610855906001600160801b03600160801b820481169116613f45565b6001600160801b0316905090565b60008051602061424b83398151915261087b81612295565b610884826122a2565b5050565b6000828152602081905260409020600101546108a381612295565b6108ad838361231a565b505050565b600061080c61239e565b6001600160a01b03811633146109315760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61088482826124c5565b6037546000908190600160a01b900460ff161561096a5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156109945760405162461bcd60e51b815260040161092890613f90565b61099f33858561252a565b915091505b9250929050565b60008051602061424b8339815191526109c381612295565b61088482612807565b6000806109df6109da612869565b6128d7565b915091509091565b60007f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c16610a1381612295565b603754600160a81b900460ff16610a5d5760405162461bcd60e51b815260206004820152600e60248201526d11d4d357d393d517d4d15256915160921b6044820152606401610928565b60008311610a7d5760405162461bcd60e51b815260040161092890613fb4565b6000610a87612869565b905080841115610a95578093505b6040516323b872dd60e01b8152336004820152306024820152604481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c9190613fdc565b50603a54604051639bea62ad60e01b8152600481018690526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b158015610b7357600080fd5b505af1158015610b87573d6000803e3d6000fd5b503392507f40812dae8a8ddfad8bbf45f53c5cdbca587edc4238cbcc7537ae84e204b1c8ae9150869050610bbb8185613ff9565b6040805192835260208301919091520160405180910390a2839250505b50919050565b603754600090600160a81b900460ff1615610c0b5760405162461bcd60e51b815260040161092890613f90565b7f5e17fc5225d4a099df75359ce1f405503ca79498a8dc46a7d583235a0ee45c16610c3581612295565b6037805460ff60a81b1916600160a81b179055603880546001600160801b03169055610c616000612807565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec919061400c565b90508015610d2e57603654610d2e906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836129b4565b6036546001600160a01b0316337fe51b546a59a5440500bc9464ab1cb969d07a4508292c32e540ac0f37b644aca883610d65612869565b6040805192835260208301919091520160405180910390a391505090565b60008051602061424b833981519152610d9b81612295565b61088482612a45565b60025460019060ff1680610db75750303b155b80610dc3575060015481115b610e265760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610928565b60025460ff16158015610e47576002805460ff191660019081179091558290555b6001600160a01b038616610e6d5760405162461bcd60e51b815260040161092890614025565b610e7860008761231a565b610e9060008051602061424b8339815191528761231a565b610e99856122a2565b610ea284612807565b610eab83612a45565b8015610ebc576002805460ff191690555b505050505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6037546000908190600160a01b900460ff1615610f1c5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff1615610f465760405162461bcd60e51b815260040161092890613f90565b42851015610f965760405162461bcd60e51b815260206004820152601a60248201527f5349474e41545552455f444541444c494e455f455850495245440000000000006044820152606401610928565b6001600160a01b0388166000908152603560205260408120805461103f917fcfb9ac928a9a202b47d70fc2e62c0dade955274336ca821ed60aeb2142af92e6918c918c918c9187610fe683614055565b909155506040805160208101969096526001600160a01b03948516908601526060850192909252909116608083015260a082015260c0810188905260e00160405160208183030381529060405280519060200120612bed565b9050611082898287878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3b92505050565b6110c25760405162461bcd60e51b815260206004820152601160248201527014d251d3905515549157d2539590531251607a1b6044820152606401610928565b6110cd89898961252a565b9250925050965096945050505050565b600061080c612869565b603754600090600160a81b900460ff16156111145760405162461bcd60e51b815260040161092890613f90565b60008051602061424b83398151915261112c81612295565b6000831161114c5760405162461bcd60e51b815260040161092890613fb4565b6000611156612869565b90506000611163826128d7565b915050600081116111b65760405162461bcd60e51b815260206004820152601a60248201527f4e4f5f43555252454e545f444546494349545f4241434b494e470000000000006044820152606401610928565b60008186116111c557856111c7565b815b6040516323b872dd60e01b8152336004820152306024820152604481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af115801561123d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112619190613fdc565b50603a54604051639bea62ad60e01b8152600481018390526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b1580156112a857600080fd5b505af11580156112bc573d6000803e3d6000fd5b50506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691503390507f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea3838061131a8188613ff9565b6040805193845260208401929092529082015260600160405180910390a395945050505050565b6037546000908190819081906001600160a01b03161515818161136457866113d1565b6037546040516318fdd06b60e01b8152600481018990526001600160a01b03909116906318fdd06b90602401602060405180830381865afa1580156113ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d1919061400c565b604051635ded74a560e01b815260048101829052600160248201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ded74a590604401602060405180830381865afa158015611443573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611467919061400c565b6040516329ede30f60e21b8152600481018290526000602482018190529192506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a7b78c3c90604401602060405180830381865afa1580156114d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fc919061400c565b905060008461150c576000611579565b60375460405163959d6d2960e01b8152600481018490526001600160a01b039091169063959d6d2990602401602060405180830381865afa158015611555573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611579919061400c565b9050826115868284613ff9565b909b909a509198509650945050505050565b6037546000908190819081906001600160a01b0316151581816115bb5786611628565b6037546040516352510fd160e11b8152600481018990526001600160a01b039091169063a4a21fa290602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611628919061400c565b604051635ded74a560e01b8152600481018290526000602482018190529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ded74a590604401602060405180830381865afa158015611699573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bd919061400c565b6040516329ede30f60e21b815260048101829052600160248201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a7b78c3c90604401602060405180830381865afa15801561172f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611753919061400c565b90506000846117635760006117d0565b6037546040516345d6494d60e01b8152600481018490526001600160a01b03909116906345d6494d90602401602060405180830381865afa1580156117ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d0919061400c565b905082611586828461406e565b6037546000908190600160a01b900460ff161561180c5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156118365760405162461bcd60e51b815260040161092890613f90565b61099f338585612d7f565b600061080c613043565b603754600090600160a81b900460ff16156118785760405162461bcd60e51b815260040161092890613f90565b60008051602061424b83398151915261189081612295565b600083116118b05760405162461bcd60e51b815260040161092890613fb4565b60006118bd6109da612869565b915050600081116119105760405162461bcd60e51b815260206004820152601a60248201527f4e4f5f43555252454e545f444546494349545f4241434b494e470000000000006044820152606401610928565b604051635ded74a560e01b815260048101829052600060248201819052906119ac906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ded74a590604401602060405180830381865afa158015611983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a7919061400c565b613074565b9050806001600160801b03168510611ad75780603860108282829054906101000a90046001600160801b03166119e29190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550611a4f3330836001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166130e1909392919063ffffffff16565b604080516001600160801b03831681526020810184905260008183015290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169133917f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea39181900360600190a36001600160801b03169250610bd89050565b6040516329ede30f60e21b815260048101869052600060248201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a7b78c3c90604401602060405180830381865afa158015611b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6a919061400c565b905085603860108282829054906101000a90046001600160801b0316611b909190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550611bf43330887f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166130e1909392919063ffffffff16565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016337f4c41558c3fb5d20cbb8485f911a1b9b6e26c6a8ef6f8450ae816463725a65ea38884611c4c8189613ff9565b6040805193845260208401929092529082015260600160405180910390a3859450505050610bd8565b600080600080611c8485613183565b93509350935093509193509193565b60008051602061424b833981519152611cab81612295565b610884826133f6565b7f6dac4cc0544e34aa1a4ed2862f6de78290e3f18f00fe77179ee8ef34de9dfa24611cde81612295565b8115611d3857603754600160a01b900460ff1615611d335760405162461bcd60e51b815260206004820152601260248201527123a9a6afa0a62922a0a22cafa32927ad22a760711b6044820152606401610928565b611d88565b603754600160a01b900460ff16611d885760405162461bcd60e51b815260206004820152601460248201527323a9a6afa0a62922a0a22cafaaa7232927ad22a760611b6044820152606401610928565b60378054831515600160a01b0260ff60a01b1990911617905560405133907f2aa23821d2fd7524b53239d5f8398ea59652bbfea171645c0da0dbe82afb5d4390611dd790851515815260200190565b60405180910390a25050565b600080600080611c8485613448565b7fbf63066482b01a20567880b14a2934fecb21c925e6bcc0a0a091c59723fa9c06611e1c81612295565b60008211611e3c5760405162461bcd60e51b815260040161092890613fb4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603611f4b576039546040516370a0823160e01b81523060048201526000916001600160801b0316906001600160a01b038716906370a0823190602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed919061400c565b611ef79190613ff9565b905082811015611f495760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f47484f5f544f5f5245534355450000000000006044820152606401610928565b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603612070576038546040516370a0823160e01b8152306004820152600091600160801b90046001600160801b0316906001600160a01b038716906370a0823190602401602060405180830381865afa158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612003919061400c565b61200d9190613ff9565b90508281101561206e5760405162461bcd60e51b815260206004820152602660248201527f494e53554646494349454e545f45584f47454e4f55535f41535345545f544f5f60448201526552455343554560d01b6064820152608401610928565b505b6120846001600160a01b03851684846129b4565b826001600160a01b0316846001600160a01b03167f77023e19c7343ad491fd706c36335ca0e738340a91f29b1fd81e2673d44896c4846040516120c991815260200190565b60405180910390a350505050565b6000828152602081905260409020600101546120f281612295565b6108ad83836124c5565b6121046136a5565b61210c6137a9565b565b6037546000908190600160a01b900460ff161561213d5760405162461bcd60e51b815260040161092890613f6c565b603754600160a81b900460ff16156121675760405162461bcd60e51b815260040161092890613f90565b428510156121b75760405162461bcd60e51b815260206004820152601a60248201527f5349474e41545552455f444541444c494e455f455850495245440000000000006044820152606401610928565b6001600160a01b03881660009081526035602052604081208054612207917ff570a3b94987b56be9e62084f59006353309fa95357dfbc6d3ea78cce6382d13918c918c918c9187610fe683614055565b905061224a898287878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3b92505050565b61228a5760405162461bcd60e51b815260206004820152601160248201527014d251d3905515549157d2539590531251607a1b6044820152606401610928565b6110cd898989612d7f565b61229f81336138cb565b50565b6001600160a01b0381166122c85760405162461bcd60e51b815260040161092890614025565b603680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f13f4413d8d93a259bd6c10f35095371f30ed50f81a73407e52e9f02000d5d16b90600090a35050565b6123248282610ec4565b610884576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561235a3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156123f757507f000000000000000000000000000000000000000000000000000000000000000046145b1561242157507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6124cf8282610ec4565b15610884576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008060008060008061253c88613448565b935093509350935061254f898589613924565b6000841161256f5760405162461bcd60e51b815260040161092890613fb4565b603854600160801b90046001600160801b03168411156125ea5760405162461bcd60e51b815260206004820152603060248201527f494e53554646494349454e545f415641494c41424c455f45584f47454e4f555360448201526f5f41535345545f4c495155494449545960801b6064820152608401610928565b83603860108282829054906101000a90046001600160801b031661260e9190613f45565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061263b81613074565b603980546000906126569084906001600160801b0316614081565b82546001600160801b039182166101009390930a9283029190920219909116179055506040516323b872dd60e01b81526001600160a01b038a81166004830152306024830152604482018590527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156126ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127129190613fdc565b50603a54604051639bea62ad60e01b8152600481018490526001600160a01b0390911690639bea62ad90602401600060405180830381600087803b15801561275957600080fd5b505af115801561276d573d6000803e3d6000fd5b506127a79250506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016905088866129b4565b60408051858152602081018590529081018290526001600160a01b0380891691908b16907f35b18eb91d0f8ce2968fdf81c1ed9ac429776c7260cdb8bf35c314564e714f66906060015b60405180910390a3509197909650945050505050565b603880546001600160801b038381166001600160801b031983168117909355604080519190921680825260208201939093527fe0f222fd3dc07d1f2556e7d34819cc5fe0ab68fedb472dc2de611aa3398409ce91015b60405180910390a15050565b603a5460405163c701e30560e01b81523060048201526000916001600160a01b03169063c701e305906024015b602060405180830381865afa1580156128b3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080c919061400c565b6038546040516329ede30f60e21b8152600160801b9091046001600160801b0316600482015260006024820181905290819081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a7b78c3c90604401602060405180830381865afa15801561295c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612980919061400c565b905083811061299e576129938482613ff9565b946000945092505050565b60006129aa8286613ff9565b9250925050915091565b60405163a9059cbb60e01b8082526001600160a01b0384166004830152602482018390529060008060448382895af16129f1573d6000803e3d6000fd5b506129fb8461392c565b612a3f5760405162461bcd60e51b815260206004820152601560248201527423a83b191d103330b4b632b2103a3930b739b332b960591b6044820152606401610928565b50505050565b6001600160a01b038116612a6b5760405162461bcd60e51b815260040161092890614025565b603a80546001600160a01b038381166001600160a01b031983161790925560405163095ea7b360e01b81529082166004820181905260006024830152917f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015612af3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b179190613fdc565b5060405163095ea7b360e01b81526001600160a01b03838116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015612b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bac9190613fdc565b50604080516001600160a01b038084168252841660208201527f2c08a25f68366783e094daa7889fc9e62fd3baeebb3cc5e7ff37a53d52336ac8910161285d565b60006107df612bfa61239e565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612c4a85856139d2565b90925090506000816004811115612c6357612c636140a1565b148015612c815750856001600160a01b0316826001600160a01b0316145b15612c9157600192505050612d78565b600080876001600160a01b0316631626ba7e60e01b8888604051602401612cb9929190614107565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612cf79190614128565b600060405180830381855afa9150503d8060008114612d32576040519150601f19603f3d011682016040523d82523d6000602084013e612d37565b606091505b5091509150818015612d4a575080516020145b8015612d7157508051630b135d3f60e11b90612d6f908301602090810190840161400c565b145b9450505050505b9392505050565b600080600080600080612d9188613183565b935093509350935060008411612db95760405162461bcd60e51b815260040161092890613fb4565b6038546001600160801b0380821691612ddb918791600160801b90041661406e565b1115612e335760405162461bcd60e51b815260206004820152602160248201527f45584f47454e4f55535f41535345545f4558504f535552455f544f4f5f4849476044820152600960fb1b6064820152608401610928565b83603860108282829054906101000a90046001600160801b0316612e579190614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612e8481613074565b60398054600090612e9f9084906001600160801b0316614081565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612f038930867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166130e1909392919063ffffffff16565b603a546040516355ada22b60e11b8152600481018490526001600160a01b039091169063ab5b445690602401600060405180830381600087803b158015612f4957600080fd5b505af1158015612f5d573d6000803e3d6000fd5b505060405163a9059cbb60e01b81526001600160a01b038a81166004830152602482018790527f000000000000000000000000000000000000000000000000000000000000000016925063a9059cbb91506044016020604051808303816000875af1158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff49190613fdc565b5060408051858152602081018490529081018290526001600160a01b0380891691908b16907fefd9053c6d75eeb7635ae405072e58d5d1588e1ee0db5d212e6afcb529b975e3906060016127f1565b603a54604051630e71473960e11b81523060048201526000916001600160a01b031690631ce28e7290602401612896565b60006001600160801b038211156130dd5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610928565b5090565b6040516323b872dd60e01b8082526001600160a01b038581166004840152841660248301526044820183905290600080606483828a5af1613126573d6000803e3d6000fd5b506131308561392c565b61317c5760405162461bcd60e51b815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d000000000000006044820152606401610928565b5050505050565b6037546040516329ede30f60e21b815260048101839052600060248201819052918291829182916001600160a01b0391821615159183917f00000000000000000000000000000000000000000000000000000000000000009091169063a7b78c3c90604401602060405180830381865afa158015613205573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613229919061400c565b90506000826132395760006132a6565b60375460405163959d6d2960e01b8152600481018490526001600160a01b039091169063959d6d2990602401602060405180830381865afa158015613282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132a6919061400c565b905060006132b48284613ff9565b90506000846132c35781613330565b6037546040516318fdd06b60e01b8152600481018490526001600160a01b03909116906318fdd06b90602401602060405180830381865afa15801561330c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613330919061400c565b604051635ded74a560e01b815260048101829052600160248201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ded74a590604401602060405180830381865afa1580156133a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c6919061400c565b905060006133d48484613ff9565b9050816133e18285613ff9565b909d909c50929a509850909650505050505050565b603780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8a53d8a38ee2969ab6c2a4793fc6d15aac23906030c4943495dd2e843b48f9d690600090a35050565b6037546040516329ede30f60e21b815260048101839052600160248201526000918291829182916001600160a01b0391821615159183917f00000000000000000000000000000000000000000000000000000000000000009091169063a7b78c3c90604401602060405180830381865afa1580156134ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ee919061400c565b90506000826134fe57600061356b565b6037546040516345d6494d60e01b8152600481018490526001600160a01b03909116906345d6494d90602401602060405180830381865afa158015613547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061356b919061400c565b90506000613579828461406e565b905060008461358857816135f5565b6037546040516352510fd160e11b8152600481018490526001600160a01b039091169063a4a21fa290602401602060405180830381865afa1580156135d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f5919061400c565b604051635ded74a560e01b8152600481018290526000602482018190529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ded74a590604401602060405180830381865afa158015613666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368a919061400c565b905060006136988385613ff9565b9050816133e1828561406e565b6000806136b0613a14565b9150915060008183116136c45760006136ce565b6136ce8284613ff9565b905060006136db836128d7565b5090506000811180156136ee5750600082115b15612a3f578181116137005780613702565b815b6039805491925082916000906137229084906001600160801b0316614081565b82546001600160801b039182166101009390930a928302919092021990911617905550603a546040516355ada22b60e11b8152600481018390526001600160a01b039091169063ab5b445690602401600060405180830381600087803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b5050505050505050565b6039546001600160801b0316801561229f57603980546001600160801b031916905560365460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af115801561383f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138639190613fdc565b506036546040518281526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169216907fb29fcda740927812f5a71075b62e132bead3769a455319c29b9a1cc461a654759060200160405180910390a350565b6138d58282610ec4565b610884576138e281613a84565b6138ed836020613a96565b6040516020016138fe929190614144565b60408051601f198184030181529082905262461bcd60e51b8252610928916004016141b9565b6108ad6136a5565b6000613951565b62461bcd60e51b600052602060045280602452508060445260646000fd5b3d801561399057602081146139c15761398b7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f613933565b610bd8565b823b6139b8576139b87311d41d8c8e881b9bdd08184818dbdb9d1c9858dd60621b6014613933565b60019150610bd8565b3d6000803e50506000511515919050565b6000808251604103613a085760208301516040840151606085015160001a6139fc87828585613c32565b945094505050506109a4565b506000905060026109a4565b603a54604051632cdcd8af60e11b815230600482015260009182916001600160a01b03909116906359b9b15e906024016040805180830381865afa158015613a60573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109df91906141cc565b60606107df6001600160a01b03831660145b60606000613aa58360026141f0565b613ab090600261406e565b67ffffffffffffffff811115613ac857613ac8614207565b6040519080825280601f01601f191660200182016040528015613af2576020820181803683370190505b509050600360fc1b81600081518110613b0d57613b0d61421d565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613b3c57613b3c61421d565b60200101906001600160f81b031916908160001a9053506000613b608460026141f0565b613b6b90600161406e565b90505b6001811115613be3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613b9f57613b9f61421d565b1a60f81b828281518110613bb557613bb561421d565b60200101906001600160f81b031916908160001a90535060049490941c93613bdc81614233565b9050613b6e565b508315612d785760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610928565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613c695750600090506003613ced565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613cbd573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613ce657600060019250925050613ced565b9150600090505b94509492505050565b600060208284031215613d0857600080fd5b81356001600160e01b031981168114612d7857600080fd5b80356001600160a01b0381168114613d3757600080fd5b919050565b600060208284031215613d4e57600080fd5b612d7882613d20565b600060208284031215613d6957600080fd5b5035919050565b60008060408385031215613d8357600080fd5b82359150613d9360208401613d20565b90509250929050565b80356001600160801b0381168114613d3757600080fd5b600060208284031215613dc557600080fd5b612d7882613d9c565b60008060008060808587031215613de457600080fd5b613ded85613d20565b9350613dfb60208601613d20565b9250613e0960408601613d9c565b9150613e1760608601613d20565b905092959194509250565b60008060008060008060a08789031215613e3b57600080fd5b613e4487613d20565b955060208701359450613e5960408801613d20565b935060608701359250608087013567ffffffffffffffff80821115613e7d57600080fd5b818901915089601f830112613e9157600080fd5b813581811115613ea057600080fd5b8a6020828501011115613eb257600080fd5b6020830194508093505050509295509295509295565b801515811461229f57600080fd5b600060208284031215613ee857600080fd5b8135612d7881613ec8565b600080600060608486031215613f0857600080fd5b613f1184613d20565b9250613f1f60208501613d20565b9150604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115613f6557613f65613f2f565b5092915050565b6020808252600a908201526923a9a6afa32927ad22a760b11b604082015260600190565b6020808252600a908201526911d4d357d4d15256915160b21b604082015260600190565b6020808252600e908201526d1253959053125117d05353d5539560921b604082015260600190565b600060208284031215613fee57600080fd5b8151612d7881613ec8565b818103818111156107df576107df613f2f565b60006020828403121561401e57600080fd5b5051919050565b60208082526016908201527516915493d7d05111149154d4d7d393d517d59053125160521b604082015260600190565b60006001820161406757614067613f2f565b5060010190565b808201808211156107df576107df613f2f565b6001600160801b03818116838216019080821115613f6557613f65613f2f565b634e487b7160e01b600052602160045260246000fd5b60005b838110156140d25781810151838201526020016140ba565b50506000910152565b600081518084526140f38160208601602086016140b7565b601f01601f19169290920160200192915050565b82815260406020820152600061412060408301846140db565b949350505050565b6000825161413a8184602087016140b7565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161417c8160178501602088016140b7565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516141ad8160288401602088016140b7565b01602801949350505050565b602081526000612d7860208301846140db565b600080604083850312156141df57600080fd5b505080516020909101519092909150565b80820281158282048414176107df576107df613f2f565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008161424257614242613f2f565b50600019019056fe3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0a164736f6c6343000816000a00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f","name":"Gsm4626","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"lib/aave-v3-origin/src/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity ^0.8.10;\n\nimport {IERC20} from '../../openzeppelin/contracts/IERC20.sol';\n\n/// @title Gnosis Protocol v2 Safe ERC20 Transfer Library\n/// @author Gnosis Developers\n/// @dev Gas-efficient version of Openzeppelin's SafeERC20 contract.\nlibrary GPv2SafeERC20 {\n  /// @dev Wrapper around a call to the ERC20 function `transfer` that reverts\n  /// also when the token returns `false`.\n  function safeTransfer(IERC20 token, address to, uint256 value) internal {\n    bytes4 selector_ = token.transfer.selector;\n\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      let freeMemoryPointer := mload(0x40)\n      mstore(freeMemoryPointer, selector_)\n      mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n      mstore(add(freeMemoryPointer, 36), value)\n\n      if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {\n        returndatacopy(0, 0, returndatasize())\n        revert(0, returndatasize())\n      }\n    }\n\n    require(getLastTransferResult(token), 'GPv2: failed transfer');\n  }\n\n  /// @dev Wrapper around a call to the ERC20 function `transferFrom` that\n  /// reverts also when the token returns `false`.\n  function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n    bytes4 selector_ = token.transferFrom.selector;\n\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      let freeMemoryPointer := mload(0x40)\n      mstore(freeMemoryPointer, selector_)\n      mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))\n      mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n      mstore(add(freeMemoryPointer, 68), value)\n\n      if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {\n        returndatacopy(0, 0, returndatasize())\n        revert(0, returndatasize())\n      }\n    }\n\n    require(getLastTransferResult(token), 'GPv2: failed transferFrom');\n  }\n\n  /// @dev Verifies that the last return was a successful `transfer*` call.\n  /// This is done by checking that the return data is either empty, or\n  /// is a valid ABI encoded boolean.\n  function getLastTransferResult(IERC20 token) private view returns (bool success) {\n    // NOTE: Inspecting previous return data requires assembly. Note that\n    // we write the return data to memory 0 in the case where the return\n    // data size is 32, this is OK since the first 64 bytes of memory are\n    // reserved by Solidy as a scratch space that can be used within\n    // assembly blocks.\n    // <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      /// @dev Revert with an ABI encoded Solidity error with a message\n      /// that fits into 32-bytes.\n      ///\n      /// An ABI encoded Solidity error has the following memory layout:\n      ///\n      /// ------------+----------------------------------\n      ///  byte range | value\n      /// ------------+----------------------------------\n      ///  0x00..0x04 |        selector(\"Error(string)\")\n      ///  0x04..0x24 |      string offset (always 0x20)\n      ///  0x24..0x44 |                    string length\n      ///  0x44..0x64 | string value, padded to 32-bytes\n      function revertWithMessage(length, message) {\n        mstore(0x00, '\\x08\\xc3\\x79\\xa0')\n        mstore(0x04, 0x20)\n        mstore(0x24, length)\n        mstore(0x44, message)\n        revert(0x00, 0x64)\n      }\n\n      switch returndatasize()\n      // Non-standard ERC20 transfer without return.\n      case 0 {\n        // NOTE: When the return data size is 0, verify that there\n        // is code at the address. This is done in order to maintain\n        // compatibility with Solidity calling conventions.\n        // <https://docs.soliditylang.org/en/v0.7.6/control-structures.html#external-function-calls>\n        if iszero(extcodesize(token)) {\n          revertWithMessage(20, 'GPv2: not a contract')\n        }\n\n        success := 1\n      }\n      // Standard ERC20 transfer returning boolean success value.\n      case 32 {\n        returndatacopy(0, 0, returndatasize())\n\n        // NOTE: For ABI encoding v1, any non-zero value is accepted\n        // as `true` for a boolean. In order to stay compatible with\n        // OpenZeppelin's `SafeERC20` library which is known to work\n        // with the existing ERC20 implementation we care about,\n        // make sure we return success for any non-zero return value\n        // from the `transfer*` call.\n        success := iszero(iszero(mload(0)))\n      }\n      default {\n        revertWithMessage(31, 'GPv2: malformed transfer result')\n      }\n    }\n  }\n}\n"},{"file_path":"lib/aave-v3-origin/src/contracts/dependencies/openzeppelin/contracts/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\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 Returns the amount of tokens in existence.\n   */\n  function totalSupply() external view returns (uint256);\n\n  /**\n   * @dev Returns the amount of tokens owned by `account`.\n   */\n  function balanceOf(address account) external view returns (uint256);\n\n  /**\n   * @dev Moves `amount` tokens from the caller's account to `recipient`.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transfer(address recipient, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Returns the remaining number of tokens that `spender` will be\n   * allowed to spend on behalf of `owner` through {transferFrom}. This is\n   * zero by default.\n   *\n   * This value changes when {approve} or {transferFrom} are called.\n   */\n  function allowance(address owner, address spender) external view returns (uint256);\n\n  /**\n   * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * IMPORTANT: Beware that changing an allowance with this method brings the risk\n   * that someone may use both the old and the new allowance by unfortunate\n   * transaction ordering. One possible solution to mitigate this race\n   * condition is to first reduce the spender's allowance to 0 and set the\n   * desired value afterwards:\n   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n   *\n   * Emits an {Approval} event.\n   */\n  function approve(address spender, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Moves `amount` tokens from `sender` to `recipient` using the\n   * allowance mechanism. `amount` is then deducted from the caller's\n   * allowance.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Emitted when `value` tokens are moved from one account (`from`) to\n   * another (`to`).\n   *\n   * Note that `value` may be zero.\n   */\n  event Transfer(address indexed from, address indexed to, uint256 value);\n\n  /**\n   * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n   * a call to {approve}. `value` is the new allowance.\n   */\n  event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},{"file_path":"lib/aave-v3-origin/src/contracts/misc/aave-upgradeability/VersionedInitializable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\n/**\n * @title VersionedInitializable\n * @author Aave, inspired by the OpenZeppelin Initializable contract\n * @notice Helper contract to implement initializer functions. To use it, replace\n * the constructor with a function that has the `initializer` modifier.\n * @dev WARNING: Unlike constructors, initializer functions must be manually\n * invoked. This applies both to deploying an Initializable contract, as well\n * as extending an Initializable contract via inheritance.\n * WARNING: When used with inheritance, manual care must be taken to not invoke\n * a parent initializer twice, or ensure that all initializers are idempotent,\n * because this is not dealt with automatically as with constructors.\n */\nabstract contract VersionedInitializable {\n  /**\n   * @dev Indicates that the contract has been initialized.\n   */\n  uint256 private lastInitializedRevision = 0;\n\n  /**\n   * @dev Indicates that the contract is in the process of being initialized.\n   */\n  bool private initializing;\n\n  /**\n   * @dev Modifier to use in the initializer function of a contract.\n   */\n  modifier initializer() {\n    uint256 revision = getRevision();\n    require(\n      initializing || isConstructor() || revision > lastInitializedRevision,\n      'Contract instance has already been initialized'\n    );\n\n    bool isTopLevelCall = !initializing;\n    if (isTopLevelCall) {\n      initializing = true;\n      lastInitializedRevision = revision;\n    }\n\n    _;\n\n    if (isTopLevelCall) {\n      initializing = false;\n    }\n  }\n\n  /**\n   * @notice Returns the revision number of the contract\n   * @dev Needs to be defined in the inherited class as a constant.\n   * @return The revision number\n   */\n  function getRevision() internal pure virtual returns (uint256);\n\n  /**\n   * @notice Returns true if and only if the function is running in the constructor\n   * @return True if the function is running in the constructor\n   */\n  function isConstructor() private view returns (bool) {\n    // extcodesize checks the size of the code stored in an address, and\n    // address returns the current address. Since the code is still not\n    // deployed when running a constructor, any checks on its code size will\n    // yield zero, making it an effective way to detect if a contract is\n    // under construction or not.\n    uint256 cs;\n    //solium-disable-next-line\n    assembly {\n      cs := extcodesize(address())\n    }\n    return cs == 0;\n  }\n\n  // Reserved storage space to allow for layout changes in the future.\n  uint256[50] private ______gap;\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\n     *\n     * Format of the revert message is described in {_checkRole}.\n     *\n     * _Available since v4.6._\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(account),\n                        \" is missing role \",\n                        Strings.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * May emit a {RoleGranted} event.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     *\n     * NOTE: This function is deprecated in favor of {_grantRole}.\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/interfaces/IERC1271.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n    /**\n     * @dev Should return whether the signature provided is valid for the provided data\n     * @param hash      Hash of the data to be signed\n     * @param signature Signature byte array associated with _data\n     */\n    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"// 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"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, \"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        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or 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            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\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            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n    /* solhint-disable var-name-mixedcase */\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n    // invalidate the cached domain separator if the chain id changes.\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n    uint256 private immutable _CACHED_CHAIN_ID;\n    address private immutable _CACHED_THIS;\n\n    bytes32 private immutable _HASHED_NAME;\n    bytes32 private immutable _HASHED_VERSION;\n    bytes32 private immutable _TYPE_HASH;\n\n    /* solhint-enable var-name-mixedcase */\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    constructor(string memory name, string memory version) {\n        bytes32 hashedName = keccak256(bytes(name));\n        bytes32 hashedVersion = keccak256(bytes(version));\n        bytes32 typeHash = keccak256(\n            \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n        );\n        _HASHED_NAME = hashedName;\n        _HASHED_VERSION = hashedVersion;\n        _CACHED_CHAIN_ID = block.chainid;\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n        _CACHED_THIS = address(this);\n        _TYPE_HASH = typeHash;\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n            return _CACHED_DOMAIN_SEPARATOR;\n        } else {\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n        }\n    }\n\n    function _buildDomainSeparator(\n        bytes32 typeHash,\n        bytes32 nameHash,\n        bytes32 versionHash\n    ) private view returns (bytes32) {\n        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../Address.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n    /**\n     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n     *\n     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n     * change through time. It could return true at block N and false at block N+1 (or the opposite).\n     */\n    function isValidSignatureNow(\n        address signer,\n        bytes32 hash,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n        if (error == ECDSA.RecoverError.NoError && recovered == signer) {\n            return true;\n        }\n\n        (bool success, bytes memory result) = signer.staticcall(\n            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n        );\n        return (success &&\n            result.length == 32 &&\n            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10**64) {\n                value /= 10**64;\n                result += 64;\n            }\n            if (value >= 10**32) {\n                value /= 10**32;\n                result += 32;\n            }\n            if (value >= 10**16) {\n                value /= 10**16;\n                result += 16;\n            }\n            if (value >= 10**8) {\n                value /= 10**8;\n                result += 8;\n            }\n            if (value >= 10**4) {\n                value /= 10**4;\n                result += 4;\n            }\n            if (value >= 10**2) {\n                value /= 10**2;\n                result += 2;\n            }\n            if (value >= 10**1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n        }\n    }\n}\n"},{"file_path":"src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"},{"file_path":"src/contracts/facilitators/gsm/Gsm.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {VersionedInitializable} from 'aave-v3-origin/contracts/misc/aave-upgradeability/VersionedInitializable.sol';\nimport {IERC20} from 'aave-v3-origin/contracts/dependencies/openzeppelin/contracts/IERC20.sol';\nimport {GPv2SafeERC20} from 'aave-v3-origin/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol';\nimport {EIP712} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol';\nimport {SignatureChecker} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol';\nimport {SafeCast} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/utils/math/SafeCast.sol';\nimport {AccessControl} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/access/AccessControl.sol';\nimport {IGhoFacilitator} from 'src/contracts/gho/interfaces/IGhoFacilitator.sol';\nimport {IGhoToken} from 'src/contracts/gho/interfaces/IGhoToken.sol';\nimport {IGsmPriceStrategy} from 'src/contracts/facilitators/gsm/priceStrategy/interfaces/IGsmPriceStrategy.sol';\nimport {IGsmFeeStrategy} from 'src/contracts/facilitators/gsm/feeStrategy/interfaces/IGsmFeeStrategy.sol';\nimport {IGhoReserve} from 'src/contracts/facilitators/gsm/interfaces/IGhoReserve.sol';\nimport {IGsm} from 'src/contracts/facilitators/gsm/interfaces/IGsm.sol';\n\n/**\n * @title Gsm\n * @author Aave\n * @notice GHO Stability Module. It provides buy/sell facilities to go to/from an underlying asset to/from GHO.\n * @dev To be covered by a proxy contract.\n */\ncontract Gsm is AccessControl, VersionedInitializable, EIP712, IGsm {\n  using GPv2SafeERC20 for IERC20;\n  using SafeCast for uint256;\n\n  /// @inheritdoc IGsm\n  bytes32 public constant CONFIGURATOR_ROLE = keccak256('CONFIGURATOR_ROLE');\n\n  /// @inheritdoc IGsm\n  bytes32 public constant TOKEN_RESCUER_ROLE = keccak256('TOKEN_RESCUER_ROLE');\n\n  /// @inheritdoc IGsm\n  bytes32 public constant SWAP_FREEZER_ROLE = keccak256('SWAP_FREEZER_ROLE');\n\n  /// @inheritdoc IGsm\n  bytes32 public constant LIQUIDATOR_ROLE = keccak256('LIQUIDATOR_ROLE');\n\n  /// @inheritdoc IGsm\n  bytes32 public constant BUY_ASSET_WITH_SIG_TYPEHASH =\n    keccak256(\n      'BuyAssetWithSig(address originator,uint256 minAmount,address receiver,uint256 nonce,uint256 deadline)'\n    );\n\n  /// @inheritdoc IGsm\n  bytes32 public constant SELL_ASSET_WITH_SIG_TYPEHASH =\n    keccak256(\n      'SellAssetWithSig(address originator,uint256 maxAmount,address receiver,uint256 nonce,uint256 deadline)'\n    );\n\n  /// @inheritdoc IGsm\n  address public immutable GHO_TOKEN;\n\n  /// @inheritdoc IGsm\n  address public immutable UNDERLYING_ASSET;\n\n  /// @inheritdoc IGsm\n  address public immutable PRICE_STRATEGY;\n\n  /// @inheritdoc IGsm\n  mapping(address => uint256) public nonces;\n\n  address internal _ghoTreasury;\n  address internal _feeStrategy;\n  bool internal _isFrozen;\n  bool internal _isSeized;\n  uint128 internal _exposureCap;\n  uint128 internal _currentExposure;\n  uint128 internal _accruedFees;\n  address internal _ghoReserve;\n\n  /**\n   * @dev Require GSM to not be frozen for functions marked by this modifier\n   */\n  modifier notFrozen() {\n    require(!_isFrozen, 'GSM_FROZEN');\n    _;\n  }\n\n  /**\n   * @dev Require GSM to not be seized for functions marked by this modifier\n   */\n  modifier notSeized() {\n    require(!_isSeized, 'GSM_SEIZED');\n    _;\n  }\n\n  /**\n   * @dev Constructor\n   * @param ghoToken The address of the GHO token contract\n   * @param underlyingAsset The address of the collateral asset\n   * @param priceStrategy The address of the price strategy\n   */\n  constructor(address ghoToken, address underlyingAsset, address priceStrategy) EIP712('GSM', '1') {\n    require(ghoToken != address(0), 'ZERO_ADDRESS_NOT_VALID');\n    require(underlyingAsset != address(0), 'ZERO_ADDRESS_NOT_VALID');\n    require(\n      IGsmPriceStrategy(priceStrategy).UNDERLYING_ASSET() == underlyingAsset,\n      'INVALID_PRICE_STRATEGY'\n    );\n    GHO_TOKEN = ghoToken;\n    UNDERLYING_ASSET = underlyingAsset;\n    PRICE_STRATEGY = priceStrategy;\n  }\n\n  /**\n   * @notice GSM initializer\n   * @param admin The address of the default admin role\n   * @param ghoTreasury The address of the GHO treasury\n   * @param exposureCap Maximum amount of user-supplied underlying asset in GSM\n   * @param ghoReserve The address of the GHO reserve to use tokens from\n   */\n  function initialize(\n    address admin,\n    address ghoTreasury,\n    uint128 exposureCap,\n    address ghoReserve\n  ) external initializer {\n    require(admin != address(0), 'ZERO_ADDRESS_NOT_VALID');\n    _grantRole(DEFAULT_ADMIN_ROLE, admin);\n    _grantRole(CONFIGURATOR_ROLE, admin);\n    _updateGhoTreasury(ghoTreasury);\n    _updateExposureCap(exposureCap);\n    _updateGhoReserve(ghoReserve);\n  }\n\n  /// @inheritdoc IGsm\n  function buyAsset(\n    uint256 minAmount,\n    address receiver\n  ) external notFrozen notSeized returns (uint256, uint256) {\n    return _buyAsset(msg.sender, minAmount, receiver);\n  }\n\n  /// @inheritdoc IGsm\n  function buyAssetWithSig(\n    address originator,\n    uint256 minAmount,\n    address receiver,\n    uint256 deadline,\n    bytes calldata signature\n  ) external notFrozen notSeized returns (uint256, uint256) {\n    require(deadline >= block.timestamp, 'SIGNATURE_DEADLINE_EXPIRED');\n    bytes32 digest = _hashTypedDataV4(\n      keccak256(\n        abi.encode(\n          BUY_ASSET_WITH_SIG_TYPEHASH,\n          originator,\n          minAmount,\n          receiver,\n          nonces[originator]++,\n          deadline\n        )\n      )\n    );\n    require(\n      SignatureChecker.isValidSignatureNow(originator, digest, signature),\n      'SIGNATURE_INVALID'\n    );\n\n    return _buyAsset(originator, minAmount, receiver);\n  }\n\n  /// @inheritdoc IGsm\n  function sellAsset(\n    uint256 maxAmount,\n    address receiver\n  ) external notFrozen notSeized returns (uint256, uint256) {\n    return _sellAsset(msg.sender, maxAmount, receiver);\n  }\n\n  /// @inheritdoc IGsm\n  function sellAssetWithSig(\n    address originator,\n    uint256 maxAmount,\n    address receiver,\n    uint256 deadline,\n    bytes calldata signature\n  ) external notFrozen notSeized returns (uint256, uint256) {\n    require(deadline >= block.timestamp, 'SIGNATURE_DEADLINE_EXPIRED');\n    bytes32 digest = _hashTypedDataV4(\n      keccak256(\n        abi.encode(\n          SELL_ASSET_WITH_SIG_TYPEHASH,\n          originator,\n          maxAmount,\n          receiver,\n          nonces[originator]++,\n          deadline\n        )\n      )\n    );\n    require(\n      SignatureChecker.isValidSignatureNow(originator, digest, signature),\n      'SIGNATURE_INVALID'\n    );\n\n    return _sellAsset(originator, maxAmount, receiver);\n  }\n\n  /// @inheritdoc IGsm\n  function rescueTokens(\n    address token,\n    address to,\n    uint256 amount\n  ) external onlyRole(TOKEN_RESCUER_ROLE) {\n    require(amount > 0, 'INVALID_AMOUNT');\n    if (token == GHO_TOKEN) {\n      uint256 rescuableBalance = IERC20(token).balanceOf(address(this)) - _accruedFees;\n      require(rescuableBalance >= amount, 'INSUFFICIENT_GHO_TO_RESCUE');\n    }\n    if (token == UNDERLYING_ASSET) {\n      uint256 rescuableBalance = IERC20(token).balanceOf(address(this)) - _currentExposure;\n      require(rescuableBalance >= amount, 'INSUFFICIENT_EXOGENOUS_ASSET_TO_RESCUE');\n    }\n    IERC20(token).safeTransfer(to, amount);\n    emit TokensRescued(token, to, amount);\n  }\n\n  /// @inheritdoc IGsm\n  function setSwapFreeze(bool enable) external onlyRole(SWAP_FREEZER_ROLE) {\n    if (enable) {\n      require(!_isFrozen, 'GSM_ALREADY_FROZEN');\n    } else {\n      require(_isFrozen, 'GSM_ALREADY_UNFROZEN');\n    }\n    _isFrozen = enable;\n    emit SwapFreeze(msg.sender, enable);\n  }\n\n  /// @inheritdoc IGsm\n  function seize() external notSeized onlyRole(LIQUIDATOR_ROLE) returns (uint256) {\n    _isSeized = true;\n    _currentExposure = 0;\n    _updateExposureCap(0);\n\n    uint256 underlyingBalance = IERC20(UNDERLYING_ASSET).balanceOf(address(this));\n    if (underlyingBalance > 0) {\n      IERC20(UNDERLYING_ASSET).safeTransfer(_ghoTreasury, underlyingBalance);\n    }\n\n    emit Seized(msg.sender, _ghoTreasury, underlyingBalance, _getUsed());\n    return underlyingBalance;\n  }\n\n  /// @inheritdoc IGsm\n  function burnAfterSeize(uint256 amount) external onlyRole(LIQUIDATOR_ROLE) returns (uint256) {\n    require(_isSeized, 'GSM_NOT_SEIZED');\n    require(amount > 0, 'INVALID_AMOUNT');\n\n    uint256 usedGho = _getUsed();\n    if (amount > usedGho) {\n      amount = usedGho;\n    }\n\n    IGhoToken(GHO_TOKEN).transferFrom(msg.sender, address(this), amount);\n    IGhoReserve(_ghoReserve).restore(amount);\n\n    emit BurnAfterSeize(msg.sender, amount, (usedGho - amount));\n    return amount;\n  }\n\n  /// @inheritdoc IGsm\n  function updateFeeStrategy(address feeStrategy) external onlyRole(CONFIGURATOR_ROLE) {\n    _updateFeeStrategy(feeStrategy);\n  }\n\n  /// @inheritdoc IGsm\n  function updateExposureCap(uint128 exposureCap) external onlyRole(CONFIGURATOR_ROLE) {\n    _updateExposureCap(exposureCap);\n  }\n\n  /// @inheritdoc IGsm\n  function updateGhoReserve(address newGhoReserve) external onlyRole(CONFIGURATOR_ROLE) {\n    _updateGhoReserve(newGhoReserve);\n  }\n\n  /// @inheritdoc IGhoFacilitator\n  function distributeFeesToTreasury() public virtual override {\n    uint256 accruedFees = _accruedFees;\n    if (accruedFees > 0) {\n      _accruedFees = 0;\n      IERC20(GHO_TOKEN).transfer(_ghoTreasury, accruedFees);\n      emit FeesDistributedToTreasury(_ghoTreasury, GHO_TOKEN, accruedFees);\n    }\n  }\n\n  /// @inheritdoc IGhoFacilitator\n  function updateGhoTreasury(address newGhoTreasury) external override onlyRole(CONFIGURATOR_ROLE) {\n    _updateGhoTreasury(newGhoTreasury);\n  }\n\n  /// @inheritdoc IGsm\n  function DOMAIN_SEPARATOR() external view returns (bytes32) {\n    return _domainSeparatorV4();\n  }\n\n  /// @inheritdoc IGsm\n  function getGhoAmountForBuyAsset(\n    uint256 minAssetAmount\n  ) external view returns (uint256, uint256, uint256, uint256) {\n    return _calculateGhoAmountForBuyAsset(minAssetAmount);\n  }\n\n  /// @inheritdoc IGsm\n  function getGhoAmountForSellAsset(\n    uint256 maxAssetAmount\n  ) external view returns (uint256, uint256, uint256, uint256) {\n    return _calculateGhoAmountForSellAsset(maxAssetAmount);\n  }\n\n  /// @inheritdoc IGsm\n  function getAssetAmountForBuyAsset(\n    uint256 maxGhoAmount\n  ) external view returns (uint256, uint256, uint256, uint256) {\n    bool withFee = _feeStrategy != address(0);\n    uint256 grossAmount = withFee\n      ? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalBought(maxGhoAmount)\n      : maxGhoAmount;\n    // round down so maxGhoAmount is guaranteed\n    uint256 assetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(grossAmount, false);\n    uint256 finalGrossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(\n      assetAmount,\n      true\n    );\n    uint256 finalFee = withFee ? IGsmFeeStrategy(_feeStrategy).getBuyFee(finalGrossAmount) : 0;\n    return (assetAmount, finalGrossAmount + finalFee, finalGrossAmount, finalFee);\n  }\n\n  /// @inheritdoc IGsm\n  function getAssetAmountForSellAsset(\n    uint256 minGhoAmount\n  ) external view returns (uint256, uint256, uint256, uint256) {\n    bool withFee = _feeStrategy != address(0);\n    uint256 grossAmount = withFee\n      ? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalSold(minGhoAmount)\n      : minGhoAmount;\n    // round up so minGhoAmount is guaranteed\n    uint256 assetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(grossAmount, true);\n    uint256 finalGrossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(\n      assetAmount,\n      false\n    );\n    uint256 finalFee = withFee ? IGsmFeeStrategy(_feeStrategy).getSellFee(finalGrossAmount) : 0;\n    return (assetAmount, finalGrossAmount - finalFee, finalGrossAmount, finalFee);\n  }\n\n  /// @inheritdoc IGsm\n  function getAvailableUnderlyingExposure() external view returns (uint256) {\n    return _exposureCap > _currentExposure ? _exposureCap - _currentExposure : 0;\n  }\n\n  /// @inheritdoc IGsm\n  function getExposureCap() external view returns (uint128) {\n    return _exposureCap;\n  }\n\n  /// @inheritdoc IGsm\n  function getAvailableLiquidity() external view returns (uint256) {\n    return _currentExposure;\n  }\n\n  /// @inheritdoc IGsm\n  function getFeeStrategy() external view returns (address) {\n    return _feeStrategy;\n  }\n\n  /// @inheritdoc IGsm\n  function getAccruedFees() external view returns (uint256) {\n    return _accruedFees;\n  }\n\n  /// @inheritdoc IGsm\n  function getIsFrozen() external view returns (bool) {\n    return _isFrozen;\n  }\n\n  /// @inheritdoc IGsm\n  function getIsSeized() external view returns (bool) {\n    return _isSeized;\n  }\n\n  /// @inheritdoc IGsm\n  function getGhoReserve() external view returns (address) {\n    return _ghoReserve;\n  }\n\n  /// @inheritdoc IGsm\n  function getUsed() external view returns (uint256) {\n    return _getUsed();\n  }\n\n  /// @inheritdoc IGsm\n  function getLimit() external view returns (uint256) {\n    return _getLimit();\n  }\n\n  /// @inheritdoc IGsm\n  function canSwap() external view returns (bool) {\n    return !_isFrozen && !_isSeized;\n  }\n\n  /// @inheritdoc IGhoFacilitator\n  function getGhoTreasury() external view override returns (address) {\n    return _ghoTreasury;\n  }\n\n  /// @inheritdoc IGsm\n  function GSM_REVISION() public pure virtual override returns (uint256) {\n    return 1;\n  }\n\n  /**\n   * @dev Buys an underlying asset with GHO\n   * @param originator The originator of the request\n   * @param minAmount The minimum amount of the underlying asset desired for purchase\n   * @param receiver The recipient address of the underlying asset being purchased\n   * @return The amount of underlying asset bought\n   * @return The amount of GHO sold by the user\n   */\n  function _buyAsset(\n    address originator,\n    uint256 minAmount,\n    address receiver\n  ) internal returns (uint256, uint256) {\n    (\n      uint256 assetAmount,\n      uint256 ghoSold,\n      uint256 grossAmount,\n      uint256 fee\n    ) = _calculateGhoAmountForBuyAsset(minAmount);\n\n    _beforeBuyAsset(originator, assetAmount, receiver);\n\n    require(assetAmount > 0, 'INVALID_AMOUNT');\n    require(_currentExposure >= assetAmount, 'INSUFFICIENT_AVAILABLE_EXOGENOUS_ASSET_LIQUIDITY');\n\n    _currentExposure -= uint128(assetAmount);\n    _accruedFees += fee.toUint128();\n\n    IGhoToken(GHO_TOKEN).transferFrom(originator, address(this), ghoSold);\n    IGhoReserve(_ghoReserve).restore(grossAmount);\n    IERC20(UNDERLYING_ASSET).safeTransfer(receiver, assetAmount);\n\n    emit BuyAsset(originator, receiver, assetAmount, ghoSold, fee);\n    return (assetAmount, ghoSold);\n  }\n\n  /**\n   * @dev Hook that is called before `buyAsset`.\n   * @dev This can be used to add custom logic\n   * @param originator Originator of the request\n   * @param amount The amount of the underlying asset desired for purchase\n   * @param receiver Recipient address of the underlying asset being purchased\n   */\n  function _beforeBuyAsset(address originator, uint256 amount, address receiver) internal virtual {}\n\n  /**\n   * @dev Sells an underlying asset for GHO\n   * @param originator The originator of the request\n   * @param maxAmount The maximum amount of the underlying asset desired to sell\n   * @param receiver The recipient address of the GHO being purchased\n   * @return The amount of underlying asset sold\n   * @return The amount of GHO bought by the user\n   */\n  function _sellAsset(\n    address originator,\n    uint256 maxAmount,\n    address receiver\n  ) internal returns (uint256, uint256) {\n    (\n      uint256 assetAmount,\n      uint256 ghoBought,\n      uint256 grossAmount,\n      uint256 fee\n    ) = _calculateGhoAmountForSellAsset(maxAmount);\n\n    _beforeSellAsset(originator, assetAmount, receiver);\n\n    require(assetAmount > 0, 'INVALID_AMOUNT');\n    require(_currentExposure + assetAmount <= _exposureCap, 'EXOGENOUS_ASSET_EXPOSURE_TOO_HIGH');\n\n    _currentExposure += uint128(assetAmount);\n    _accruedFees += fee.toUint128();\n    IERC20(UNDERLYING_ASSET).safeTransferFrom(originator, address(this), assetAmount);\n\n    IGhoReserve(_ghoReserve).use(grossAmount);\n    IGhoToken(GHO_TOKEN).transfer(receiver, ghoBought);\n\n    emit SellAsset(originator, receiver, assetAmount, grossAmount, fee);\n    return (assetAmount, ghoBought);\n  }\n\n  /**\n   * @dev Hook that is called before `sellAsset`.\n   * @dev This can be used to add custom logic\n   * @param originator Originator of the request\n   * @param amount The amount of the underlying asset desired to sell\n   * @param receiver Recipient address of the GHO being purchased\n   */\n  function _beforeSellAsset(\n    address originator,\n    uint256 amount,\n    address receiver\n  ) internal virtual {}\n\n  /**\n   * @dev Returns the amount of GHO sold in exchange of buying underlying asset\n   * @param assetAmount The amount of underlying asset to buy\n   * @return The exact amount of asset the user purchases\n   * @return The total amount of GHO the user sells (gross amount in GHO plus fee)\n   * @return The gross amount of GHO\n   * @return The fee amount in GHO, applied on top of gross amount of GHO\n   */\n  function _calculateGhoAmountForBuyAsset(\n    uint256 assetAmount\n  ) internal view returns (uint256, uint256, uint256, uint256) {\n    bool withFee = _feeStrategy != address(0);\n    // pick the highest GHO amount possible for given asset amount\n    uint256 grossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(assetAmount, true);\n    uint256 fee = withFee ? IGsmFeeStrategy(_feeStrategy).getBuyFee(grossAmount) : 0;\n    uint256 ghoSold = grossAmount + fee;\n    uint256 finalGrossAmount = withFee\n      ? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalBought(ghoSold)\n      : ghoSold;\n    // pick the lowest asset amount possible for given GHO amount\n    uint256 finalAssetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(\n      finalGrossAmount,\n      false\n    );\n    uint256 finalFee = ghoSold - finalGrossAmount;\n    return (finalAssetAmount, finalGrossAmount + finalFee, finalGrossAmount, finalFee);\n  }\n\n  /**\n   * @dev Returns the amount of GHO bought in exchange of a given amount of underlying asset\n   * @param assetAmount The amount of underlying asset to sell\n   * @return The exact amount of asset the user sells\n   * @return The total amount of GHO the user buys (gross amount in GHO minus fee)\n   * @return The gross amount of GHO\n   * @return The fee amount in GHO, applied to the gross amount of GHO\n   */\n  function _calculateGhoAmountForSellAsset(\n    uint256 assetAmount\n  ) internal view returns (uint256, uint256, uint256, uint256) {\n    bool withFee = _feeStrategy != address(0);\n    // pick the lowest GHO amount possible for given asset amount\n    uint256 grossAmount = IGsmPriceStrategy(PRICE_STRATEGY).getAssetPriceInGho(assetAmount, false);\n    uint256 fee = withFee ? IGsmFeeStrategy(_feeStrategy).getSellFee(grossAmount) : 0;\n    uint256 ghoBought = grossAmount - fee;\n    uint256 finalGrossAmount = withFee\n      ? IGsmFeeStrategy(_feeStrategy).getGrossAmountFromTotalSold(ghoBought)\n      : ghoBought;\n    // pick the highest asset amount possible for given GHO amount\n    uint256 finalAssetAmount = IGsmPriceStrategy(PRICE_STRATEGY).getGhoPriceInAsset(\n      finalGrossAmount,\n      true\n    );\n    uint256 finalFee = finalGrossAmount - ghoBought;\n    return (finalAssetAmount, finalGrossAmount - finalFee, finalGrossAmount, finalFee);\n  }\n\n  /**\n   * @dev Returns the amount of GHO currently used.\n   * @return The amount of GHO used\n   */\n  function _getUsed() internal view returns (uint256) {\n    return IGhoReserve(_ghoReserve).getUsed(address(this));\n  }\n\n  /**\n   * @dev Returns the maximum amount of GHO that can be used.\n   * @return The usage limit of GHO\n   */\n  function _getLimit() internal view returns (uint256) {\n    return IGhoReserve(_ghoReserve).getLimit(address(this));\n  }\n\n  /**\n   * @dev Returns the usage data of a specified entity.\n   * @return The usage limit of GHO\n   * @return The amount of GHO used\n   */\n  function _getUsage() internal view returns (uint256, uint256) {\n    return IGhoReserve(_ghoReserve).getUsage(address(this));\n  }\n\n  /**\n   * @dev Updates Fee Strategy\n   * @param feeStrategy The address of the new Fee Strategy\n   */\n  function _updateFeeStrategy(address feeStrategy) internal {\n    address oldFeeStrategy = _feeStrategy;\n    _feeStrategy = feeStrategy;\n    emit FeeStrategyUpdated(oldFeeStrategy, feeStrategy);\n  }\n\n  /**\n   * @dev Updates Exposure Cap\n   * @param exposureCap The value of the new Exposure Cap\n   */\n  function _updateExposureCap(uint128 exposureCap) internal {\n    uint128 oldExposureCap = _exposureCap;\n    _exposureCap = exposureCap;\n    emit ExposureCapUpdated(oldExposureCap, exposureCap);\n  }\n\n  /**\n   * @dev Updates GHO Treasury Address\n   * @param newGhoTreasury The address of the new GHO Treasury\n   */\n  function _updateGhoTreasury(address newGhoTreasury) internal {\n    require(newGhoTreasury != address(0), 'ZERO_ADDRESS_NOT_VALID');\n    address oldGhoTreasury = _ghoTreasury;\n    _ghoTreasury = newGhoTreasury;\n    emit GhoTreasuryUpdated(oldGhoTreasury, newGhoTreasury);\n  }\n\n  /**\n   * @dev Updates the address of GHO reserve\n   * @param newGhoReserve The address of the GHO reserve for the GSM\n   */\n  function _updateGhoReserve(address newGhoReserve) internal {\n    require(newGhoReserve != address(0), 'ZERO_ADDRESS_NOT_VALID');\n    address oldReserve = _ghoReserve;\n    _ghoReserve = newGhoReserve;\n\n    IGhoToken(GHO_TOKEN).approve(oldReserve, 0);\n    IGhoToken(GHO_TOKEN).approve(newGhoReserve, type(uint256).max);\n\n    emit GhoReserveUpdated(oldReserve, newGhoReserve);\n  }\n\n  /// @inheritdoc VersionedInitializable\n  function getRevision() internal pure virtual override returns (uint256) {\n    return GSM_REVISION();\n  }\n}\n"},{"file_path":"src/contracts/facilitators/gsm/feeStrategy/interfaces/IGsmFeeStrategy.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title IGsmFeeStrategy\n * @author Aave\n * @notice Defines the behaviour of Fee Strategies\n * @dev Functions' logic must be invertible, being possible to calculate the fee amount based on the gross amount, and\n * the other way round.\n * @dev All math operations must round up, favoring the protocol.\n */\ninterface IGsmFeeStrategy {\n  /**\n   * @notice Returns the fee to be applied when buying an underlying asset in exchange for GHO\n   * @param grossAmount The amount of GHO being sold for the underlying asset\n   * @return The fee amount of GHO\n   */\n  function getBuyFee(uint256 grossAmount) external view returns (uint256);\n\n  /**\n   * @notice Returns the fee to be applied when buying GHO in exchange for an underlying asset\n   * @param grossAmount The amount of underlying, converted to GHO, being sold\n   * @return The fee amount of GHO\n   */\n  function getSellFee(uint256 grossAmount) external view returns (uint256);\n\n  /**\n   * @notice Returns the gross amount of GHO being bought based on the total bought amount\n   * @param totalAmount The total amount of GHO being bought (gross amount, GHO bought plus fee)\n   * @return The gross amount of GHO being bought (total amount minus fee)\n   */\n  function getGrossAmountFromTotalBought(uint256 totalAmount) external view returns (uint256);\n\n  /**\n   * @notice Returns the amount of GHO being sold based on the total sold amount\n   * @param totalAmount The total amount of GHO being sold (gross amount, GHO sold minus fee)\n   * @return The gross amount of GHO being sold (total amount plus fee)\n   */\n  function getGrossAmountFromTotalSold(uint256 totalAmount) external view returns (uint256);\n}\n"},{"file_path":"src/contracts/facilitators/gsm/interfaces/IGhoReserve.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title IGhoReserve\n * @author Aave/TokenLogic\n * @notice Defines the behaviour of a GhoReserve\n */\ninterface IGhoReserve {\n  /**\n   * @dev Struct data representing GHO usage.\n   * @param limit The maximum amount of GHO that can be used\n   * @param used The current amount of GHO used\n   */\n  struct GhoUsage {\n    uint128 limit;\n    uint128 used;\n  }\n\n  /**\n   * @dev Emitted when an entity is added to the GhoReserve entities set\n   * @param entity The address of the entity\n   */\n  event EntityAdded(address indexed entity);\n\n  /**\n   * @dev Emitted when an entity is removed from the GhoReserve entities set\n   * @param entity The address of the entity\n   */\n  event EntityRemoved(address indexed entity);\n\n  /**\n   * @dev Emitted when GHO is restored to the reserve by an entity\n   * @param entity The address restoring the GHO tokens\n   * @param amount The amount of token restored\n   */\n  event GhoUsed(address indexed entity, uint256 amount);\n\n  /**\n   * @dev Emitted when GHO is transferred from the reserve to an entity\n   * @param entity The address receiving the GHO tokens\n   * @param amount The amount of token to transfer\n   */\n  event GhoRestored(address indexed entity, uint256 amount);\n\n  /**\n   * @dev Emitted when GHO is transferred from the reserve\n   * @param to The address receiving the GHO tokens\n   * @param amount The amount of token to transfer\n   */\n  event GhoTransferred(address indexed to, uint256 amount);\n\n  /**\n   * @dev Emitted when the GHO limit for a given entity is updated\n   * @param entity The address of the entity\n   * @param limit The new usage limit\n   */\n  event GhoLimitUpdated(address indexed entity, uint256 limit);\n\n  /**\n   * @notice Restores a specified amount of GHO to the reserve.\n   * @dev The entity must grant allowance in advance to enable the reserve to pull the funds.\n   * @dev Only callable by approved reserve entities.\n   * @param amount The amount of GHO to restore.\n   */\n  function restore(uint256 amount) external;\n\n  /**\n   * @notice Uses a specified amount of GHO from the reserve.\n   * @dev Callable only by entities with sufficient usage limit.\n   * @param amount The amount of GHO to use.\n   */\n  function use(uint256 amount) external;\n\n  /**\n   * @notice Transfers a specified amount of GHO from the reserve\n   * @param to The address receiving the GHO tokens\n   * @param amount The amount of GHO to transfer\n   */\n  function transfer(address to, uint256 amount) external;\n\n  /**\n   * @notice Adds an entity to the reserve\n   * @param entity The address of the entity\n   */\n  function addEntity(address entity) external;\n\n  /**\n   * @notice Removes an entity from the reserve\n   * @param entity The address of the entity\n   */\n  function removeEntity(address entity) external;\n\n  /**\n   * @notice Sets a usage limit for a specified entity.\n   * @dev The new usage limit can be set below the amount of GHO currently used\n   * @param entity The address of the entity\n   * @param limit The maximum amount of GHO that can be used\n   */\n  function setLimit(address entity, uint256 limit) external;\n\n  /**\n   * @notice Returns the address of the GHO token\n   * @return The address of GHO token contract\n   */\n  function GHO_TOKEN() external view returns (address);\n\n  /**\n   * @notice Returns the list of all entities currently in the reserve\n   * @return The array of addresses\n   */\n  function getEntities() external view returns (address[] memory);\n\n  /**\n   * @notice Returns the amount of GHO used by a specified entity\n   * @param entity The address of the entity\n   * @return The amount of GHO used\n   */\n  function getUsed(address entity) external view returns (uint256);\n\n  /**\n   * @notice Returns the usage data of a specified entity\n   * @param entity The address of the entity\n   * @return The usage limit\n   * @return The amount of GHO used\n   */\n  function getUsage(address entity) external view returns (uint256, uint256);\n\n  /**\n   * @notice Returns the usage limit of a specified entity\n   * @param entity The address of the entity\n   * @return The usage limit\n   */\n  function getLimit(address entity) external view returns (uint256);\n\n  /**\n   * @notice Returns whether the entity is part of the reserve\n   * @param entity The address of the entity\n   * @return True if the entity is part of the set\n   */\n  function isEntity(address entity) external view returns (bool);\n\n  /**\n   * @notice Returns the number of entities in the reserve\n   * @return The total number of entities\n   */\n  function totalEntities() external view returns (uint256);\n\n  /**\n   * @notice Returns the GhoReserve revision number\n   * @return The revision number\n   */\n  function GHO_REMOTE_RESERVE_REVISION() external pure returns (uint256);\n}\n"},{"file_path":"src/contracts/facilitators/gsm/interfaces/IGsm.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IAccessControl} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/access/IAccessControl.sol';\nimport {IGhoFacilitator} from 'src/contracts/gho/interfaces/IGhoFacilitator.sol';\n\n/**\n * @title IGsm\n * @author Aave\n * @notice Defines the behaviour of a GHO Stability Module\n */\ninterface IGsm is IAccessControl, IGhoFacilitator {\n  /**\n   * @dev Emitted when a user buys an asset (selling GHO) in the GSM\n   * @param originator The address of the buyer originating the request\n   * @param receiver The address of the receiver of the underlying asset\n   * @param underlyingAmount The amount of the underlying asset bought\n   * @param ghoAmount The amount of GHO sold, inclusive of fee\n   * @param fee The fee paid by the buyer, in GHO\n   */\n  event BuyAsset(\n    address indexed originator,\n    address indexed receiver,\n    uint256 underlyingAmount,\n    uint256 ghoAmount,\n    uint256 fee\n  );\n\n  /**\n   * @dev Emitted when the GHO reserve is updated\n   * @param oldReserve The address of the old reserve\n   * @param newReserve The address of the new reserve\n   */\n  event GhoReserveUpdated(address oldReserve, address newReserve);\n\n  /**\n   * @dev Emitted when a user sells an asset (buying GHO) in the GSM\n   * @param originator The address of the seller originating the request\n   * @param receiver The address of the receiver of GHO\n   * @param underlyingAmount The amount of the underlying asset sold\n   * @param ghoAmount The amount of GHO bought, inclusive of fee\n   * @param fee The fee paid by the buyer, in GHO\n   */\n  event SellAsset(\n    address indexed originator,\n    address indexed receiver,\n    uint256 underlyingAmount,\n    uint256 ghoAmount,\n    uint256 fee\n  );\n\n  /**\n   * @dev Emitted when the Swap Freezer freezes buys/sells\n   * @param freezer The address of the Swap Freezer\n   * @param enabled True if swap functions are frozen, False otherwise\n   */\n  event SwapFreeze(address indexed freezer, bool enabled);\n\n  /**\n   * @dev Emitted when a Liquidator seizes GSM funds\n   * @param seizer The address originating the seizure request\n   * @param recipient The address of the recipient of seized funds\n   * @param underlyingAmount The amount of the underlying asset seized\n   * @param ghoOutstanding The amount of remaining GHO that the GSM had minted\n   */\n  event Seized(\n    address indexed seizer,\n    address indexed recipient,\n    uint256 underlyingAmount,\n    uint256 ghoOutstanding\n  );\n\n  /**\n   * @dev Emitted when burning GHO after a seizure of GSM funds\n   * @param burner The address of the burner\n   * @param amount The amount of GHO burned\n   * @param ghoOutstanding The amount of remaining GHO that the GSM had minted\n   */\n  event BurnAfterSeize(address indexed burner, uint256 amount, uint256 ghoOutstanding);\n\n  /**\n   * @dev Emitted when the Fee Strategy is updated\n   * @param oldFeeStrategy The address of the old Fee Strategy\n   * @param newFeeStrategy The address of the new Fee Strategy\n   */\n  event FeeStrategyUpdated(address indexed oldFeeStrategy, address indexed newFeeStrategy);\n\n  /**\n   * @dev Emitted when the GSM underlying asset Exposure Cap is updated\n   * @param oldExposureCap The amount of the old Exposure Cap\n   * @param newExposureCap The amount of the new Exposure Cap\n   */\n  event ExposureCapUpdated(uint256 oldExposureCap, uint256 newExposureCap);\n\n  /**\n   * @dev Emitted when tokens are rescued from the GSM\n   * @param tokenRescued The address of the rescued token\n   * @param recipient The address that received the rescued tokens\n   * @param amountRescued The amount of token rescued\n   */\n  event TokensRescued(\n    address indexed tokenRescued,\n    address indexed recipient,\n    uint256 amountRescued\n  );\n\n  /**\n   * @notice Buys the GSM underlying asset in exchange for selling GHO\n   * @dev Use `getAssetAmountForBuyAsset` function to calculate the amount based on the GHO amount to sell\n   * @param minAmount The minimum amount of the underlying asset to buy\n   * @param receiver Recipient address of the underlying asset being purchased\n   * @return The amount of underlying asset bought\n   * @return The amount of GHO sold by the user\n   */\n  function buyAsset(uint256 minAmount, address receiver) external returns (uint256, uint256);\n\n  /**\n   * @notice Buys the GSM underlying asset in exchange for selling GHO, using an EIP-712 signature\n   * @dev Use `getAssetAmountForBuyAsset` function to calculate the amount based on the GHO amount to sell\n   * @param originator The signer of the request\n   * @param minAmount The minimum amount of the underlying asset to buy\n   * @param receiver Recipient address of the underlying asset being purchased\n   * @param deadline Signature expiration deadline\n   * @param signature Signature data\n   * @return The amount of underlying asset bought\n   * @return The amount of GHO sold by the user\n   */\n  function buyAssetWithSig(\n    address originator,\n    uint256 minAmount,\n    address receiver,\n    uint256 deadline,\n    bytes calldata signature\n  ) external returns (uint256, uint256);\n\n  /**\n   * @notice Sells the GSM underlying asset in exchange for buying GHO\n   * @dev Use `getAssetAmountForSellAsset` function to calculate the amount based on the GHO amount to buy\n   * @param maxAmount The maximum amount of the underlying asset to sell\n   * @param receiver Recipient address of the GHO being purchased\n   * @return The amount of underlying asset sold\n   * @return The amount of GHO bought by the user\n   */\n  function sellAsset(uint256 maxAmount, address receiver) external returns (uint256, uint256);\n\n  /**\n   * @notice Sells the GSM underlying asset in exchange for buying GHO, using an EIP-712 signature\n   * @dev Use `getAssetAmountForSellAsset` function to calculate the amount based on the GHO amount to buy\n   * @param originator The signer of the request\n   * @param maxAmount The maximum amount of the underlying asset to sell\n   * @param receiver Recipient address of the GHO being purchased\n   * @param deadline Signature expiration deadline\n   * @param signature Signature data\n   * @return The amount of underlying asset sold\n   * @return The amount of GHO bought by the user\n   */\n  function sellAssetWithSig(\n    address originator,\n    uint256 maxAmount,\n    address receiver,\n    uint256 deadline,\n    bytes calldata signature\n  ) external returns (uint256, uint256);\n\n  /**\n   * @notice Rescue and transfer tokens locked in this contract\n   * @dev In a Gsm4626 instance, distributeFeesToTreasury() must be called first to ensure the accounting of\n   * accrued fees is up-to-date.\n   * @param token The address of the token\n   * @param to The address of the recipient\n   * @param amount The amount of token to transfer\n   */\n  function rescueTokens(address token, address to, uint256 amount) external;\n\n  /**\n   * @notice Enable or disable the swap freeze\n   * @param enable True to freeze swap functions, false otherwise\n   */\n  function setSwapFreeze(bool enable) external;\n\n  /**\n   * @notice Seizes all of the underlying asset from the GSM, sending to the Treasury\n   * @dev Seizing is a last resort mechanism to provide the Treasury with the entire amount of underlying asset\n   * so it can be used to backstop any potential event impacting the functionality of the Gsm.\n   * @dev Seizing disables the swap feature\n   * @return The amount of underlying asset seized and transferred to Treasury\n   */\n  function seize() external returns (uint256);\n\n  /**\n   * @notice Burns an amount of GHO after seizure reducing the facilitator bucket level effectively\n   * @dev Passing an amount higher than the facilitator bucket level will result in burning all minted GHO\n   * @dev Only callable if the GSM has assets seized, helpful to wind down the facilitator\n   * @param amount The amount of GHO to burn\n   * @return The amount of GHO burned\n   */\n  function burnAfterSeize(uint256 amount) external returns (uint256);\n\n  /**\n   * @notice Updates the address of the Fee Strategy\n   * @param feeStrategy The address of the new FeeStrategy\n   */\n  function updateFeeStrategy(address feeStrategy) external;\n\n  /**\n   * @notice Updates the exposure cap of the underlying asset\n   * @param exposureCap The new value for the exposure cap (in underlying asset terms)\n   */\n  function updateExposureCap(uint128 exposureCap) external;\n\n  /**\n   * @notice Updates the GHO reserve address\n   * @dev It revokes the allowance to the old reserve and grants maximum allowance to the new one.\n   * @param newGhoReserve The new address of the GHO reserve\n   */\n  function updateGhoReserve(address newGhoReserve) external;\n\n  /**\n   * @notice Returns the EIP712 domain separator\n   * @return The EIP712 domain separator\n   */\n  function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n  /**\n   * @notice Returns the total amount of GHO, gross amount and fee result of buying assets\n   * @param minAssetAmount The minimum amount of underlying asset to buy\n   * @return The exact amount of underlying asset to be bought\n   * @return The total amount of GHO the user sells (gross amount in GHO plus fee)\n   * @return The gross amount of GHO\n   * @return The fee amount in GHO, applied on top of gross amount of GHO\n   */\n  function getGhoAmountForBuyAsset(\n    uint256 minAssetAmount\n  ) external view returns (uint256, uint256, uint256, uint256);\n\n  /**\n   * @notice Returns the total amount of GHO, gross amount and fee result of selling assets\n   * @param maxAssetAmount The maximum amount of underlying asset to sell\n   * @return The exact amount of underlying asset to sell\n   * @return The total amount of GHO the user buys (gross amount in GHO minus fee)\n   * @return The gross amount of GHO\n   * @return The fee amount in GHO, applied to the gross amount of GHO\n   */\n  function getGhoAmountForSellAsset(\n    uint256 maxAssetAmount\n  ) external view returns (uint256, uint256, uint256, uint256);\n\n  /**\n   * @notice Returns the amount of underlying asset, gross amount of GHO and fee result of buying assets\n   * @param maxGhoAmount The maximum amount of GHO the user provides for buying underlying asset\n   * @return The amount of underlying asset the user buys\n   * @return The exact amount of GHO the user provides\n   * @return The gross amount of GHO corresponding to the given total amount of GHO\n   * @return The fee amount in GHO, charged for buying assets\n   */\n  function getAssetAmountForBuyAsset(\n    uint256 maxGhoAmount\n  ) external view returns (uint256, uint256, uint256, uint256);\n\n  /**\n   * @notice Returns the amount of underlying asset, gross amount of GHO and fee result of selling assets\n   * @param minGhoAmount The minimum amount of GHO the user must receive for selling underlying asset\n   * @return The amount of underlying asset the user sells\n   * @return The exact amount of GHO the user receives in exchange\n   * @return The gross amount of GHO corresponding to the given total amount of GHO\n   * @return The fee amount in GHO, charged for selling assets\n   */\n  function getAssetAmountForSellAsset(\n    uint256 minGhoAmount\n  ) external view returns (uint256, uint256, uint256, uint256);\n\n  /**\n   * @notice Returns the remaining GSM exposure capacity\n   * @return The amount of underlying asset that can be sold to the GSM\n   */\n  function getAvailableUnderlyingExposure() external view returns (uint256);\n\n  /**\n   * @notice Returns the exposure limit to the underlying asset\n   * @return The maximum amount of underlying asset that can be sold to the GSM\n   */\n  function getExposureCap() external view returns (uint128);\n\n  /**\n   * @notice Returns the actual underlying asset balance immediately available in the GSM\n   * @return The amount of underlying asset that can be bought from the GSM\n   */\n  function getAvailableLiquidity() external view returns (uint256);\n\n  /**\n   * @notice Returns the Fee Strategy for the GSM\n   * @dev It returns 0x0 in case of no fee strategy\n   * @return The address of the FeeStrategy\n   */\n  function getFeeStrategy() external view returns (address);\n\n  /**\n   * @notice Returns the amount of current accrued fees\n   * @dev It does not factor in potential fees that can be accrued upon distribution of fees\n   * @return The amount of accrued fees\n   */\n  function getAccruedFees() external view returns (uint256);\n\n  /**\n   * @notice Returns the freeze status of the GSM\n   * @return True if frozen, false if not\n   */\n  function getIsFrozen() external view returns (bool);\n\n  /**\n   * @notice Returns the current seizure status of the GSM\n   * @return True if the GSM has been seized, false if not\n   */\n  function getIsSeized() external view returns (bool);\n\n  /**\n   * @notice Returns the address of the GHO reserve\n   * @return The address of the GHO reserve\n   */\n  function getGhoReserve() external view returns (address);\n\n  /**\n   * @notice Returns the amount of GHO used by the GSM\n   * @return The amount of GHO used\n   */\n  function getUsed() external view returns (uint256);\n\n  /**\n   * @notice Returns the maximum amount of GHO that can be used\n   * @return The maximum amount of GHO that can be used\n   */\n  function getLimit() external view returns (uint256);\n\n  /**\n   * @notice Returns whether or not swaps via buyAsset/sellAsset are currently possible\n   * @return True if the GSM has swapping enabled, false otherwise\n   */\n  function canSwap() external view returns (bool);\n\n  /**\n   * @notice Returns the GSM revision number\n   * @return The revision number\n   */\n  function GSM_REVISION() external pure returns (uint256);\n\n  /**\n   * @notice Returns the address of the GHO token\n   * @return The address of GHO token contract\n   */\n  function GHO_TOKEN() external view returns (address);\n\n  /**\n   * @notice Returns the underlying asset of the GSM\n   * @return The address of the underlying asset\n   */\n  function UNDERLYING_ASSET() external view returns (address);\n\n  /**\n   * @notice Returns the price strategy of the GSM\n   * @return The address of the price strategy\n   */\n  function PRICE_STRATEGY() external view returns (address);\n\n  /**\n   * @notice Returns the current nonce (for EIP-712 signature methods) of an address\n   * @param user The address of the user\n   * @return The current nonce of the user\n   */\n  function nonces(address user) external view returns (uint256);\n\n  /**\n   * @notice Returns the identifier of the Configurator Role\n   * @return The bytes32 id hash of the Configurator role\n   */\n  function CONFIGURATOR_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Token Rescuer Role\n   * @return The bytes32 id hash of the TokenRescuer role\n   */\n  function TOKEN_RESCUER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Swap Freezer Role\n   * @return The bytes32 id hash of the SwapFreezer role\n   */\n  function SWAP_FREEZER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Liquidator Role\n   * @return The bytes32 id hash of the Liquidator role\n   */\n  function LIQUIDATOR_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the EIP-712 signature typehash for buyAssetWithSig\n   * @return The bytes32 signature typehash for buyAssetWithSig\n   */\n  function BUY_ASSET_WITH_SIG_TYPEHASH() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the EIP-712 signature typehash for sellAssetWithSig\n   * @return The bytes32 signature typehash for sellAssetWithSig\n   */\n  function SELL_ASSET_WITH_SIG_TYPEHASH() external pure returns (bytes32);\n}\n"},{"file_path":"src/contracts/facilitators/gsm/interfaces/IGsm4626.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IGsm} from 'src/contracts/facilitators/gsm/interfaces/IGsm.sol';\n\n/**\n * @title IGsm4626\n * @author Aave\n * @notice Defines the behaviour of a GHO Stability Module with an ERC-4626 underlying asset\n */\ninterface IGsm4626 is IGsm {\n  /**\n   * @dev Emitted when an asset is provided to the GSM to backstop a loss\n   * @param backer The address of the backer\n   * @param asset The address of the provided asset\n   * @param amount The amount of the asset\n   * @param ghoAmount The amount of the asset, in GHO terms\n   * @param remainingLoss The loss balance that remains after the operation\n   */\n  event BackingProvided(\n    address indexed backer,\n    address indexed asset,\n    uint256 amount,\n    uint256 ghoAmount,\n    uint256 remainingLoss\n  );\n\n  /**\n   * @notice Restores backing of GHO by burning GHO\n   * @dev Useful in the event the underlying value declines relative to GHO minted\n   * @dev Passing an amount higher than the current deficit will result in backing the entire deficit\n   * @param amount The amount of GHO to be burned\n   * @return The amount of GHO used for backing\n   */\n  function backWithGho(uint256 amount) external returns (uint256);\n\n  /**\n   * @notice Restores backing of GHO by providing underlying asset\n   * @dev Useful in the event the underlying value declines relative to GHO minted\n   * @dev Passing an amount higher than the current deficit will result in backing the entire deficit\n   * @param amount The amount of underlying to be used for backing\n   * @return The amount of underlying used for backing\n   */\n  function backWithUnderlying(uint256 amount) external returns (uint256);\n\n  /**\n   * @notice Returns the excess or deficit of GHO, reflecting current GSM backing\n   * @return The excess amount of GHO minted, relative to the value of the underlying\n   * @return The deficit of GHO minted, relative to the value of the underlying\n   */\n  function getCurrentBacking() external view returns (uint256, uint256);\n}\n"},{"file_path":"src/contracts/facilitators/gsm/priceStrategy/interfaces/IGsmPriceStrategy.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title IGsmPriceStrategy\n * @author Aave\n * @notice Defines the behaviour of Price Strategies\n */\ninterface IGsmPriceStrategy {\n  /**\n   * @notice Returns the number of decimals of GHO\n   * @return The number of decimals of GHO\n   */\n  function GHO_DECIMALS() external view returns (uint256);\n\n  /**\n   * @notice Returns the address of the underlying asset being priced\n   * @return The address of the underlying asset\n   */\n  function UNDERLYING_ASSET() external view returns (address);\n\n  /**\n   * @notice Returns the decimals of the underlying asset being priced\n   * @return The number of decimals of the underlying asset\n   */\n  function UNDERLYING_ASSET_DECIMALS() external view returns (uint256);\n\n  /**\n   * @notice Returns the price of the underlying asset (GHO denominated)\n   * @param assetAmount The amount of the underlying asset to calculate the price of\n   * @param roundUp True if the price should be rounded up, false if rounded down\n   * @return The price of the underlying asset (expressed in GHO units)\n   */\n  function getAssetPriceInGho(uint256 assetAmount, bool roundUp) external view returns (uint256);\n\n  /**\n   * @notice Returns the price of GHO (denominated in the underlying asset)\n   * @param ghoAmount The amount of GHO to calculate the price of\n   * @param roundUp True if the price should be rounded up, false if rounded down\n   * @return The price of the GHO amount (expressed in underlying asset units)\n   */\n  function getGhoPriceInAsset(uint256 ghoAmount, bool roundUp) external view returns (uint256);\n}\n"},{"file_path":"src/contracts/gho/interfaces/IGhoFacilitator.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title IGhoFacilitator\n * @author Aave\n * @notice Defines the behavior of a Gho Facilitator\n */\ninterface IGhoFacilitator {\n  /**\n   * @dev Emitted when fees are distributed to the GhoTreasury\n   * @param ghoTreasury The address of the ghoTreasury\n   * @param asset The address of the asset transferred to the ghoTreasury\n   * @param amount The amount of the asset transferred to the ghoTreasury\n   */\n  event FeesDistributedToTreasury(\n    address indexed ghoTreasury,\n    address indexed asset,\n    uint256 amount\n  );\n\n  /**\n   * @dev Emitted when Gho Treasury address is updated\n   * @param oldGhoTreasury The address of the old GhoTreasury contract\n   * @param newGhoTreasury The address of the new GhoTreasury contract\n   */\n  event GhoTreasuryUpdated(address indexed oldGhoTreasury, address indexed newGhoTreasury);\n\n  /**\n   * @notice Distribute fees to the GhoTreasury\n   */\n  function distributeFeesToTreasury() external;\n\n  /**\n   * @notice Updates the address of the Gho Treasury\n   * @dev WARNING: The GhoTreasury is where revenue fees are sent to. Update carefully\n   * @param newGhoTreasury The address of the GhoTreasury\n   */\n  function updateGhoTreasury(address newGhoTreasury) external;\n\n  /**\n   * @notice Returns the address of the Gho Treasury\n   * @return The address of the GhoTreasury contract\n   */\n  function getGhoTreasury() external view returns (address);\n}\n"},{"file_path":"src/contracts/gho/interfaces/IGhoToken.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol';\nimport {IAccessControl} from 'src/contracts/dependencies/openzeppelin-contracts/contracts/access/IAccessControl.sol';\n\n/**\n * @title IGhoToken\n * @author Aave\n */\ninterface IGhoToken is IERC20, IAccessControl {\n  struct Facilitator {\n    uint128 bucketCapacity;\n    uint128 bucketLevel;\n    string label;\n  }\n\n  /**\n   * @dev Emitted when a new facilitator is added\n   * @param facilitatorAddress The address of the new facilitator\n   * @param label A hashed human readable identifier for the facilitator\n   * @param bucketCapacity The initial capacity of the facilitator's bucket\n   */\n  event FacilitatorAdded(\n    address indexed facilitatorAddress,\n    bytes32 indexed label,\n    uint256 bucketCapacity\n  );\n\n  /**\n   * @dev Emitted when a facilitator is removed\n   * @param facilitatorAddress The address of the removed facilitator\n   */\n  event FacilitatorRemoved(address indexed facilitatorAddress);\n\n  /**\n   * @dev Emitted when the bucket capacity of a facilitator is updated\n   * @param facilitatorAddress The address of the facilitator whose bucket capacity is being changed\n   * @param oldCapacity The old capacity of the bucket\n   * @param newCapacity The new capacity of the bucket\n   */\n  event FacilitatorBucketCapacityUpdated(\n    address indexed facilitatorAddress,\n    uint256 oldCapacity,\n    uint256 newCapacity\n  );\n\n  /**\n   * @dev Emitted when the bucket level changed\n   * @param facilitatorAddress The address of the facilitator whose bucket level is being changed\n   * @param oldLevel The old level of the bucket\n   * @param newLevel The new level of the bucket\n   */\n  event FacilitatorBucketLevelUpdated(\n    address indexed facilitatorAddress,\n    uint256 oldLevel,\n    uint256 newLevel\n  );\n\n  /**\n   * @notice Returns the identifier of the Facilitator Manager Role\n   * @return The bytes32 id hash of the FacilitatorManager role\n   */\n  function FACILITATOR_MANAGER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Bucket Manager Role\n   * @return The bytes32 id hash of the BucketManager role\n   */\n  function BUCKET_MANAGER_ROLE() external pure returns (bytes32);\n\n  /**\n   * @notice Mints the requested amount of tokens to the account address.\n   * @dev Only facilitators with enough bucket capacity available can mint.\n   * @dev The bucket level is increased upon minting.\n   * @param account The address receiving the GHO tokens\n   * @param amount The amount to mint\n   */\n  function mint(address account, uint256 amount) external;\n\n  /**\n   * @notice Burns the requested amount of tokens from the account address.\n   * @dev Only active facilitators (bucket level > 0) can burn.\n   * @dev The bucket level is decreased upon burning.\n   * @param amount The amount to burn\n   */\n  function burn(uint256 amount) external;\n\n  /**\n   * @notice Add the facilitator passed with the parameters to the facilitators list.\n   * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function\n   * @param facilitatorAddress The address of the facilitator to add\n   * @param facilitatorLabel A human readable identifier for the facilitator\n   * @param bucketCapacity The upward limit of GHO can be minted by the facilitator\n   */\n  function addFacilitator(\n    address facilitatorAddress,\n    string calldata facilitatorLabel,\n    uint128 bucketCapacity\n  ) external;\n\n  /**\n   * @notice Remove the facilitator from the facilitators list.\n   * @dev Only accounts with `FACILITATOR_MANAGER_ROLE` role can call this function\n   * @param facilitatorAddress The address of the facilitator to remove\n   */\n  function removeFacilitator(address facilitatorAddress) external;\n\n  /**\n   * @notice Set the bucket capacity of the facilitator.\n   * @dev Only accounts with `BUCKET_MANAGER_ROLE` role can call this function\n   * @param facilitator The address of the facilitator\n   * @param newCapacity The new capacity of the bucket\n   */\n  function setFacilitatorBucketCapacity(address facilitator, uint128 newCapacity) external;\n\n  /**\n   * @notice Returns the facilitator data\n   * @param facilitator The address of the facilitator\n   * @return The facilitator configuration\n   */\n  function getFacilitator(address facilitator) external view returns (Facilitator memory);\n\n  /**\n   * @notice Returns the bucket configuration of the facilitator\n   * @param facilitator The address of the facilitator\n   * @return The capacity of the facilitator's bucket\n   * @return The level of the facilitator's bucket\n   */\n  function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256);\n\n  /**\n   * @notice Returns the list of the addresses of the active facilitator\n   * @return The list of the facilitators addresses\n   */\n  function getFacilitatorsList() external view returns (address[] memory);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"ghoToken","type":"address"},{"internalType":"address","name":"underlyingAsset","type":"address"},{"internalType":"address","name":"priceStrategy","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"backer","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ghoAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingLoss","type":"uint256"}],"name":"BackingProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ghoOutstanding","type":"uint256"}],"name":"BurnAfterSeize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"originator","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ghoAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"BuyAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldExposureCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newExposureCap","type":"uint256"}],"name":"ExposureCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldFeeStrategy","type":"address"},{"indexed":true,"internalType":"address","name":"newFeeStrategy","type":"address"}],"name":"FeeStrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"ghoTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesDistributedToTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldReserve","type":"address"},{"indexed":false,"internalType":"address","name":"newReserve","type":"address"}],"name":"GhoReserveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldGhoTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newGhoTreasury","type":"address"}],"name":"GhoTreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seizer","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ghoOutstanding","type":"uint256"}],"name":"Seized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"originator","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ghoAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SellAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"freezer","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SwapFreeze","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenRescued","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountRescued","type":"uint256"}],"name":"TokensRescued","type":"event"},{"inputs":[],"name":"BUY_ASSET_WITH_SIG_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONFIGURATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GHO_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GSM_REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"LIQUIDATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_STRATEGY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SELL_ASSET_WITH_SIG_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWAP_FREEZER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_RESCUER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_ASSET","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"backWithGho","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"backWithUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnAfterSeize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"buyAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"originator","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"buyAssetWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"canSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributeFeesToTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAccruedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxGhoAmount","type":"uint256"}],"name":"getAssetAmountForBuyAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minGhoAmount","type":"uint256"}],"name":"getAssetAmountForSellAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableUnderlyingExposure","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBacking","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExposureCap","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAssetAmount","type":"uint256"}],"name":"getGhoAmountForBuyAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxAssetAmount","type":"uint256"}],"name":"getGhoAmountForSellAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGhoReserve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGhoTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIsFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIsSeized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUsed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"ghoTreasury","type":"address"},{"internalType":"uint128","name":"exposureCap","type":"uint128"},{"internalType":"address","name":"ghoReserve","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"sellAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"originator","type":"address"},{"internalType":"uint256","name":"maxAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"sellAssetWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setSwapFreeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"exposureCap","type":"uint128"}],"name":"updateExposureCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeStrategy","type":"address"}],"name":"updateFeeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGhoReserve","type":"address"}],"name":"updateGhoReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGhoTreasury","type":"address"}],"name":"updateGhoTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f000000000000000000000000d4fa2d31b7968e448877f69a96de69f5de8cd23e000000000000000000000000ee73e0c5cc8e4caf400bab5239860696ff44d64f"}