{"file_path":"contracts/usdy/USDYManager.sol","creation_status":"success","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\n\npragma solidity 0.8.16;\n\nimport \"contracts/RWAHubOffChainRedemptions.sol\";\nimport \"contracts/usdy/blocklist/BlocklistClient.sol\";\nimport \"contracts/sanctions/SanctionsListClient.sol\";\nimport \"contracts/interfaces/IUSDYManager.sol\";\n\ncontract USDYManager is\n  RWAHubOffChainRedemptions,\n  BlocklistClient,\n  SanctionsListClient,\n  IUSDYManager\n{\n  bytes32 public constant TIMESTAMP_SETTER_ROLE =\n    keccak256(\"TIMESTAMP_SETTER_ROLE\");\n\n  mapping(bytes32 => uint256) public depositIdToClaimableTimestamp;\n\n  constructor(\n    address _collateral,\n    address _rwa,\n    address managerAdmin,\n    address pauser,\n    address _assetSender,\n    address _feeRecipient,\n    uint256 _minimumDepositAmount,\n    uint256 _minimumRedemptionAmount,\n    address blocklist,\n    address sanctionsList\n  )\n    RWAHubOffChainRedemptions(\n      _collateral,\n      _rwa,\n      managerAdmin,\n      pauser,\n      _assetSender,\n      _feeRecipient,\n      _minimumDepositAmount,\n      _minimumRedemptionAmount\n    )\n    BlocklistClient(blocklist)\n    SanctionsListClient(sanctionsList)\n  {}\n\n  /**\n   * @notice Function to enforce blocklist and sanctionslist restrictions to be\n   *         implemented on calls to `requestSubscription` and\n   *         `claimRedemption`\n   *\n   * @param account The account to check blocklist and sanctions list status\n   *                for\n   */\n  function _checkRestrictions(address account) internal view override {\n    if (_isBlocked(account)) {\n      revert BlockedAccount();\n    }\n    if (_isSanctioned(account)) {\n      revert SanctionedAccount();\n    }\n  }\n\n  /**\n   * @notice Internal hook that is called by `claimMint` to enforce the time\n   *         at which a user can claim their USDY\n   *\n   * @param depositId The depositId to check the claimable timestamp for\n   *\n   * @dev This function will call the `_claimMint` function in the parent\n   *      once USDY-specific checks have been made\n   */\n  function _claimMint(bytes32 depositId) internal virtual override {\n    if (depositIdToClaimableTimestamp[depositId] == 0) {\n      revert ClaimableTimestampNotSet();\n    }\n\n    if (depositIdToClaimableTimestamp[depositId] > block.timestamp) {\n      revert MintNotYetClaimable();\n    }\n\n    super._claimMint(depositId);\n    delete depositIdToClaimableTimestamp[depositId];\n  }\n\n  /**\n   * @notice Update blocklist address\n   *\n   * @param blocklist The new blocklist address\n   */\n  function setBlocklist(\n    address blocklist\n  ) external override onlyRole(MANAGER_ADMIN) {\n    _setBlocklist(blocklist);\n  }\n\n  /**\n   * @notice Update sanctions list address\n   *\n   * @param sanctionsList The new sanctions list address\n   */\n  function setSanctionsList(\n    address sanctionsList\n  ) external override onlyRole(MANAGER_ADMIN) {\n    _setSanctionsList(sanctionsList);\n  }\n\n  /**\n   * @notice Set the claimable timestamp for a list of depositIds\n   *\n   * @param claimTimestamp The timestamp at which the deposit can be claimed\n   * @param depositIds The depositIds to set the claimable timestamp for\n   */\n  function setClaimableTimestamp(\n    uint256 claimTimestamp,\n    bytes32[] calldata depositIds\n  ) external onlyRole(TIMESTAMP_SETTER_ROLE) {\n    if (claimTimestamp < block.timestamp) {\n      revert ClaimableTimestampInPast();\n    }\n\n    uint256 depositsSize = depositIds.length;\n    for (uint256 i; i < depositsSize; ++i) {\n      depositIdToClaimableTimestamp[depositIds[i]] = claimTimestamp;\n      emit ClaimableTimestampSet(claimTimestamp, depositIds[i]);\n    }\n  }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103505760003560e01c80638d044c06116101bf578063d547741f116100fa578063e4107c971161009d578063e4107c97146107f8578063e74b981b1461080b578063ec571c6a1461081e578063eddd0d9c14610831578063ee75d7d414610844578063eeb3c91014610857578063f4a203071461086a578063f80a36d61461089157600080fd5b8063d547741f14610760578063d592d81514610773578063d64e539614610786578063d8dfeb4514610799578063dd45eef6146107c0578063de6afa82146107d3578063e0f486ef146107e6578063e1a45218146107ef57600080fd5b8063aa85c1df11610162578063aa85c1df146106b3578063aab483d6146106c6578063aef18ae7146106d9578063bb13245f146106ec578063bcc7028314610713578063ca15c87314610728578063cd4d0bcf1461073b578063d0c835ce1461074d57600080fd5b80638d044c06146106145780639010d07c1461061c57806391d148541461062f578063926d7d7f1461064257806392bccb801461066957806395e4b25114610671578063a217fddf14610698578063a6138ed9146106a057600080fd5b80633bfa67fe1161028f578063525decd611610232578063525decd6146105585780635d591d681461056b57806373a95ddd146105a45780637dbc1df0146105b1578063837018fa146105c457806385c4e79e146105cc57806387e2d06e146105e15780638a07df1e146105f457600080fd5b80633bfa67fe146104cb5780634565e9ff146104f3578063458f581514610506578063469048401461050f57806349cbbf2a1461052257806349dc5e8d1461052a5780634dfe7af21461053d5780634ef1ccd11461054557600080fd5b8063248a9ca3116102f7578063248a9ca3146103e1578063258492cd1461040557806329390370146104185780632b5eceff1461042b5780632f2ff15d1461043e578063354181f31461045157806336568abe1461045a57806338fed7081461046d57600080fd5b806301ffc9a714610355578063078a6be81461037d57806307bda1bb146103a0578063080c279a146103a957806312589fb5146103b257806313966db5146103bb5780632056aa12146103c4578063244f5acf146103ce575b600080fd5b610368610363366004612cb5565b6108a4565b60405190151581526020015b60405180910390f35b61039260008051602061324583398151915281565b604051908152602001610374565b610392600c5481565b61039260085481565b610392600f5481565b610392600a5481565b6103cc6108cf565b005b6103cc6103dc366004612d2b565b610932565b6103926103ef366004612d6d565b6000908152600160208190526040909120015490565b6103cc610413366004612da2565b610c34565b6103cc610426366004612ddd565b610d8e565b6103cc610439366004612df8565b610e07565b6103cc61044c366004612e3e565b610f16565b610392600d5481565b6103cc610468366004612e3e565b610f42565b6104a661047b366004612d6d565b6007602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610374565b6104e673bda73a0f13958ee444e0782e1768ab4b76edae2881565b6040516103749190612e6a565b6103cc610501366004612d2b565b610fc0565b610392600b5481565b6005546104e6906001600160a01b031681565b6103cc61104e565b6103cc610538366004612ddd565b6110a8565b6103cc6110ca565b6103cc610553366004612d6d565b61111f565b6103cc610566366004612ddd565b611199565b6104a6610579366004612d6d565b6006602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b600e546103689060ff1681565b6103cc6105bf366004612d6d565b611205565b6103cc61127f565b61039260008051602061320583398151915281565b6103cc6105ef366004612e7e565b6112d3565b610392610602366004612d6d565b60446020526000908152604090205481565b6103cc611481565b6104e661062a366004612eea565b6114d4565b61036861063d366004612e3e565b6114f3565b6103927fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6103cc61151e565b6104e67f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c81565b610392600081565b6003546104e6906001600160a01b031681565b6103cc6106c1366004612e7e565b611574565b6103cc6106d4366004612d6d565b6116c0565b6103cc6106e7366004612ddd565b61173a565b6103927f000000000000000000000000000000000000000000000000000000e8d4a5100081565b61039260008051602061322583398151915281565b610392610736366004612d6d565b61175c565b600e5461036890610100900460ff1681565b6103cc61075b366004612f0c565b611773565b6103cc61076e366004612e3e565b611859565b6103cc610781366004612d6d565b611880565b6010546104e6906001600160a01b031681565b6104e67f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b600e546103689062010000900460ff1681565b6103cc6107e1366004612da2565b611a63565b61039260095481565b61039261271081565b6103cc610806366004612d6d565b611bac565b6103cc610819366004612ddd565b611c03565b6011546104e6906001600160a01b031681565b6103cc61083f366004612d6d565b611c6e565b6004546104e6906001600160a01b031681565b6103cc610865366004612d6d565b611ce8565b6103927fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9381565b6103cc61089f366004612eea565b611e7c565b60006001600160e01b03198216635a05180f60e01b14806108c957506108c982612051565b92915050565b6000805160206132058339815191526108e88133612086565b600e805461ff0019166101001790556040517fcd71257f2998474633e94cfffa045014068f6218ffdca256b6f4aa9d5f15fb8990610927903390612e6a565b60405180910390a150565b60026000540361095d5760405162461bcd60e51b815260040161095490612f58565b60405180910390fd5b6002600055600e5460ff1680156109875760405163aadfaddd60e01b815260040160405180910390fd5b600082815b81811015610be0576000600760008888858181106109ac576109ac612f8f565b60209081029290920135835250818101929092526040908101600020815160608101835281546001600160a01b0316808252600183015494820194909452600290910154918101919091529150610a02906120ea565b8060400151600003610a2757604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b9190612fa5565b90506000610aad83602001518361213b565b90506000610aba8261216c565b90506000610ac88284612fd4565b9050610ad48289612fe7565b9750600760008c8c89818110610aec57610aec612f8f565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560018101829055600201556004548551610b5e916001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881169291169084612189565b8a8a87818110610b7057610b70612f8f565b87516020898101516040805191825281830188905281018a905292029390930135926001600160a01b031691507f35908d59be205275271010c5ea7062a88a2b5fbafe268bb9070550276f0edadd9060600160405180910390a3505050505080610bd990612ffa565b905061098c565b508115610c2857600454600554610c28916001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811692918116911685612189565b50506001600055505050565b600080516020613245833981519152610c4d8133612086565b83610c57816120ea565b6000600760008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506007600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f5a0c55c421ae3aac2379811eca16aaee32b6e64411322b624118d4219b9350a082600001518884604001518886602001518b604051610d7d96959493929190613013565b60405180910390a250505050505050565b600080516020613245833981519152610da78133612086565b600380546001600160a01b038481166001600160a01b03198316179092556040519116907f801352e72ef9b80b3992ccbedf07ab0e133e7da7aaccf0024abf23f4f32eb99a90610dfa9083908690613049565b60405180910390a1505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4610e328133612086565b84610e3c816120ea565b6000878152600660205260409020546001600160a01b031615610e7257604051631aeecebf60e21b815260040160405180910390fd5b60408051606080820183526001600160a01b0389811680845260208085018b815260008688018181528f82526006845290889020965187546001600160a01b031916951694909417865551600186015591516002909401939093558351898152908101889052928301869052909189917fc985471d1cb1bb75da0d54fa5ab10f7171e952cefcc0bf4fc7c2546c19d1811f910160405180910390a350505050505050565b60008281526001602081905260409091200154610f338133612086565b610f3d83836121e9565b505050565b6001600160a01b0381163314610fb25760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610954565b610fbc828261220b565b5050565b600260005403610fe25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156110115760405163aadfaddd60e01b815260040160405180910390fd5b8160005b81811015610c285761103e85858381811061103257611032612f8f565b9050602002013561222d565b61104781612ffa565b9050611015565b6000805160206132058339815191526110678133612086565b600e805462ff00001916620100001790556040517fdc41a92196ccc1ab8149c01bc68c2f506b10a7bb5cd2693c9516d176f5381ff490610927903390612e6a565b6000805160206132458339815191526110c18133612086565b610fbc826122a4565b6000805160206132458339815191526110e38133612086565b600e805462ff0000191690556040517f53a8c40fc17c78d38e2c06aa8d2c550c1acbf7b30d087dbda289ab3dd41c235c90610927903390612e6a565b6000805160206132458339815191526111388133612086565b61271082101561115b5760405163617ab12d60e11b815260040160405180910390fd5b600980549083905560408051828152602081018590527ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa15942119101610dfa565b6000805160206132458339815191526111b28133612086565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fb09f298b2812193d5ada18beaadd6cb8f12b3640926d99de46e2a65394df829d90610dfa9083908690613049565b60008051602061324583398151915261121e8133612086565b61271082111561124157604051637e2df70960e11b815260040160405180910390fd5b600b80549083905560408051828152602081018590527f2956acfe8584fb02384e06c675ee215bf10d55c3de1e6ff9b2f621e8a40c64709101610dfa565b6000805160206132458339815191526112988133612086565b600e805461ff00191690556040517f94482ee2b195c365dbbc2d689fd5a088d2b219abe44360ba8895525c9471d66f90610927903390612e6a565b6000805160206132258339815191526112ec8133612086565b8382811461130d5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600060068189898581811061132f5761132f612f8f565b60209081029290920135835250810191909152604001600020546001600160a01b031603611370576040516305a8a45b60e41b815260040160405180910390fd5b6006600088888481811061138657611386612f8f565b905060200201358152602001908152602001600020600201546000146113bf57604051631139f30960e31b815260040160405180910390fd5b8484828181106113d1576113d1612f8f565b90506020020135600660008989858181106113ee576113ee612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061141c5761141c612f8f565b9050602002013587878381811061143557611435612f8f565b905060200201357fc2055184bbc2d10b90bf7df17a84f8bdda6b52377a976e41e0c1610fffafc0d760405160405180910390a361147181612ffa565b9050611310565b50505050505050565b60008051602061324583398151915261149a8133612086565b600e805460ff191690556040517fc641b9c4afa539cedcbe2e5f3e47d9f092175b5d0b8ae72dffa634a3eb3e47e490610927903390612e6a565b60008281526002602052604081206114ec908361232a565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206132058339815191526115378133612086565b600e805460ff191660011790556040517f71e0406677c0570b2a66b1a4feeccf5c1cba2d6729435461e27a312b15410d0490610927903390612e6a565b60008051602061322583398151915261158d8133612086565b838281146115ae5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600760008888848181106115cf576115cf612f8f565b9050602002013581526020019081526020016000206002015460001461160857604051631139f30960e31b815260040160405180910390fd5b84848281811061161a5761161a612f8f565b905060200201356007600089898581811061163757611637612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061166557611665612f8f565b9050602002013587878381811061167e5761167e612f8f565b905060200201357e05e86a70f400d1820ab5a0573a2be911d831ab28fe2e9448b34daab223b09c60405160405180910390a36116b981612ffa565b90506115b1565b6000805160206132458339815191526116d98133612086565b6127108210156116fc5760405163617ab12d60e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b006574369101610dfa565b6000805160206132458339815191526117538133612086565b610fbc82612336565b60008181526002602052604081206108c9906123b0565b7fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9361179e8133612086565b428410156117bf5760405163209768a360e11b815260040160405180910390fd5b8160005b818110156118515785604460008787858181106117e2576117e2612f8f565b9050602002013581526020019081526020016000208190555084848281811061180d5761180d612f8f565b90506020020135867f15d20a98e8d4b1247fc51e2f6817929874a0769087776e52268eb1b4c8bdb2dd60405160405180910390a361184a81612ffa565b90506117c3565b505050505050565b600082815260016020819052604090912001546118768133612086565b610f3d838361220b565b6002600054036118a25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156118d15760405163aadfaddd60e01b815260040160405180910390fd5b336118db816120ea565b6008548310156118fe57604051636ba4a1c760e01b815260040160405180910390fd5b6000611909846123ba565b905060006119178286612fd4565b600c8054919250600091908261192c83612ffa565b909155506040805160608101825233815260208082018681526000838501818152868252600690935293909320915182546001600160a01b0319166001600160a01b03909116178255915160018201559051600290910155905082156119c8576005546119c8906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881169133911686612189565b611a116001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48163373bda73a0f13958ee444e0782e1768ab4b76edae2885612189565b6040805187815260208101849052908101849052819033907f7cbce37c7b11d322316420484f40c29ce672ad3fa16752551a3dbe6ccfa04e149060600160405180910390a35050600160005550505050565b600080516020613245833981519152611a7c8133612086565b83611a86816120ea565b6000600660008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506006600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f7e506b1f11218d4c947d5a59a97fd996c42afc2b024b6aeaec050930eb2b339982600001518884604001518886602001518b604051610d7d96959493929190613013565b600080516020613245833981519152611bc58133612086565b600f80549083905560408051828152602081018590527f1071422bad736c3651d3d3b7a4eda70e84e9c85a08f21c955d79ded03bbf06bb9101610dfa565b600080516020613245833981519152611c1c8133612086565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116917f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191610dfa918491613049565b600080516020613245833981519152611c878133612086565b612710821115611caa57604051637e2df70960e11b815260040160405180910390fd5b600a80549083905560408051828152602081018590527f387269377ae17304805d5f88cea4252e5ca47346783c279aeb9e8627335a49ac9101610dfa565b600260005403611d0a5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5460ff168015611d345760405163aadfaddd60e01b815260040160405180910390fd5b600954821015611d575760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611d6883612ffa565b909155506040805160608101825233808252602080830188815260008486018181528782526007909352859020935184546001600160a01b0319166001600160a01b03918216178555905160018501559051600290930192909255915163079cc67960e41b81529293507f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c16916379cc679091611e09918790600401613063565b600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b50506040518581528392503391507f80ebb30e7c30052bf403a20da869bdd033841684e93930d97c4af74238529b4f9060200160405180910390a35050600160005550565b600260005403611e9e5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5462010000900460ff168015611ece5760405163aadfaddd60e01b815260040160405180910390fd5b600f54831015611ef15760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611f0283612ffa565b9091555060405163079cc67960e41b81529091506001600160a01b037f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c16906379cc679090611f579033908890600401613063565b600060405180830381600087803b158015611f7157600080fd5b505af1158015611f85573d6000803e3d6000fd5b505060408051878152602081018790528493503392507fad2102c6abc98f954bd5d61e6c0d19764db331f63019296309309a34f70e66a6910160405180910390a3505060016000555050565b611fdb82826114f3565b610fbc5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60006114ec836001600160a01b0384166123cd565b60006001600160e01b03198216637965db0b60e01b14806108c957506301ffc9a760e01b6001600160e01b03198316146108c9565b61209082826114f3565b610fbc576120a8816001600160a01b0316601461241c565b6120b383602061241c565b6040516020016120c49291906130a0565b60408051601f198184030181529082905262461bcd60e51b82526109549160040161310f565b6120f3816125b8565b15612111576040516305ffb90760e11b815260040160405180910390fd5b61211a8161262a565b1561213857604051632be4781160e21b815260040160405180910390fd5b50565b6000806121488385613142565b905061216461215f670de0b6b3a764000083613161565b61265b565b949350505050565b6000612710600b548361217f9190613142565b6108c99190613161565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526121e3908590612687565b50505050565b6121f38282611fd1565b6000828152600260205260409020610f3d908261203c565b6122158282612759565b6000828152600260205260409020610f3d90826127c0565b600081815260446020526040812054900361225b57604051630ad2496160e31b815260040160405180910390fd5b60008181526044602052604090205442101561228a5760405163309b0bcf60e21b815260040160405180910390fd5b612293816127d5565b600090815260446020526040812055565b6001600160a01b0381166122cb576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03198316179092556040519116907fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e39061231e9083908590613049565b60405180910390a15050565b60006114ec83836129c9565b6001600160a01b03811661235d57604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03198316179092556040519116907f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b73049061231e9083908590613049565b60006108c9825490565b6000612710600a548361217f9190613142565b6000818152600183016020526040812054612414575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c9565b5060006108c9565b6060600061242b836002613142565b612436906002612fe7565b67ffffffffffffffff81111561244e5761244e613183565b6040519080825280601f01601f191660200182016040528015612478576020820181803683370190505b509050600360fc1b8160008151811061249357612493612f8f565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106124c2576124c2612f8f565b60200101906001600160f81b031916908160001a90535060006124e6846002613142565b6124f1906001612fe7565b90505b6001811115612569576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061252557612525612f8f565b1a60f81b82828151811061253b5761253b612f8f565b60200101906001600160f81b031916908160001a90535060049490941c9361256281613199565b90506124f4565b5083156114ec5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610954565b60105460405163fbac395160e01b81526000916001600160a01b03169063fbac3951906125e9908590600401612e6a565b602060405180830381865afa158015612606573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c991906131b0565b60115460405163df592f7d60e01b81526000916001600160a01b03169063df592f7d906125e9908590600401612e6a565b60006108c97f000000000000000000000000000000000000000000000000000000e8d4a5100083613161565b60006126dc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166129f39092919063ffffffff16565b805190915015610f3d57808060200190518101906126fa91906131b0565b610f3d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610954565b61276382826114f3565b15610fbc5760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006114ec836001600160a01b038416612a02565b6000818152600660209081526040808320815160608101835281546001600160a01b031681526001820154938101939093526002015490820181905290910361283157604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190612fa5565b905060006128b7836020015183612af5565b60008581526006602052604080822080546001600160a01b03191681556001810183905560020191909155845190516340c10f1960e01b81529192507f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c6001600160a01b0316916340c10f1991612932918590600401613063565b600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b50508451602080870151604080890151815188815293840192909252820187905260608201528793506001600160a01b0390911691507fdd602cc9cb236502fb74f091872b4025184011dd96eee41099caa260842f20249060800160405180910390a350505050565b60008260000182815481106129e0576129e0612f8f565b9060005260206000200154905092915050565b60606121648484600085612b1f565b60008181526001830160205260408120548015612aeb576000612a26600183612fd4565b8554909150600090612a3a90600190612fd4565b9050818114612a9f576000866000018281548110612a5a57612a5a612f8f565b9060005260206000200154905080876000018481548110612a7d57612a7d612f8f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ab057612ab06131d2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c9565b60009150506108c9565b600080612b0184612c50565b612b1390670de0b6b3a7640000613142565b90506121648382613161565b606082471015612b805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610954565b6001600160a01b0385163b612bd75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610954565b600080866001600160a01b03168587604051612bf391906131e8565b60006040518083038185875af1925050503d8060008114612c30576040519150601f19603f3d011682016040523d82523d6000602084013e612c35565b606091505b5091509150612c45828286612c7c565b979650505050505050565b60006108c97f000000000000000000000000000000000000000000000000000000e8d4a5100083613142565b60608315612c8b5750816114ec565b825115612c9b5782518084602001fd5b8160405162461bcd60e51b8152600401610954919061310f565b600060208284031215612cc757600080fd5b81356001600160e01b0319811681146114ec57600080fd5b60008083601f840112612cf157600080fd5b50813567ffffffffffffffff811115612d0957600080fd5b6020830191508360208260051b8501011115612d2457600080fd5b9250929050565b60008060208385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d6185828601612cdf565b90969095509350505050565b600060208284031215612d7f57600080fd5b5035919050565b80356001600160a01b0381168114612d9d57600080fd5b919050565b60008060008060808587031215612db857600080fd5b84359350612dc860208601612d86565b93969395505050506040820135916060013590565b600060208284031215612def57600080fd5b6114ec82612d86565b600080600080600060a08688031215612e1057600080fd5b85359450612e2060208701612d86565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215612e5157600080fd5b82359150612e6160208401612d86565b90509250929050565b6001600160a01b0391909116815260200190565b60008060008060408587031215612e9457600080fd5b843567ffffffffffffffff80821115612eac57600080fd5b612eb888838901612cdf565b90965094506020870135915080821115612ed157600080fd5b50612ede87828801612cdf565b95989497509550505050565b60008060408385031215612efd57600080fd5b50508035926020909101359150565b600080600060408486031215612f2157600080fd5b83359250602084013567ffffffffffffffff811115612f3f57600080fd5b612f4b86828701612cdf565b9497909650939450505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fb757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108c9576108c9612fbe565b808201808211156108c9576108c9612fbe565b60006001820161300c5761300c612fbe565b5060010190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60005b8381101561309757818101518382015260200161307f565b50506000910152565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516130d281601785016020880161307c565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310381602884016020880161307c565b01602801949350505050565b602081526000825180602084015261312e81604085016020870161307c565b601f01601f19169190910160400192915050565b600081600019048311821515161561315c5761315c612fbe565b500290565b60008261317e57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6000816131a8576131a8612fbe565b506000190190565b6000602082840312156131c257600080fd5b815180151581146114ec57600080fd5b634e487b7160e01b600052603160045260246000fd5b600082516131fa81846020870161307c565b919091019291505056fe9ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03a2646970667358221220e50e8ac686954d12f9ea6160d12a7f72993f15c301125b7b66dd8b7ae8858cb764736f6c63430008100033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":100},"remappings":[]},"optimization_runs":100,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x25A103A1D6AeC5967c1A4fe2039cdc514886b97e/","decoded_constructor_args":[["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",{"internalType":"address","name":"_collateral","type":"address"}],["0x96F6eF951840721AdBF46Ac996b59E0235CB985C",{"internalType":"address","name":"_rwa","type":"address"}],["0x1a694A09494E214a3Be3652e4B343B7B81A73ad7",{"internalType":"address","name":"managerAdmin","type":"address"}],["0x2e55b738F5969Eea10fB67e326BEE5e2fA15A2CC",{"internalType":"address","name":"pauser","type":"address"}],["0x5Eb3ac7D9B8220C484307a2506D611Cc759626Ca",{"internalType":"address","name":"_assetSender","type":"address"}],["0x1a694A09494E214a3Be3652e4B343B7B81A73ad7",{"internalType":"address","name":"_feeRecipient","type":"address"}],["500000000",{"internalType":"uint256","name":"_minimumDepositAmount","type":"uint256"}],["500000000000000000000",{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"}],["0xd8c8174691d936E2C80114EC449037b13421B0a8",{"internalType":"address","name":"blocklist","type":"address"}],["0x40C57923924B5c5c5455c48D93317139ADDaC8fb",{"internalType":"address","name":"sanctionsList","type":"address"}]],"compiler_version":"0.8.16+commit.07a7930e","is_verified_via_verifier_alliance":false,"verified_at":"2024-02-20T18:47:56.154840Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60e06040526000600a556000600b556001600c556001600d553480156200002557600080fd5b5060405162003b7138038062003b718339810160408190526200004891620005ff565b600160005580828b8b8b8b8b8b8b8b87878787878787876001600160a01b038816620000875760405163a1aeceb760e01b815260040160405180910390fd5b6001600160a01b038716620000af5760405163071aeb1d60e01b815260040160405180910390fd5b6001600160a01b038416620000d757604051633b2b1d5560e01b815260040160405180910390fd5b6001600160a01b038316620000ff57604051634fdcfc5560e11b815260040160405180910390fd5b6200010c6000876200034a565b6200012760008051602062003b51833981519152876200034a565b6200014260008051602062003b31833981519152866200034a565b6200016c60008051602062003b3183398151915260008051602062003b518339815191526200038d565b620001a77f830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d60008051602062003b518339815191526200038d565b620001e27fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc460008051602062003b518339815191526200038d565b6001600160a01b0388811660a0819052888216608052600580546001600160a01b03199081168785161790915560048054909116928716929092178255600884905560098390556040805163313ce56760e01b81529051919263313ce5679282820192602092908290030181865afa15801562000263573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002899190620006bc565b876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ee9190620006bc565b620002fa9190620006fe565b6200030790600a62000817565b60c052505050600f95909555506200032d9a508b995050620003da975050505050505050565b50620003398162000464565b505050505050505050505062000828565b620003618282620004e760201b62001fd11760201c565b6000828152600260209081526040909120620003889183906200203c62000570821b17901c565b505050565b6000828152600160208190526040808320909101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6001600160a01b0381166200040257604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b730491015b60405180910390a15050565b6001600160a01b0381166200048c576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e3910162000458565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff166200056c5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45b5050565b600062000587836001600160a01b03841662000590565b90505b92915050565b6000818152600183016020526040812054620005d9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200058a565b5060006200058a565b80516001600160a01b0381168114620005fa57600080fd5b919050565b6000806000806000806000806000806101408b8d0312156200062057600080fd5b6200062b8b620005e2565b99506200063b60208c01620005e2565b98506200064b60408c01620005e2565b97506200065b60608c01620005e2565b96506200066b60808c01620005e2565b95506200067b60a08c01620005e2565b945060c08b0151935060e08b015192506200069a6101008c01620005e2565b9150620006ab6101208c01620005e2565b90509295989b9194979a5092959850565b600060208284031215620006cf57600080fd5b815160ff81168114620006e157600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff82811682821603908111156200058a576200058a620006e8565b600181815b808511156200075b5781600019048211156200073f576200073f620006e8565b808516156200074d57918102915b93841c93908002906200071f565b509250929050565b60008262000774575060016200058a565b8162000783575060006200058a565b81600181146200079c5760028114620007a757620007c7565b60019150506200058a565b60ff841115620007bb57620007bb620006e8565b50506001821b6200058a565b5060208310610133831016604e8410600b8410161715620007ec575081810a6200058a565b620007f883836200071a565b80600019048211156200080f576200080f620006e8565b029392505050565b60006200058760ff84168362000763565b60805160a05160c05161329a62000897600039600081816106f1015281816126620152612c5701526000818161079e01528181610b3301528181610bfb0152818161199d01526119d501526000818161067601528181611dd401528181611f2001526128f5015261329a6000f3fe608060405234801561001057600080fd5b50600436106103505760003560e01c80638d044c06116101bf578063d547741f116100fa578063e4107c971161009d578063e4107c97146107f8578063e74b981b1461080b578063ec571c6a1461081e578063eddd0d9c14610831578063ee75d7d414610844578063eeb3c91014610857578063f4a203071461086a578063f80a36d61461089157600080fd5b8063d547741f14610760578063d592d81514610773578063d64e539614610786578063d8dfeb4514610799578063dd45eef6146107c0578063de6afa82146107d3578063e0f486ef146107e6578063e1a45218146107ef57600080fd5b8063aa85c1df11610162578063aa85c1df146106b3578063aab483d6146106c6578063aef18ae7146106d9578063bb13245f146106ec578063bcc7028314610713578063ca15c87314610728578063cd4d0bcf1461073b578063d0c835ce1461074d57600080fd5b80638d044c06146106145780639010d07c1461061c57806391d148541461062f578063926d7d7f1461064257806392bccb801461066957806395e4b25114610671578063a217fddf14610698578063a6138ed9146106a057600080fd5b80633bfa67fe1161028f578063525decd611610232578063525decd6146105585780635d591d681461056b57806373a95ddd146105a45780637dbc1df0146105b1578063837018fa146105c457806385c4e79e146105cc57806387e2d06e146105e15780638a07df1e146105f457600080fd5b80633bfa67fe146104cb5780634565e9ff146104f3578063458f581514610506578063469048401461050f57806349cbbf2a1461052257806349dc5e8d1461052a5780634dfe7af21461053d5780634ef1ccd11461054557600080fd5b8063248a9ca3116102f7578063248a9ca3146103e1578063258492cd1461040557806329390370146104185780632b5eceff1461042b5780632f2ff15d1461043e578063354181f31461045157806336568abe1461045a57806338fed7081461046d57600080fd5b806301ffc9a714610355578063078a6be81461037d57806307bda1bb146103a0578063080c279a146103a957806312589fb5146103b257806313966db5146103bb5780632056aa12146103c4578063244f5acf146103ce575b600080fd5b610368610363366004612cb5565b6108a4565b60405190151581526020015b60405180910390f35b61039260008051602061324583398151915281565b604051908152602001610374565b610392600c5481565b61039260085481565b610392600f5481565b610392600a5481565b6103cc6108cf565b005b6103cc6103dc366004612d2b565b610932565b6103926103ef366004612d6d565b6000908152600160208190526040909120015490565b6103cc610413366004612da2565b610c34565b6103cc610426366004612ddd565b610d8e565b6103cc610439366004612df8565b610e07565b6103cc61044c366004612e3e565b610f16565b610392600d5481565b6103cc610468366004612e3e565b610f42565b6104a661047b366004612d6d565b6007602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610374565b6104e673bda73a0f13958ee444e0782e1768ab4b76edae2881565b6040516103749190612e6a565b6103cc610501366004612d2b565b610fc0565b610392600b5481565b6005546104e6906001600160a01b031681565b6103cc61104e565b6103cc610538366004612ddd565b6110a8565b6103cc6110ca565b6103cc610553366004612d6d565b61111f565b6103cc610566366004612ddd565b611199565b6104a6610579366004612d6d565b6006602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b600e546103689060ff1681565b6103cc6105bf366004612d6d565b611205565b6103cc61127f565b61039260008051602061320583398151915281565b6103cc6105ef366004612e7e565b6112d3565b610392610602366004612d6d565b60446020526000908152604090205481565b6103cc611481565b6104e661062a366004612eea565b6114d4565b61036861063d366004612e3e565b6114f3565b6103927fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6103cc61151e565b6104e67f000000000000000000000000000000000000000000000000000000000000000081565b610392600081565b6003546104e6906001600160a01b031681565b6103cc6106c1366004612e7e565b611574565b6103cc6106d4366004612d6d565b6116c0565b6103cc6106e7366004612ddd565b61173a565b6103927f000000000000000000000000000000000000000000000000000000000000000081565b61039260008051602061322583398151915281565b610392610736366004612d6d565b61175c565b600e5461036890610100900460ff1681565b6103cc61075b366004612f0c565b611773565b6103cc61076e366004612e3e565b611859565b6103cc610781366004612d6d565b611880565b6010546104e6906001600160a01b031681565b6104e67f000000000000000000000000000000000000000000000000000000000000000081565b600e546103689062010000900460ff1681565b6103cc6107e1366004612da2565b611a63565b61039260095481565b61039261271081565b6103cc610806366004612d6d565b611bac565b6103cc610819366004612ddd565b611c03565b6011546104e6906001600160a01b031681565b6103cc61083f366004612d6d565b611c6e565b6004546104e6906001600160a01b031681565b6103cc610865366004612d6d565b611ce8565b6103927fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9381565b6103cc61089f366004612eea565b611e7c565b60006001600160e01b03198216635a05180f60e01b14806108c957506108c982612051565b92915050565b6000805160206132058339815191526108e88133612086565b600e805461ff0019166101001790556040517fcd71257f2998474633e94cfffa045014068f6218ffdca256b6f4aa9d5f15fb8990610927903390612e6a565b60405180910390a150565b60026000540361095d5760405162461bcd60e51b815260040161095490612f58565b60405180910390fd5b6002600055600e5460ff1680156109875760405163aadfaddd60e01b815260040160405180910390fd5b600082815b81811015610be0576000600760008888858181106109ac576109ac612f8f565b60209081029290920135835250818101929092526040908101600020815160608101835281546001600160a01b0316808252600183015494820194909452600290910154918101919091529150610a02906120ea565b8060400151600003610a2757604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b9190612fa5565b90506000610aad83602001518361213b565b90506000610aba8261216c565b90506000610ac88284612fd4565b9050610ad48289612fe7565b9750600760008c8c89818110610aec57610aec612f8f565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560018101829055600201556004548551610b5e916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169291169084612189565b8a8a87818110610b7057610b70612f8f565b87516020898101516040805191825281830188905281018a905292029390930135926001600160a01b031691507f35908d59be205275271010c5ea7062a88a2b5fbafe268bb9070550276f0edadd9060600160405180910390a3505050505080610bd990612ffa565b905061098c565b508115610c2857600454600554610c28916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811692918116911685612189565b50506001600055505050565b600080516020613245833981519152610c4d8133612086565b83610c57816120ea565b6000600760008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506007600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f5a0c55c421ae3aac2379811eca16aaee32b6e64411322b624118d4219b9350a082600001518884604001518886602001518b604051610d7d96959493929190613013565b60405180910390a250505050505050565b600080516020613245833981519152610da78133612086565b600380546001600160a01b038481166001600160a01b03198316179092556040519116907f801352e72ef9b80b3992ccbedf07ab0e133e7da7aaccf0024abf23f4f32eb99a90610dfa9083908690613049565b60405180910390a1505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4610e328133612086565b84610e3c816120ea565b6000878152600660205260409020546001600160a01b031615610e7257604051631aeecebf60e21b815260040160405180910390fd5b60408051606080820183526001600160a01b0389811680845260208085018b815260008688018181528f82526006845290889020965187546001600160a01b031916951694909417865551600186015591516002909401939093558351898152908101889052928301869052909189917fc985471d1cb1bb75da0d54fa5ab10f7171e952cefcc0bf4fc7c2546c19d1811f910160405180910390a350505050505050565b60008281526001602081905260409091200154610f338133612086565b610f3d83836121e9565b505050565b6001600160a01b0381163314610fb25760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610954565b610fbc828261220b565b5050565b600260005403610fe25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156110115760405163aadfaddd60e01b815260040160405180910390fd5b8160005b81811015610c285761103e85858381811061103257611032612f8f565b9050602002013561222d565b61104781612ffa565b9050611015565b6000805160206132058339815191526110678133612086565b600e805462ff00001916620100001790556040517fdc41a92196ccc1ab8149c01bc68c2f506b10a7bb5cd2693c9516d176f5381ff490610927903390612e6a565b6000805160206132458339815191526110c18133612086565b610fbc826122a4565b6000805160206132458339815191526110e38133612086565b600e805462ff0000191690556040517f53a8c40fc17c78d38e2c06aa8d2c550c1acbf7b30d087dbda289ab3dd41c235c90610927903390612e6a565b6000805160206132458339815191526111388133612086565b61271082101561115b5760405163617ab12d60e11b815260040160405180910390fd5b600980549083905560408051828152602081018590527ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa15942119101610dfa565b6000805160206132458339815191526111b28133612086565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fb09f298b2812193d5ada18beaadd6cb8f12b3640926d99de46e2a65394df829d90610dfa9083908690613049565b60008051602061324583398151915261121e8133612086565b61271082111561124157604051637e2df70960e11b815260040160405180910390fd5b600b80549083905560408051828152602081018590527f2956acfe8584fb02384e06c675ee215bf10d55c3de1e6ff9b2f621e8a40c64709101610dfa565b6000805160206132458339815191526112988133612086565b600e805461ff00191690556040517f94482ee2b195c365dbbc2d689fd5a088d2b219abe44360ba8895525c9471d66f90610927903390612e6a565b6000805160206132258339815191526112ec8133612086565b8382811461130d5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600060068189898581811061132f5761132f612f8f565b60209081029290920135835250810191909152604001600020546001600160a01b031603611370576040516305a8a45b60e41b815260040160405180910390fd5b6006600088888481811061138657611386612f8f565b905060200201358152602001908152602001600020600201546000146113bf57604051631139f30960e31b815260040160405180910390fd5b8484828181106113d1576113d1612f8f565b90506020020135600660008989858181106113ee576113ee612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061141c5761141c612f8f565b9050602002013587878381811061143557611435612f8f565b905060200201357fc2055184bbc2d10b90bf7df17a84f8bdda6b52377a976e41e0c1610fffafc0d760405160405180910390a361147181612ffa565b9050611310565b50505050505050565b60008051602061324583398151915261149a8133612086565b600e805460ff191690556040517fc641b9c4afa539cedcbe2e5f3e47d9f092175b5d0b8ae72dffa634a3eb3e47e490610927903390612e6a565b60008281526002602052604081206114ec908361232a565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206132058339815191526115378133612086565b600e805460ff191660011790556040517f71e0406677c0570b2a66b1a4feeccf5c1cba2d6729435461e27a312b15410d0490610927903390612e6a565b60008051602061322583398151915261158d8133612086565b838281146115ae5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600760008888848181106115cf576115cf612f8f565b9050602002013581526020019081526020016000206002015460001461160857604051631139f30960e31b815260040160405180910390fd5b84848281811061161a5761161a612f8f565b905060200201356007600089898581811061163757611637612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061166557611665612f8f565b9050602002013587878381811061167e5761167e612f8f565b905060200201357e05e86a70f400d1820ab5a0573a2be911d831ab28fe2e9448b34daab223b09c60405160405180910390a36116b981612ffa565b90506115b1565b6000805160206132458339815191526116d98133612086565b6127108210156116fc5760405163617ab12d60e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b006574369101610dfa565b6000805160206132458339815191526117538133612086565b610fbc82612336565b60008181526002602052604081206108c9906123b0565b7fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9361179e8133612086565b428410156117bf5760405163209768a360e11b815260040160405180910390fd5b8160005b818110156118515785604460008787858181106117e2576117e2612f8f565b9050602002013581526020019081526020016000208190555084848281811061180d5761180d612f8f565b90506020020135867f15d20a98e8d4b1247fc51e2f6817929874a0769087776e52268eb1b4c8bdb2dd60405160405180910390a361184a81612ffa565b90506117c3565b505050505050565b600082815260016020819052604090912001546118768133612086565b610f3d838361220b565b6002600054036118a25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156118d15760405163aadfaddd60e01b815260040160405180910390fd5b336118db816120ea565b6008548310156118fe57604051636ba4a1c760e01b815260040160405180910390fd5b6000611909846123ba565b905060006119178286612fd4565b600c8054919250600091908261192c83612ffa565b909155506040805160608101825233815260208082018681526000838501818152868252600690935293909320915182546001600160a01b0319166001600160a01b03909116178255915160018201559051600290910155905082156119c8576005546119c8906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169133911686612189565b611a116001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163373bda73a0f13958ee444e0782e1768ab4b76edae2885612189565b6040805187815260208101849052908101849052819033907f7cbce37c7b11d322316420484f40c29ce672ad3fa16752551a3dbe6ccfa04e149060600160405180910390a35050600160005550505050565b600080516020613245833981519152611a7c8133612086565b83611a86816120ea565b6000600660008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506006600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f7e506b1f11218d4c947d5a59a97fd996c42afc2b024b6aeaec050930eb2b339982600001518884604001518886602001518b604051610d7d96959493929190613013565b600080516020613245833981519152611bc58133612086565b600f80549083905560408051828152602081018590527f1071422bad736c3651d3d3b7a4eda70e84e9c85a08f21c955d79ded03bbf06bb9101610dfa565b600080516020613245833981519152611c1c8133612086565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116917f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191610dfa918491613049565b600080516020613245833981519152611c878133612086565b612710821115611caa57604051637e2df70960e11b815260040160405180910390fd5b600a80549083905560408051828152602081018590527f387269377ae17304805d5f88cea4252e5ca47346783c279aeb9e8627335a49ac9101610dfa565b600260005403611d0a5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5460ff168015611d345760405163aadfaddd60e01b815260040160405180910390fd5b600954821015611d575760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611d6883612ffa565b909155506040805160608101825233808252602080830188815260008486018181528782526007909352859020935184546001600160a01b0319166001600160a01b03918216178555905160018501559051600290930192909255915163079cc67960e41b81529293507f000000000000000000000000000000000000000000000000000000000000000016916379cc679091611e09918790600401613063565b600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b50506040518581528392503391507f80ebb30e7c30052bf403a20da869bdd033841684e93930d97c4af74238529b4f9060200160405180910390a35050600160005550565b600260005403611e9e5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5462010000900460ff168015611ece5760405163aadfaddd60e01b815260040160405180910390fd5b600f54831015611ef15760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611f0283612ffa565b9091555060405163079cc67960e41b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906379cc679090611f579033908890600401613063565b600060405180830381600087803b158015611f7157600080fd5b505af1158015611f85573d6000803e3d6000fd5b505060408051878152602081018790528493503392507fad2102c6abc98f954bd5d61e6c0d19764db331f63019296309309a34f70e66a6910160405180910390a3505060016000555050565b611fdb82826114f3565b610fbc5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60006114ec836001600160a01b0384166123cd565b60006001600160e01b03198216637965db0b60e01b14806108c957506301ffc9a760e01b6001600160e01b03198316146108c9565b61209082826114f3565b610fbc576120a8816001600160a01b0316601461241c565b6120b383602061241c565b6040516020016120c49291906130a0565b60408051601f198184030181529082905262461bcd60e51b82526109549160040161310f565b6120f3816125b8565b15612111576040516305ffb90760e11b815260040160405180910390fd5b61211a8161262a565b1561213857604051632be4781160e21b815260040160405180910390fd5b50565b6000806121488385613142565b905061216461215f670de0b6b3a764000083613161565b61265b565b949350505050565b6000612710600b548361217f9190613142565b6108c99190613161565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526121e3908590612687565b50505050565b6121f38282611fd1565b6000828152600260205260409020610f3d908261203c565b6122158282612759565b6000828152600260205260409020610f3d90826127c0565b600081815260446020526040812054900361225b57604051630ad2496160e31b815260040160405180910390fd5b60008181526044602052604090205442101561228a5760405163309b0bcf60e21b815260040160405180910390fd5b612293816127d5565b600090815260446020526040812055565b6001600160a01b0381166122cb576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03198316179092556040519116907fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e39061231e9083908590613049565b60405180910390a15050565b60006114ec83836129c9565b6001600160a01b03811661235d57604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03198316179092556040519116907f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b73049061231e9083908590613049565b60006108c9825490565b6000612710600a548361217f9190613142565b6000818152600183016020526040812054612414575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c9565b5060006108c9565b6060600061242b836002613142565b612436906002612fe7565b67ffffffffffffffff81111561244e5761244e613183565b6040519080825280601f01601f191660200182016040528015612478576020820181803683370190505b509050600360fc1b8160008151811061249357612493612f8f565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106124c2576124c2612f8f565b60200101906001600160f81b031916908160001a90535060006124e6846002613142565b6124f1906001612fe7565b90505b6001811115612569576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061252557612525612f8f565b1a60f81b82828151811061253b5761253b612f8f565b60200101906001600160f81b031916908160001a90535060049490941c9361256281613199565b90506124f4565b5083156114ec5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610954565b60105460405163fbac395160e01b81526000916001600160a01b03169063fbac3951906125e9908590600401612e6a565b602060405180830381865afa158015612606573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c991906131b0565b60115460405163df592f7d60e01b81526000916001600160a01b03169063df592f7d906125e9908590600401612e6a565b60006108c97f000000000000000000000000000000000000000000000000000000000000000083613161565b60006126dc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166129f39092919063ffffffff16565b805190915015610f3d57808060200190518101906126fa91906131b0565b610f3d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610954565b61276382826114f3565b15610fbc5760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006114ec836001600160a01b038416612a02565b6000818152600660209081526040808320815160608101835281546001600160a01b031681526001820154938101939093526002015490820181905290910361283157604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190612fa5565b905060006128b7836020015183612af5565b60008581526006602052604080822080546001600160a01b03191681556001810183905560020191909155845190516340c10f1960e01b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916340c10f1991612932918590600401613063565b600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b50508451602080870151604080890151815188815293840192909252820187905260608201528793506001600160a01b0390911691507fdd602cc9cb236502fb74f091872b4025184011dd96eee41099caa260842f20249060800160405180910390a350505050565b60008260000182815481106129e0576129e0612f8f565b9060005260206000200154905092915050565b60606121648484600085612b1f565b60008181526001830160205260408120548015612aeb576000612a26600183612fd4565b8554909150600090612a3a90600190612fd4565b9050818114612a9f576000866000018281548110612a5a57612a5a612f8f565b9060005260206000200154905080876000018481548110612a7d57612a7d612f8f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ab057612ab06131d2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c9565b60009150506108c9565b600080612b0184612c50565b612b1390670de0b6b3a7640000613142565b90506121648382613161565b606082471015612b805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610954565b6001600160a01b0385163b612bd75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610954565b600080866001600160a01b03168587604051612bf391906131e8565b60006040518083038185875af1925050503d8060008114612c30576040519150601f19603f3d011682016040523d82523d6000602084013e612c35565b606091505b5091509150612c45828286612c7c565b979650505050505050565b60006108c97f000000000000000000000000000000000000000000000000000000000000000083613142565b60608315612c8b5750816114ec565b825115612c9b5782518084602001fd5b8160405162461bcd60e51b8152600401610954919061310f565b600060208284031215612cc757600080fd5b81356001600160e01b0319811681146114ec57600080fd5b60008083601f840112612cf157600080fd5b50813567ffffffffffffffff811115612d0957600080fd5b6020830191508360208260051b8501011115612d2457600080fd5b9250929050565b60008060208385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d6185828601612cdf565b90969095509350505050565b600060208284031215612d7f57600080fd5b5035919050565b80356001600160a01b0381168114612d9d57600080fd5b919050565b60008060008060808587031215612db857600080fd5b84359350612dc860208601612d86565b93969395505050506040820135916060013590565b600060208284031215612def57600080fd5b6114ec82612d86565b600080600080600060a08688031215612e1057600080fd5b85359450612e2060208701612d86565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215612e5157600080fd5b82359150612e6160208401612d86565b90509250929050565b6001600160a01b0391909116815260200190565b60008060008060408587031215612e9457600080fd5b843567ffffffffffffffff80821115612eac57600080fd5b612eb888838901612cdf565b90965094506020870135915080821115612ed157600080fd5b50612ede87828801612cdf565b95989497509550505050565b60008060408385031215612efd57600080fd5b50508035926020909101359150565b600080600060408486031215612f2157600080fd5b83359250602084013567ffffffffffffffff811115612f3f57600080fd5b612f4b86828701612cdf565b9497909650939450505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fb757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108c9576108c9612fbe565b808201808211156108c9576108c9612fbe565b60006001820161300c5761300c612fbe565b5060010190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60005b8381101561309757818101518382015260200161307f565b50506000910152565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516130d281601785016020880161307c565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310381602884016020880161307c565b01602801949350505050565b602081526000825180602084015261312e81604085016020870161307c565b601f01601f19169190910160400192915050565b600081600019048311821515161561315c5761315c612fbe565b500290565b60008261317e57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6000816131a8576131a8612fbe565b506000190190565b6000602082840312156131c257600080fd5b815180151581146114ec57600080fd5b634e487b7160e01b600052603160045260246000fd5b600082516131fa81846020870161307c565b919091019291505056fe9ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03a2646970667358221220e50e8ac686954d12f9ea6160d12a7f72993f15c301125b7b66dd8b7ae8858cb764736f6c634300081000339ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad70000000000000000000000002e55b738f5969eea10fb67e326bee5e2fa15a2cc0000000000000000000000005eb3ac7d9b8220c484307a2506d611cc759626ca0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7000000000000000000000000000000000000000000000000000000001dcd650000000000000000000000000000000000000000000000001b1ae4d6e2ef500000000000000000000000000000d8c8174691d936e2c80114ec449037b13421b0a800000000000000000000000040c57923924b5c5c5455c48d93317139addac8fb","name":"USDYManager","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"contracts/RWAHub.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/interfaces/IPricerReader.sol\";\nimport \"contracts/interfaces/IRWALike.sol\";\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\nimport \"contracts/external/openzeppelin/contracts/token/SafeERC20.sol\";\nimport \"contracts/interfaces/IRWAHub.sol\";\n\n// Additional Dependencies\nimport \"contracts/external/openzeppelin/contracts/token/IERC20Metadata.sol\";\nimport \"contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol\";\nimport \"contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nabstract contract RWAHub is IRWAHub, ReentrancyGuard, AccessControlEnumerable {\n  using SafeERC20 for IERC20;\n  // RWA Token contract\n  IRWALike public immutable rwa;\n  // Pointer to Pricer\n  IPricerReader public pricer;\n  // Address to receive deposits\n  address public constant assetRecipient =\n    0xbDa73A0F13958ee444e0782E1768aB4B76EdaE28; // USDY - CB Deposit Address\n  // Address to send redemptions\n  address public assetSender;\n  // Address fee recipient\n  address public feeRecipient;\n  // Mapping from deposit Id -> Depositor\n  mapping(bytes32 => Depositor) public depositIdToDepositor;\n  // Mapping from redemptionId -> Redeemer\n  mapping(bytes32 => Redeemer) public redemptionIdToRedeemer;\n\n  /// @dev Mint/Redeem Parameters\n  // Minimum amount that must be deposited to mint the RWA token\n  // Denoted in decimals of `collateral`\n  uint256 public minimumDepositAmount;\n\n  // Minimum amount that must be redeemed for a withdraw request\n  uint256 public minimumRedemptionAmount;\n\n  // Minting fee specified in basis points\n  uint256 public mintFee = 0;\n\n  // Redemption fee specified in basis points\n  uint256 public redemptionFee = 0;\n\n  // The asset accepted by the RWAHub\n  IERC20 public immutable collateral;\n\n  // Decimal multiplier representing the difference between `rwa` decimals\n  // In `collateral` token decimals\n  uint256 public immutable decimalsMultiplier;\n\n  // Deposit counter to map subscription requests to\n  uint256 public subscriptionRequestCounter = 1;\n\n  // Redemption Id to map from\n  uint256 public redemptionRequestCounter = 1;\n\n  // Helper constant that allows us to specify basis points in calculations\n  uint256 public constant BPS_DENOMINATOR = 10_000;\n\n  // Pause variables\n  bool public redemptionPaused;\n  bool public subscriptionPaused;\n\n  /// @dev Role based access control roles\n  bytes32 public constant MANAGER_ADMIN = keccak256(\"MANAGER_ADMIN\");\n  bytes32 public constant PAUSER_ADMIN = keccak256(\"PAUSER_ADMIN\");\n  bytes32 public constant PRICE_ID_SETTER_ROLE =\n    keccak256(\"PRICE_ID_SETTER_ROLE\");\n  bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n\n  /// @notice constructor\n  constructor(\n    address _collateral,\n    address _rwa,\n    address managerAdmin,\n    address pauser,\n    address _assetSender,\n    address _feeRecipient,\n    uint256 _minimumDepositAmount,\n    uint256 _minimumRedemptionAmount\n  ) {\n    if (_collateral == address(0)) {\n      revert CollateralCannotBeZero();\n    }\n    if (_rwa == address(0)) {\n      revert RWACannotBeZero();\n    }\n    if (_assetSender == address(0)) {\n      revert AssetSenderCannotBeZero();\n    }\n    if (_feeRecipient == address(0)) {\n      revert FeeRecipientCannotBeZero();\n    }\n\n    _grantRole(DEFAULT_ADMIN_ROLE, managerAdmin);\n    _grantRole(MANAGER_ADMIN, managerAdmin);\n    _grantRole(PAUSER_ADMIN, pauser);\n    _setRoleAdmin(PAUSER_ADMIN, MANAGER_ADMIN);\n    _setRoleAdmin(PRICE_ID_SETTER_ROLE, MANAGER_ADMIN);\n    _setRoleAdmin(RELAYER_ROLE, MANAGER_ADMIN);\n\n    collateral = IERC20(_collateral);\n    rwa = IRWALike(_rwa);\n    feeRecipient = _feeRecipient;\n    assetSender = _assetSender;\n    minimumDepositAmount = _minimumDepositAmount;\n    minimumRedemptionAmount = _minimumRedemptionAmount;\n\n    decimalsMultiplier =\n      10 **\n        (IERC20Metadata(_rwa).decimals() -\n          IERC20Metadata(_collateral).decimals());\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                  Subscription/Redemption Functions\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Function used by users to request subscription to the fund\n   *\n   * @param amount The amount of collateral one wished to deposit\n   */\n  function requestSubscription(\n    uint256 amount\n  )\n    external\n    virtual\n    nonReentrant\n    ifNotPaused(subscriptionPaused)\n    checkRestrictions(msg.sender)\n  {\n    if (amount < minimumDepositAmount) {\n      revert DepositTooSmall();\n    }\n\n    uint256 feesInCollateral = _getMintFees(amount);\n    uint256 depositAmountAfterFee = amount - feesInCollateral;\n\n    // Link the depositor to their deposit ID\n    bytes32 depositId = bytes32(subscriptionRequestCounter++);\n    depositIdToDepositor[depositId] = Depositor(\n      msg.sender,\n      depositAmountAfterFee,\n      0\n    );\n\n    if (feesInCollateral > 0) {\n      collateral.safeTransferFrom(msg.sender, feeRecipient, feesInCollateral);\n    }\n\n    collateral.safeTransferFrom(\n      msg.sender,\n      assetRecipient,\n      depositAmountAfterFee\n    );\n\n    emit MintRequested(\n      msg.sender,\n      depositId,\n      amount,\n      depositAmountAfterFee,\n      feesInCollateral\n    );\n  }\n\n  /**\n   * @notice Function used to claim tokens corresponding to a deposit request\n   *\n   * @param depositIds An array containing the deposit Ids one wishes to claim\n   *\n   * @dev Implicitly does all transfer checks present in underlying `rwa`\n   * @dev The priceId corresponding to a given depositId must be set prior to\n   *      claiming a mint\n   */\n  function claimMint(\n    bytes32[] calldata depositIds\n  ) external virtual nonReentrant ifNotPaused(subscriptionPaused) {\n    uint256 depositsSize = depositIds.length;\n    for (uint256 i = 0; i < depositsSize; ++i) {\n      _claimMint(depositIds[i]);\n    }\n  }\n\n  /**\n   * @notice Internal claim mint helper\n   *\n   * @dev This function can be overriden to implement custom claiming logic\n   */\n  function _claimMint(bytes32 depositId) internal virtual {\n    Depositor memory depositor = depositIdToDepositor[depositId];\n    // Revert if priceId is not set\n    if (depositor.priceId == 0) {\n      revert PriceIdNotSet();\n    }\n\n    uint256 price = pricer.getPrice(depositor.priceId);\n    uint256 rwaOwed = _getMintAmountForPrice(\n      depositor.amountDepositedMinusFees,\n      price\n    );\n\n    delete depositIdToDepositor[depositId];\n    rwa.mint(depositor.user, rwaOwed);\n\n    emit MintCompleted(\n      depositor.user,\n      depositId,\n      rwaOwed,\n      depositor.amountDepositedMinusFees,\n      price,\n      depositor.priceId\n    );\n  }\n\n  /**\n   * @notice Function used by users to request a redemption from the fund\n   *\n   * @param amount The amount (in units of `rwa`) that a user wishes to redeem\n   *               from the fund\n   */\n  function requestRedemption(\n    uint256 amount\n  ) external virtual nonReentrant ifNotPaused(redemptionPaused) {\n    if (amount < minimumRedemptionAmount) {\n      revert RedemptionTooSmall();\n    }\n    bytes32 redemptionId = bytes32(redemptionRequestCounter++);\n    redemptionIdToRedeemer[redemptionId] = Redeemer(msg.sender, amount, 0);\n\n    rwa.burnFrom(msg.sender, amount);\n\n    emit RedemptionRequested(msg.sender, redemptionId, amount);\n  }\n\n  /**\n   * @notice Function to claim collateral corresponding to a redemption request\n   *\n   * @param redemptionIds an Array of redemption Id's which ought to fulfilled\n   *\n   * @dev Implicitly does all checks present in underlying `rwa`\n   * @dev The price Id corresponding to a redemptionId must be set prior to\n   *      claiming a redemption\n   */\n  function claimRedemption(\n    bytes32[] calldata redemptionIds\n  ) external virtual nonReentrant ifNotPaused(redemptionPaused) {\n    uint256 fees;\n    uint256 redemptionsSize = redemptionIds.length;\n    for (uint256 i = 0; i < redemptionsSize; ++i) {\n      Redeemer memory member = redemptionIdToRedeemer[redemptionIds[i]];\n      _checkRestrictions(member.user);\n      if (member.priceId == 0) {\n        // Then the price for this redemption has not been set\n        revert PriceIdNotSet();\n      }\n\n      // Calculate collateral due and fees\n      uint256 price = pricer.getPrice(member.priceId);\n      uint256 collateralDue = _getRedemptionAmountForRwa(\n        member.amountRwaTokenBurned,\n        price\n      );\n      uint256 fee = _getRedemptionFees(collateralDue);\n      uint256 collateralDuePostFees = collateralDue - fee;\n      fees += fee;\n\n      delete redemptionIdToRedeemer[redemptionIds[i]];\n\n      collateral.safeTransferFrom(\n        assetSender,\n        member.user,\n        collateralDuePostFees\n      );\n\n      emit RedemptionCompleted(\n        member.user,\n        redemptionIds[i],\n        member.amountRwaTokenBurned,\n        collateralDuePostFees,\n        price\n      );\n    }\n    if (fees > 0) {\n      collateral.safeTransferFrom(assetSender, feeRecipient, fees);\n    }\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                         Relayer Functions\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Adds a deposit proof to the contract\n   *\n   * @param txHash                The transaction hash of the deposit\n   * @param user                  The address of the user who made the deposit\n   * @param depositAmountAfterFee The amount of the deposit after fees\n   * @param feeAmount             The amount of the fees taken\n   * @param timestamp             The timestamp of the deposit\n   *\n   * @dev txHash is used as the depositId in storage\n   * @dev All amounts are in decimals of `collateral`\n   */\n  function addProof(\n    bytes32 txHash,\n    address user,\n    uint256 depositAmountAfterFee,\n    uint256 feeAmount,\n    uint256 timestamp\n  ) external override onlyRole(RELAYER_ROLE) checkRestrictions(user) {\n    if (depositIdToDepositor[txHash].user != address(0)) {\n      revert DepositProofAlreadyExists();\n    }\n    depositIdToDepositor[txHash] = Depositor(user, depositAmountAfterFee, 0);\n    emit DepositProofAdded(\n      txHash,\n      user,\n      depositAmountAfterFee,\n      feeAmount,\n      timestamp\n    );\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                           PriceId Setters\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Admin function to associate a depositId with a given Price Id\n   *\n   * @param depositIds an Array of deposit Ids to be associated\n   * @param priceIds   an Array of price Ids to be associated\n   *\n   * @dev Array size must match\n   */\n  function setPriceIdForDeposits(\n    bytes32[] calldata depositIds,\n    uint256[] calldata priceIds\n  ) external virtual onlyRole(PRICE_ID_SETTER_ROLE) {\n    uint256 depositsSize = depositIds.length;\n    if (depositsSize != priceIds.length) {\n      revert ArraySizeMismatch();\n    }\n    for (uint256 i = 0; i < depositsSize; ++i) {\n      if (depositIdToDepositor[depositIds[i]].user == address(0)) {\n        revert DepositorNull();\n      }\n      if (depositIdToDepositor[depositIds[i]].priceId != 0) {\n        revert PriceIdAlreadySet();\n      }\n      depositIdToDepositor[depositIds[i]].priceId = priceIds[i];\n      emit PriceIdSetForDeposit(depositIds[i], priceIds[i]);\n    }\n  }\n\n  /**\n   * @notice Admin function to associate redemptionId with a given priceId\n   *\n   * @param redemptionIds an Array of redemptionIds to associate\n   * @param priceIds  an Array of priceIds to associate\n   */\n  function setPriceIdForRedemptions(\n    bytes32[] calldata redemptionIds,\n    uint256[] calldata priceIds\n  ) external virtual onlyRole(PRICE_ID_SETTER_ROLE) {\n    uint256 redemptionsSize = redemptionIds.length;\n    if (redemptionsSize != priceIds.length) {\n      revert ArraySizeMismatch();\n    }\n    for (uint256 i = 0; i < redemptionsSize; ++i) {\n      if (redemptionIdToRedeemer[redemptionIds[i]].priceId != 0) {\n        revert PriceIdAlreadySet();\n      }\n      redemptionIdToRedeemer[redemptionIds[i]].priceId = priceIds[i];\n      emit PriceIdSetForRedemption(redemptionIds[i], priceIds[i]);\n    }\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                           Admin Setters\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Admin function to overwrite entries in the depoitIdToDepositor\n   *         mapping\n   *\n   * @param depositIdToOverwrite  The depositId of the entry we wish to\n   *                              overwrite\n   * @param user                  The user for the new entry\n   * @param depositAmountAfterFee The deposit value for the new entry\n   * @param priceId               The priceId to be associated with the new\n   *                              entry\n   */\n  function overwriteDepositor(\n    bytes32 depositIdToOverwrite,\n    address user,\n    uint256 depositAmountAfterFee,\n    uint256 priceId\n  ) external onlyRole(MANAGER_ADMIN) checkRestrictions(user) {\n    Depositor memory oldDepositor = depositIdToDepositor[depositIdToOverwrite];\n\n    depositIdToDepositor[depositIdToOverwrite] = Depositor(\n      user,\n      depositAmountAfterFee,\n      priceId\n    );\n\n    emit DepositorOverwritten(\n      depositIdToOverwrite,\n      oldDepositor.user,\n      user,\n      oldDepositor.priceId,\n      priceId,\n      oldDepositor.amountDepositedMinusFees,\n      depositAmountAfterFee\n    );\n  }\n\n  /**\n   * @notice Admin function to overwrite entries in the redemptionIdToRedeemer\n   *         mapping\n   *\n   * @param redemptionIdToOverwrite The redemptionId of the entry we wish to\n   *                                overwrite\n   * @param user                    The user for the new entry\n   * @param rwaTokenAmountBurned    The burn amount for the new entry\n   * @param priceId                 The priceID to be associated with the new\n   *                                entry\n   */\n  function overwriteRedeemer(\n    bytes32 redemptionIdToOverwrite,\n    address user,\n    uint256 rwaTokenAmountBurned,\n    uint256 priceId\n  ) external onlyRole(MANAGER_ADMIN) checkRestrictions(user) {\n    Redeemer memory oldRedeemer = redemptionIdToRedeemer[\n      redemptionIdToOverwrite\n    ];\n    redemptionIdToRedeemer[redemptionIdToOverwrite] = Redeemer(\n      user,\n      rwaTokenAmountBurned,\n      priceId\n    );\n    emit RedeemerOverwritten(\n      redemptionIdToOverwrite,\n      oldRedeemer.user,\n      user,\n      oldRedeemer.priceId,\n      priceId,\n      oldRedeemer.amountRwaTokenBurned,\n      rwaTokenAmountBurned\n    );\n  }\n\n  /**\n   * @notice Admin function to set the minimum amount to redeem\n   *\n   * @param _minimumRedemptionAmount The minimum amount required to submit a\n   *                                 redemption request\n   */\n  function setMinimumRedemptionAmount(\n    uint256 _minimumRedemptionAmount\n  ) external onlyRole(MANAGER_ADMIN) {\n    if (_minimumRedemptionAmount < BPS_DENOMINATOR) {\n      revert AmountTooSmall();\n    }\n    uint256 oldRedeemMinimum = minimumRedemptionAmount;\n    minimumRedemptionAmount = _minimumRedemptionAmount;\n    emit MinimumRedemptionAmountSet(oldRedeemMinimum, _minimumRedemptionAmount);\n  }\n\n  /**\n   * @notice Admin function to set the minimum amount required for a deposit\n   *\n   * @param minDepositAmount The minimum amount required to submit a deposit\n   *                         request\n   */\n  function setMinimumDepositAmount(\n    uint256 minDepositAmount\n  ) external onlyRole(MANAGER_ADMIN) {\n    if (minDepositAmount < BPS_DENOMINATOR) {\n      revert AmountTooSmall();\n    }\n    uint256 oldMinimumDepositAmount = minimumDepositAmount;\n    minimumDepositAmount = minDepositAmount;\n    emit MinimumDepositAmountSet(oldMinimumDepositAmount, minDepositAmount);\n  }\n\n  /**\n   * @notice Admin function to set the mint fee\n   *\n   * @param _mintFee The new mint fee specified in basis points\n   *\n   * @dev The maximum fee that can be set is 10_000 bps, or 100%\n   */\n  function setMintFee(uint256 _mintFee) external onlyRole(MANAGER_ADMIN) {\n    if (_mintFee > BPS_DENOMINATOR) {\n      revert FeeTooLarge();\n    }\n    uint256 oldMintFee = mintFee;\n    mintFee = _mintFee;\n    emit MintFeeSet(oldMintFee, _mintFee);\n  }\n\n  /**\n   * @notice Admin function to set the redeem fee\n   *\n   * @param _redemptionFee The new redeem fee specified in basis points\n   *\n   * @dev The maximum fee that can be set is 10_000 bps, or 100%\n   */\n  function setRedemptionFee(\n    uint256 _redemptionFee\n  ) external onlyRole(MANAGER_ADMIN) {\n    if (_redemptionFee > BPS_DENOMINATOR) {\n      revert FeeTooLarge();\n    }\n    uint256 oldRedeemFee = redemptionFee;\n    redemptionFee = _redemptionFee;\n    emit RedemptionFeeSet(oldRedeemFee, _redemptionFee);\n  }\n\n  /**\n   * @notice Admin function to set the address of the Pricer contract\n   *\n   * @param newPricer The address of the new pricer contract\n   */\n  function setPricer(address newPricer) external onlyRole(MANAGER_ADMIN) {\n    address oldPricer = address(pricer);\n    pricer = IPricerReader(newPricer);\n    emit NewPricerSet(oldPricer, newPricer);\n  }\n\n  /**\n   * @notice Admin function to set the address of `feeRecipient`\n   *\n   * @param newFeeRecipient The address of the new `feeRecipient`\n   */\n  function setFeeRecipient(\n    address newFeeRecipient\n  ) external onlyRole(MANAGER_ADMIN) {\n    address oldFeeRecipient = feeRecipient;\n    feeRecipient = newFeeRecipient;\n    emit FeeRecipientSet(oldFeeRecipient, feeRecipient);\n  }\n\n  /**\n   * @notice Admin function to set the address of `assetSender`\n   *\n   * @param newAssetSender The address of the new `assetSender`\n   */\n  function setAssetSender(\n    address newAssetSender\n  ) external onlyRole(MANAGER_ADMIN) {\n    address oldAssetSender = assetSender;\n    assetSender = newAssetSender;\n    emit AssetSenderSet(oldAssetSender, newAssetSender);\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                            Pause Utils\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Modifier to check if a feature is paused\n   *\n   * @param feature The feature to check if paused\n   */\n  modifier ifNotPaused(bool feature) {\n    if (feature) {\n      revert FeaturePaused();\n    }\n    _;\n  }\n\n  /**\n   * @notice Function to pause subscription to RWAHub\n   */\n  function pauseSubscription() external onlyRole(PAUSER_ADMIN) {\n    subscriptionPaused = true;\n    emit SubscriptionPaused(msg.sender);\n  }\n\n  /**\n   * @notice Function to pause redemptions to RWAHub\n   */\n  function pauseRedemption() external onlyRole(PAUSER_ADMIN) {\n    redemptionPaused = true;\n    emit RedemptionPaused(msg.sender);\n  }\n\n  /**\n   * @notice Function to unpause subscriptions to RWAHub\n   */\n  function unpauseSubscription() external onlyRole(MANAGER_ADMIN) {\n    subscriptionPaused = false;\n    emit SubscriptionUnpaused(msg.sender);\n  }\n\n  /**\n   * @notice Function to unpause redemptions to RWAHub\n   */\n  function unpauseRedemption() external onlyRole(MANAGER_ADMIN) {\n    redemptionPaused = false;\n    emit RedemptionUnpaused(msg.sender);\n  }\n\n  /*//////////////////////////////////////////////////////////////\n                      Check Restriction Utils\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Modifier to check restrictions status of an account\n   *\n   * @param account The account to check\n   */\n  modifier checkRestrictions(address account) {\n    _checkRestrictions(account);\n    _;\n  }\n\n  /**\n   * @notice internal function to check restriction status\n   *         of an address\n   *\n   * @param account The account to check restriction status for\n   *\n   * @dev This function is virtual to be overridden by child contract\n   *      to check restrictions on a more granular level\n   */\n  function _checkRestrictions(address account) internal view virtual;\n\n  /*//////////////////////////////////////////////////////////////\n                           Math Utils\n  //////////////////////////////////////////////////////////////*/\n\n  /**\n   * @notice Given amount of `collateral`, returns how much in fees\n   *         are owed\n   *\n   *\n   * @param collateralAmount Amount `collateral` to calculate fees\n   *                         (in decimals of `collateral`)\n   */\n  function _getMintFees(\n    uint256 collateralAmount\n  ) internal view returns (uint256) {\n    return (collateralAmount * mintFee) / BPS_DENOMINATOR;\n  }\n\n  /**\n   * @notice Given amount of `collateral`, returns how much in fees\n   *         are owed\n   *\n   * @param collateralAmount Amount of `collateral` to calculate fees\n   *                         (in decimals of `collateral`)\n   */\n  function _getRedemptionFees(\n    uint256 collateralAmount\n  ) internal view returns (uint256) {\n    return (collateralAmount * redemptionFee) / BPS_DENOMINATOR;\n  }\n\n  /**\n   * @notice Given a deposit amount and priceId, returns the amount\n   *         of `rwa` due\n   *\n   * @param depositAmt The amount deposited in units of `collateral`\n   * @param price      The price associated with this deposit\n   */\n  function _getMintAmountForPrice(\n    uint256 depositAmt,\n    uint256 price\n  ) internal view returns (uint256 rwaAmountOut) {\n    uint256 amountE36 = _scaleUp(depositAmt) * 1e18;\n    // Will revert with div by 0 if price not defined for a priceId\n    rwaAmountOut = amountE36 / price;\n  }\n\n  /**\n   * @notice Given a redemption amount and a priceId, returns the amount\n   *         of `collateral` due\n   *\n   * @param rwaTokenAmountBurned The amount of `rwa` burned for a redemption\n   * @param price                The price associated with this redemption\n   */\n  function _getRedemptionAmountForRwa(\n    uint256 rwaTokenAmountBurned,\n    uint256 price\n  ) internal view returns (uint256 collateralOwed) {\n    uint256 amountE36 = rwaTokenAmountBurned * price;\n    collateralOwed = _scaleDown(amountE36 / 1e18);\n  }\n\n  /**\n   * @notice Scale provided amount up by `decimalsMultiplier`\n   *\n   * @dev This helper is used for converting the collateral's decimals\n   *      representation to the RWA amount decimals representation.\n   */\n  function _scaleUp(uint256 amount) internal view returns (uint256) {\n    return amount * decimalsMultiplier;\n  }\n\n  /**\n   * @notice Scale provided amount down by `decimalsMultiplier`\n   *\n   * @dev This helper is used for converting `rwa`'s decimal\n   *      representation to the `collateral`'s decimal representation\n   */\n  function _scaleDown(uint256 amount) internal view returns (uint256) {\n    return amount / decimalsMultiplier;\n  }\n}\n"},{"file_path":"contracts/RWAHubOffChainRedemptions.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\n\npragma solidity 0.8.16;\n\nimport \"contracts/RWAHub.sol\";\nimport \"contracts/interfaces/IRWAHubOffChainRedemptions.sol\";\n\nabstract contract RWAHubOffChainRedemptions is\n  RWAHub,\n  IRWAHubOffChainRedemptions\n{\n  // To enable and disable off chain redemptions\n  bool public offChainRedemptionPaused;\n\n  // Minimum off chain redemption amount\n  uint256 public minimumOffChainRedemptionAmount;\n\n  constructor(\n    address _collateral,\n    address _rwa,\n    address managerAdmin,\n    address pauser,\n    address _assetSender,\n    address _feeRecipient,\n    uint256 _minimumDepositAmount,\n    uint256 _minimumRedemptionAmount\n  )\n    RWAHub(\n      _collateral,\n      _rwa,\n      managerAdmin,\n      pauser,\n      _assetSender,\n      _feeRecipient,\n      _minimumDepositAmount,\n      _minimumRedemptionAmount\n    )\n  {\n    // Default to the same minimum redemption amount as for On-Chain\n    // redemptions.\n    minimumOffChainRedemptionAmount = _minimumRedemptionAmount;\n  }\n\n  /**\n   * @notice Request a redemption to be serviced off chain.\n   *\n   * @param amountRWATokenToRedeem The requested redemption amount\n   * @param offChainDestination    A hash of the destination to which\n   *                               the request should be serviced to.\n   */\n  function requestRedemptionServicedOffchain(\n    uint256 amountRWATokenToRedeem,\n    bytes32 offChainDestination\n  ) external nonReentrant ifNotPaused(offChainRedemptionPaused) {\n    if (amountRWATokenToRedeem < minimumOffChainRedemptionAmount) {\n      revert RedemptionTooSmall();\n    }\n\n    bytes32 redemptionId = bytes32(redemptionRequestCounter++);\n\n    rwa.burnFrom(msg.sender, amountRWATokenToRedeem);\n\n    emit RedemptionRequestedServicedOffChain(\n      msg.sender,\n      redemptionId,\n      amountRWATokenToRedeem,\n      offChainDestination\n    );\n  }\n\n  /**\n   * @notice Function to pause off chain redemptoins\n   */\n  function pauseOffChainRedemption() external onlyRole(PAUSER_ADMIN) {\n    offChainRedemptionPaused = true;\n    emit OffChainRedemptionPaused(msg.sender);\n  }\n\n  /**\n   * @notice Function to unpause off chain redemptoins\n   */\n  function unpauseOffChainRedemption() external onlyRole(MANAGER_ADMIN) {\n    offChainRedemptionPaused = false;\n    emit OffChainRedemptionUnpaused(msg.sender);\n  }\n\n  /**\n   * @notice Admin Function to set the minimum off chain redemption amount\n   *\n   * @param _minimumOffChainRedemptionAmount The new minimum off chain\n   *                                         redemption amount\n   */\n  function setOffChainRedemptionMinimum(\n    uint256 _minimumOffChainRedemptionAmount\n  ) external onlyRole(MANAGER_ADMIN) {\n    uint256 oldMinimum = minimumOffChainRedemptionAmount;\n    minimumOffChainRedemptionAmount = _minimumOffChainRedemptionAmount;\n    emit OffChainRedemptionMinimumSet(\n      oldMinimum,\n      _minimumOffChainRedemptionAmount\n    );\n  }\n}\n"},{"file_path":"contracts/external/chainalysis/ISanctionsList.sol","source_code":"/// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.16;\n\ninterface ISanctionsList {\n  function isSanctioned(address addr) external view returns (bool);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControl.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/Context.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/Strings.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/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, _msgSender());\n    _;\n  }\n\n  /**\n   * @dev See {IERC165-supportsInterface}.\n   */\n  function supportsInterface(bytes4 interfaceId)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return\n      interfaceId == type(IAccessControl).interfaceId ||\n      super.supportsInterface(interfaceId);\n  }\n\n  /**\n   * @dev Returns `true` if `account` has been granted `role`.\n   */\n  function hasRole(bytes32 role, address account)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return _roles[role].members[account];\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(uint160(account), 20),\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)\n    public\n    view\n    virtual\n    override\n    returns (bytes32)\n  {\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  function grantRole(bytes32 role, address account)\n    public\n    virtual\n    override\n    onlyRole(getRoleAdmin(role))\n  {\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  function revokeRole(bytes32 role, address account)\n    public\n    virtual\n    override\n    onlyRole(getRoleAdmin(role))\n  {\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  function renounceRole(bytes32 role, address account) public virtual override {\n    require(\n      account == _msgSender(),\n      \"AccessControl: can only renounce roles for self\"\n    );\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   * [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  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  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":"contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol\";\nimport \"contracts/external/openzeppelin/contracts/access/AccessControl.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is\n  IAccessControlEnumerable,\n  AccessControl\n{\n  using EnumerableSet for EnumerableSet.AddressSet;\n\n  mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n  /**\n   * @dev See {IERC165-supportsInterface}.\n   */\n  function supportsInterface(bytes4 interfaceId)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return\n      interfaceId == type(IAccessControlEnumerable).interfaceId ||\n      super.supportsInterface(interfaceId);\n  }\n\n  /**\n   * @dev Returns one of the accounts that have `role`. `index` must be a\n   * value between 0 and {getRoleMemberCount}, non-inclusive.\n   *\n   * Role bearers are not sorted in any particular way, and their ordering may\n   * change at any point.\n   *\n   * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n   * you perform all queries on the same block. See the following\n   * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n   * for more information.\n   */\n  function getRoleMember(bytes32 role, uint256 index)\n    public\n    view\n    virtual\n    override\n    returns (address)\n  {\n    return _roleMembers[role].at(index);\n  }\n\n  /**\n   * @dev Returns the number of accounts that have `role`. Can be used\n   * together with {getRoleMember} to enumerate all bearers of a role.\n   */\n  function getRoleMemberCount(bytes32 role)\n    public\n    view\n    virtual\n    override\n    returns (uint256)\n  {\n    return _roleMembers[role].length();\n  }\n\n  /**\n   * @dev Overload {_grantRole} to track enumerable memberships\n   */\n  function _grantRole(bytes32 role, address account) internal virtual override {\n    super._grantRole(role, account);\n    _roleMembers[role].add(account);\n  }\n\n  /**\n   * @dev Overload {_revokeRole} to track enumerable memberships\n   */\n  function _revokeRole(bytes32 role, address account)\n    internal\n    virtual\n    override\n  {\n    super._revokeRole(role, account);\n    _roleMembers[role].remove(account);\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/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(\n    bytes32 indexed role,\n    bytes32 indexed previousAdminRole,\n    bytes32 indexed newAdminRole\n  );\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(\n    bytes32 indexed role,\n    address indexed account,\n    address indexed sender\n  );\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(\n    bytes32 indexed role,\n    address indexed account,\n    address indexed sender\n  );\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":"contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n  /**\n   * @dev Returns one of the accounts that have `role`. `index` must be a\n   * value between 0 and {getRoleMemberCount}, non-inclusive.\n   *\n   * Role bearers are not sorted in any particular way, and their ordering may\n   * change at any point.\n   *\n   * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n   * you perform all queries on the same block. See the following\n   * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n   * for more information.\n   */\n  function getRoleMember(bytes32 role, uint256 index)\n    external\n    view\n    returns (address);\n\n  /**\n   * @dev Returns the number of accounts that have `role`. Can be used\n   * together with {getRoleMember} to enumerate all bearers of a role.\n   */\n  function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n  // Booleans are more expensive than uint256 or any type that takes up a full\n  // word because each write operation emits an extra SLOAD to first read the\n  // slot's contents, replace the bits taken up by the boolean, and then write\n  // back. This is the compiler's defense against contract upgrades and\n  // pointer aliasing, and it cannot be disabled.\n\n  // The values being non-zero value makes deployment a bit more expensive,\n  // but in exchange the refund on every call to nonReentrant will be lower in\n  // amount. Since refunds are capped to a percentage of the total\n  // transaction's gas, it is best to keep them low in cases like this one, to\n  // increase the likelihood of the full refund coming into effect.\n  uint256 private constant _NOT_ENTERED = 1;\n  uint256 private constant _ENTERED = 2;\n\n  uint256 private _status;\n\n  constructor() {\n    _status = _NOT_ENTERED;\n  }\n\n  /**\n   * @dev Prevents a contract from calling itself, directly or indirectly.\n   * Calling a `nonReentrant` function from another `nonReentrant`\n   * function is not supported. It is possible to prevent this from happening\n   * by making the `nonReentrant` function external, and making it call a\n   * `private` function that does the actual work.\n   */\n  modifier nonReentrant() {\n    // On the first call to nonReentrant, _notEntered will be true\n    require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n    // Any calls to nonReentrant after this point will fail\n    _status = _ENTERED;\n\n    _;\n\n    // By storing the original value once again, a refund is triggered (see\n    // https://eips.ethereum.org/EIPS/eip-2200)\n    _status = _NOT_ENTERED;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/token/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.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 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)\n    external\n    view\n    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  /**\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":"contracts/external/openzeppelin/contracts/token/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n  /**\n   * @dev Returns the name of the token.\n   */\n  function name() external view returns (string memory);\n\n  /**\n   * @dev Returns the symbol of the token.\n   */\n  function symbol() external view returns (string memory);\n\n  /**\n   * @dev Returns the decimals places of the token.\n   */\n  function decimals() external view returns (uint8);\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/token/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\nimport \"contracts/external/openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n  using Address for address;\n\n  function safeTransfer(\n    IERC20 token,\n    address to,\n    uint256 value\n  ) internal {\n    _callOptionalReturn(\n      token,\n      abi.encodeWithSelector(token.transfer.selector, to, value)\n    );\n  }\n\n  function safeTransferFrom(\n    IERC20 token,\n    address from,\n    address to,\n    uint256 value\n  ) internal {\n    _callOptionalReturn(\n      token,\n      abi.encodeWithSelector(token.transferFrom.selector, from, to, value)\n    );\n  }\n\n  /**\n   * @dev Deprecated. This function has issues similar to the ones found in\n   * {IERC20-approve}, and its usage is discouraged.\n   *\n   * Whenever possible, use {safeIncreaseAllowance} and\n   * {safeDecreaseAllowance} instead.\n   */\n  function safeApprove(\n    IERC20 token,\n    address spender,\n    uint256 value\n  ) internal {\n    // safeApprove should only be called when setting an initial allowance,\n    // or when resetting it to zero. To increase and decrease it, use\n    // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n    require(\n      (value == 0) || (token.allowance(address(this), spender) == 0),\n      \"SafeERC20: approve from non-zero to non-zero allowance\"\n    );\n    _callOptionalReturn(\n      token,\n      abi.encodeWithSelector(token.approve.selector, spender, value)\n    );\n  }\n\n  function safeIncreaseAllowance(\n    IERC20 token,\n    address spender,\n    uint256 value\n  ) internal {\n    uint256 newAllowance = token.allowance(address(this), spender) + value;\n    _callOptionalReturn(\n      token,\n      abi.encodeWithSelector(token.approve.selector, spender, newAllowance)\n    );\n  }\n\n  function safeDecreaseAllowance(\n    IERC20 token,\n    address spender,\n    uint256 value\n  ) internal {\n    unchecked {\n      uint256 oldAllowance = token.allowance(address(this), spender);\n      require(\n        oldAllowance >= value,\n        \"SafeERC20: decreased allowance below zero\"\n      );\n      uint256 newAllowance = oldAllowance - value;\n      _callOptionalReturn(\n        token,\n        abi.encodeWithSelector(token.approve.selector, spender, newAllowance)\n      );\n    }\n  }\n\n  /**\n   * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n   * on the return value: the return value is optional (but if data is returned, it must not be false).\n   * @param token The token targeted by the call.\n   * @param data The call data (encoded using abi.encode or one of its variants).\n   */\n  function _callOptionalReturn(IERC20 token, bytes memory data) private {\n    // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n    // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n    // the target address contains contract code and also asserts for success in the low-level call.\n\n    bytes memory returndata =\n      address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n    if (returndata.length > 0) {\n      // Return data is optional\n      require(\n        abi.decode(returndata, (bool)),\n        \"SafeERC20: ERC20 operation did not succeed\"\n      );\n    }\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n  /**\n   * @dev Returns true if `account` is a contract.\n   *\n   * [IMPORTANT]\n   * ====\n   * It is unsafe to assume that an address for which this function returns\n   * false is an externally-owned account (EOA) and not a contract.\n   *\n   * Among others, `isContract` will return false for the following\n   * types of addresses:\n   *\n   *  - an externally-owned account\n   *  - a contract in construction\n   *  - an address where a contract will be created\n   *  - an address where a contract lived, but was destroyed\n   * ====\n   *\n   * [IMPORTANT]\n   * ====\n   * You shouldn't rely on `isContract` to protect against flash loan attacks!\n   *\n   * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n   * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n   * constructor.\n   * ====\n   */\n  function isContract(address account) internal view returns (bool) {\n    // This method relies on extcodesize/address.code.length, which returns 0\n    // for contracts in construction, since the code is only stored at the end\n    // of the constructor execution.\n\n    return account.code.length > 0;\n  }\n\n  /**\n   * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n   * `recipient`, forwarding all available gas and reverting on errors.\n   *\n   * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n   * of certain opcodes, possibly making contracts go over the 2300 gas limit\n   * imposed by `transfer`, making them unable to receive funds via\n   * `transfer`. {sendValue} removes this limitation.\n   *\n   * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n   *\n   * IMPORTANT: because control is transferred to `recipient`, care must be\n   * taken to not create reentrancy vulnerabilities. Consider using\n   * {ReentrancyGuard} or the\n   * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n   */\n  function sendValue(address payable recipient, uint256 amount) internal {\n    require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n    (bool success, ) = recipient.call{value: amount}(\"\");\n    require(\n      success,\n      \"Address: unable to send value, recipient may have reverted\"\n    );\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)\n    internal\n    returns (bytes memory)\n  {\n    return functionCall(target, data, \"Address: low-level call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n   * `errorMessage` as a fallback revert reason when `target` reverts.\n   *\n   * _Available since v3.1._\n   */\n  function functionCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    return functionCallWithValue(target, data, 0, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but also transferring `value` wei to `target`.\n   *\n   * Requirements:\n   *\n   * - the calling contract must have an ETH balance of at least `value`.\n   * - the called Solidity function must be `payable`.\n   *\n   * _Available since v3.1._\n   */\n  function functionCallWithValue(\n    address target,\n    bytes memory data,\n    uint256 value\n  ) internal returns (bytes memory) {\n    return\n      functionCallWithValue(\n        target,\n        data,\n        value,\n        \"Address: low-level call with value failed\"\n      );\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(\n      address(this).balance >= value,\n      \"Address: insufficient balance for call\"\n    );\n    require(isContract(target), \"Address: call to non-contract\");\n\n    (bool success, bytes memory returndata) = target.call{value: value}(data);\n    return verifyCallResult(success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(address target, bytes memory data)\n    internal\n    view\n    returns (bytes memory)\n  {\n    return\n      functionStaticCall(target, data, \"Address: low-level static call failed\");\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n   * but performing a static call.\n   *\n   * _Available since v3.3._\n   */\n  function functionStaticCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal view returns (bytes memory) {\n    require(isContract(target), \"Address: static call to non-contract\");\n\n    (bool success, bytes memory returndata) = target.staticcall(data);\n    return verifyCallResult(success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n   * but performing a delegate call.\n   *\n   * _Available since v3.4._\n   */\n  function functionDelegateCall(address target, bytes memory data)\n    internal\n    returns (bytes memory)\n  {\n    return\n      functionDelegateCall(\n        target,\n        data,\n        \"Address: low-level delegate call failed\"\n      );\n  }\n\n  /**\n   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n   * but performing a delegate call.\n   *\n   * _Available since v3.4._\n   */\n  function functionDelegateCall(\n    address target,\n    bytes memory data,\n    string memory errorMessage\n  ) internal returns (bytes memory) {\n    require(isContract(target), \"Address: delegate call to non-contract\");\n\n    (bool success, bytes memory returndata) = target.delegatecall(data);\n    return verifyCallResult(success, returndata, errorMessage);\n  }\n\n  /**\n   * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n   * revert reason using the provided one.\n   *\n   * _Available since v4.3._\n   */\n  function verifyCallResult(\n    bool success,\n    bytes memory returndata,\n    string memory errorMessage\n  ) internal pure returns (bytes memory) {\n    if (success) {\n      return returndata;\n    } else {\n      // Look for revert reason and bubble it up if present\n      if (returndata.length > 0) {\n        // The easiest way to bubble the revert reason is using memory via assembly\n\n        assembly {\n          let returndata_size := mload(returndata)\n          revert(add(32, returndata), returndata_size)\n        }\n      } else {\n        revert(errorMessage);\n      }\n    }\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/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":"contracts/external/openzeppelin/contracts/utils/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 \"contracts/external/openzeppelin/contracts/utils/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)\n    public\n    view\n    virtual\n    override\n    returns (bool)\n  {\n    return interfaceId == type(IERC165).interfaceId;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n  // To implement this library for multiple types with as little code\n  // repetition as possible, we write it in terms of a generic Set type with\n  // bytes32 values.\n  // The Set implementation uses private functions, and user-facing\n  // implementations (such as AddressSet) are just wrappers around the\n  // underlying Set.\n  // This means that we can only create new EnumerableSets for types that fit\n  // in bytes32.\n\n  struct Set {\n    // Storage of set values\n    bytes32[] _values;\n    // Position of the value in the `values` array, plus 1 because index 0\n    // means a value is not in the set.\n    mapping(bytes32 => uint256) _indexes;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function _add(Set storage set, bytes32 value) private returns (bool) {\n    if (!_contains(set, value)) {\n      set._values.push(value);\n      // The value is stored at length-1, but we add 1 to all indexes\n      // and use 0 as a sentinel value\n      set._indexes[value] = set._values.length;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function _remove(Set storage set, bytes32 value) private returns (bool) {\n    // We read and store the value's index to prevent multiple reads from the same storage slot\n    uint256 valueIndex = set._indexes[value];\n\n    if (valueIndex != 0) {\n      // Equivalent to contains(set, value)\n      // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n      // the array, and then remove the last element (sometimes called as 'swap and pop').\n      // This modifies the order of the array, as noted in {at}.\n\n      uint256 toDeleteIndex = valueIndex - 1;\n      uint256 lastIndex = set._values.length - 1;\n\n      if (lastIndex != toDeleteIndex) {\n        bytes32 lastvalue = set._values[lastIndex];\n\n        // Move the last value to the index where the value to delete is\n        set._values[toDeleteIndex] = lastvalue;\n        // Update the index for the moved value\n        set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n      }\n\n      // Delete the slot where the moved value was stored\n      set._values.pop();\n\n      // Delete the index for the deleted slot\n      delete set._indexes[value];\n\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function _contains(Set storage set, bytes32 value)\n    private\n    view\n    returns (bool)\n  {\n    return set._indexes[value] != 0;\n  }\n\n  /**\n   * @dev Returns the number of values on the set. O(1).\n   */\n  function _length(Set storage set) private view returns (uint256) {\n    return set._values.length;\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function _at(Set storage set, uint256 index) private view returns (bytes32) {\n    return set._values[index];\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function _values(Set storage set) private view returns (bytes32[] memory) {\n    return set._values;\n  }\n\n  // Bytes32Set\n\n  struct Bytes32Set {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n    return _add(set._inner, value);\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(Bytes32Set storage set, bytes32 value)\n    internal\n    returns (bool)\n  {\n    return _remove(set._inner, value);\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(Bytes32Set storage set, bytes32 value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, value);\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(Bytes32Set storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(Bytes32Set storage set, uint256 index)\n    internal\n    view\n    returns (bytes32)\n  {\n    return _at(set._inner, index);\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(Bytes32Set storage set)\n    internal\n    view\n    returns (bytes32[] memory)\n  {\n    return _values(set._inner);\n  }\n\n  // AddressSet\n\n  struct AddressSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(AddressSet storage set, address value) internal returns (bool) {\n    return _add(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(AddressSet storage set, address value)\n    internal\n    returns (bool)\n  {\n    return _remove(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(AddressSet storage set, address value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, bytes32(uint256(uint160(value))));\n  }\n\n  /**\n   * @dev Returns the number of values in the set. O(1).\n   */\n  function length(AddressSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(AddressSet storage set, uint256 index)\n    internal\n    view\n    returns (address)\n  {\n    return address(uint160(uint256(_at(set._inner, index))));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(AddressSet storage set)\n    internal\n    view\n    returns (address[] memory)\n  {\n    bytes32[] memory store = _values(set._inner);\n    address[] memory result;\n\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n\n  // UintSet\n\n  struct UintSet {\n    Set _inner;\n  }\n\n  /**\n   * @dev Add a value to a set. O(1).\n   *\n   * Returns true if the value was added to the set, that is if it was not\n   * already present.\n   */\n  function add(UintSet storage set, uint256 value) internal returns (bool) {\n    return _add(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Removes a value from a set. O(1).\n   *\n   * Returns true if the value was removed from the set, that is if it was\n   * present.\n   */\n  function remove(UintSet storage set, uint256 value) internal returns (bool) {\n    return _remove(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns true if the value is in the set. O(1).\n   */\n  function contains(UintSet storage set, uint256 value)\n    internal\n    view\n    returns (bool)\n  {\n    return _contains(set._inner, bytes32(value));\n  }\n\n  /**\n   * @dev Returns the number of values on the set. O(1).\n   */\n  function length(UintSet storage set) internal view returns (uint256) {\n    return _length(set._inner);\n  }\n\n  /**\n   * @dev Returns the value stored at position `index` in the set. O(1).\n   *\n   * Note that there are no guarantees on the ordering of values inside the\n   * array, and it may change when more values are added or removed.\n   *\n   * Requirements:\n   *\n   * - `index` must be strictly less than {length}.\n   */\n  function at(UintSet storage set, uint256 index)\n    internal\n    view\n    returns (uint256)\n  {\n    return uint256(_at(set._inner, index));\n  }\n\n  /**\n   * @dev Return the entire set in an array\n   *\n   * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n   * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n   * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n   * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n   */\n  function values(UintSet storage set)\n    internal\n    view\n    returns (uint256[] memory)\n  {\n    bytes32[] memory store = _values(set._inner);\n    uint256[] memory result;\n\n    assembly {\n      result := store\n    }\n\n    return result;\n  }\n}\n"},{"file_path":"contracts/external/openzeppelin/contracts/utils/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":"contracts/external/openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n  bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\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    // Inspired by OraclizeAPI's implementation - MIT licence\n    // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n    if (value == 0) {\n      return \"0\";\n    }\n    uint256 temp = value;\n    uint256 digits;\n    while (temp != 0) {\n      digits++;\n      temp /= 10;\n    }\n    bytes memory buffer = new bytes(digits);\n    while (value != 0) {\n      digits -= 1;\n      buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n      value /= 10;\n    }\n    return string(buffer);\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    if (value == 0) {\n      return \"0x00\";\n    }\n    uint256 temp = value;\n    uint256 length = 0;\n    while (temp != 0) {\n      length++;\n      temp >>= 8;\n    }\n    return toHexString(value, length);\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)\n    internal\n    pure\n    returns (string memory)\n  {\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] = _HEX_SYMBOLS[value & 0xf];\n      value >>= 4;\n    }\n    require(value == 0, \"Strings: hex length insufficient\");\n    return string(buffer);\n  }\n}\n"},{"file_path":"contracts/interfaces/IBlocklist.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\ninterface IBlocklist {\n  function addToBlocklist(address[] calldata accounts) external;\n\n  function removeFromBlocklist(address[] calldata accounts) external;\n\n  function isBlocked(address account) external view returns (bool);\n\n  /**\n   * @notice Event emitted when addresses are added to the blocklist\n   *\n   * @param accounts The addresses that were added to the blocklist\n   */\n  event BlockedAddressesAdded(address[] accounts);\n\n  /**\n   * @notice Event emitted when addresses are removed from the blocklist\n   *\n   * @param accounts The addresses that were removed from the blocklist\n   */\n  event BlockedAddressesRemoved(address[] accounts);\n}\n"},{"file_path":"contracts/interfaces/IBlocklistClient.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/interfaces/IBlocklist.sol\";\n\n/**\n * @title IBlocklistClient\n * @author Ondo Finance\n * @notice The client interface for the Blocklist contract.\n */\ninterface IBlocklistClient {\n  /// @notice Returns reference to the blocklist that this client queries\n  function blocklist() external view returns (IBlocklist);\n\n  /// @notice Sets the blocklist reference\n  function setBlocklist(address registry) external;\n\n  /// @notice Error for when caller attempts to set the blocklist reference\n  ///         to the zero address\n  error BlocklistZeroAddress();\n\n  /// @notice Error for when caller attempts to perform action on a blocked\n  ///         account\n  error BlockedAccount();\n\n  /**\n   * @dev Event for when the blocklist reference is set\n   *\n   * @param oldBlocklist The old blocklist\n   * @param newBlocklist The new blocklist\n   */\n  event BlocklistSet(address oldBlocklist, address newBlocklist);\n}\n"},{"file_path":"contracts/interfaces/IPricerReader.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\ninterface IPricerReader {\n  /**\n   * @notice Gets the latest price of the asset\n   *\n   * @return uint256 The latest price of the asset\n   */\n  function getLatestPrice() external view returns (uint256);\n\n  /**\n   * @notice Gets the price of the asset at a specific priceId\n   *\n   * @param priceId The priceId at which to get the price\n   *\n   * @return uint256 The price of the asset with the given priceId\n   */\n  function getPrice(uint256 priceId) external view returns (uint256);\n}\n"},{"file_path":"contracts/interfaces/IRWAHub.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\ninterface IRWAHub {\n  // Struct to contain the deposit information for a given depositId\n  struct Depositor {\n    address user;\n    uint256 amountDepositedMinusFees;\n    uint256 priceId;\n  }\n\n  // Struc to contain withdrawal infromation for a given redemptionId\n  struct Redeemer {\n    address user;\n    uint256 amountRwaTokenBurned;\n    uint256 priceId;\n  }\n\n  function requestSubscription(uint256 amount) external;\n\n  function claimMint(bytes32[] calldata depositIds) external;\n\n  function requestRedemption(uint256 amount) external;\n\n  function claimRedemption(bytes32[] calldata redemptionIds) external;\n\n  function addProof(\n    bytes32 txHash,\n    address user,\n    uint256 depositAmountAfterFee,\n    uint256 feeAmount,\n    uint256 timestamp\n  ) external;\n\n  function setPriceIdForDeposits(\n    bytes32[] calldata depositIds,\n    uint256[] calldata priceIds\n  ) external;\n\n  function setPriceIdForRedemptions(\n    bytes32[] calldata redemptionIds,\n    uint256[] calldata priceIds\n  ) external;\n\n  function setPricer(address newPricer) external;\n\n  function overwriteDepositor(\n    bytes32 depositIdToOverride,\n    address user,\n    uint256 depositAmountAfterFee,\n    uint256 priceId\n  ) external;\n\n  function overwriteRedeemer(\n    bytes32 redemptionIdToOverride,\n    address user,\n    uint256 rwaTokenAmountBurned,\n    uint256 priceId\n  ) external;\n\n  /**\n   * @notice Event emitted when fee recipient is set\n   *\n   * @param oldFeeRecipient Old fee recipient\n   * @param newFeeRecipient New fee recipient\n   */\n  event FeeRecipientSet(address oldFeeRecipient, address newFeeRecipient);\n\n  /**\n   * @notice Event emitted when the assetSender is changed\n   *\n   * @param oldAssetSender The address of the old assetSender\n   * @param newAssetSender The address of the new assetSender\n   */\n  event AssetSenderSet(address oldAssetSender, address newAssetSender);\n\n  /**\n   * @notice Event emitted when minimum deposit amount is set\n   *\n   * @param oldMinimum Old minimum\n   * @param newMinimum New minimum\n   *\n   * @dev See inheriting contract for decimals representation\n   */\n  event MinimumDepositAmountSet(uint256 oldMinimum, uint256 newMinimum);\n\n  /**\n   * @notice Event emitted when a new redeem minimum is set.\n   *         All units are in 1e18\n   *\n   * @param oldRedemptionMin The old redeem minimum value\n   * @param newRedemptionMin The new redeem minimum value\n   */\n  event MinimumRedemptionAmountSet(\n    uint256 oldRedemptionMin,\n    uint256 newRedemptionMin\n  );\n\n  /**\n   * @notice Event emitted when mint fee is set\n   *\n   * @param oldFee Old fee\n   * @param newFee New fee\n   *\n   * @dev See inheriting contract for decimals representation\n   */\n  event MintFeeSet(uint256 oldFee, uint256 newFee);\n\n  /**\n   * @notice Event emitted when redeem fee is set\n   *\n   * @param oldFee Old fee\n   * @param newFee New fee\n   *\n   * @dev see inheriting contract for decimal representation\n   */\n  event RedemptionFeeSet(uint256 oldFee, uint256 newFee);\n\n  /**\n   * @notice Event emitted when redemption request is submitted\n   *\n   * @param user         The user submitting the redemption request\n   * @param redemptionId The id corresponding to a given redemption\n   * @param rwaAmountIn  The amount of cash being burned\n   */\n  event RedemptionRequested(\n    address indexed user,\n    bytes32 indexed redemptionId,\n    uint256 rwaAmountIn\n  );\n\n  /**\n   * @notice Event emitted when a mint request is submitted\n   *\n   * @param user                      The user requesting to mint\n   * @param depositId                 The depositId of the request\n   * @param collateralAmountDeposited The total amount deposited\n   * @param depositAmountAfterFee     The value deposited - fee\n   * @param feeAmount                 The fee amount taken\n   *                                  (units of collateral)\n   */\n  event MintRequested(\n    address indexed user,\n    bytes32 indexed depositId,\n    uint256 collateralAmountDeposited,\n    uint256 depositAmountAfterFee,\n    uint256 feeAmount\n  );\n\n  /**\n   * @notice Event emitted when a redemption request is completed\n   *\n   * @param user                     The address of the user getting the funds\n   * @param redemptionId             The id corresponding to a given redemption\n   *                                 requested\n   * @param rwaAmountRequested       Amount of RWA originally requested by the user\n   * @param collateralAmountReturned Amount of collateral received by the user\n   * @param price                    The price at which the redemption was\n   *                                 serviced at\n   */\n  event RedemptionCompleted(\n    address indexed user,\n    bytes32 indexed redemptionId,\n    uint256 rwaAmountRequested,\n    uint256 collateralAmountReturned,\n    uint256 price\n  );\n\n  /**\n   * @notice Event emitted when a Mint request is completed\n   *\n   * @param user                      The address of the user getting the funds\n   * @param depositId                 The depositId of the mint request\n   * @param rwaAmountOut              The amount of RWA token minted to the\n   *                                  user\n   * @param collateralAmountDeposited The amount of collateral deposited\n   * @param price                     The price set for the given\n   *                                  deposit id\n   * @param priceId                   The priceId used to determine price\n   */\n  event MintCompleted(\n    address indexed user,\n    bytes32 indexed depositId,\n    uint256 rwaAmountOut,\n    uint256 collateralAmountDeposited,\n    uint256 price,\n    uint256 priceId\n  );\n\n  /**\n   * @notice Event emitted when a deposit has its corresponding priceId set\n   *\n   * @param depositIdSet The Deposit Id for which the price Id is being set\n   * @param priceIdSet   The price Id being associate with a deposit Id\n   */\n  event PriceIdSetForDeposit(\n    bytes32 indexed depositIdSet,\n    uint256 indexed priceIdSet\n  );\n\n  /**\n   * @notice Event Emitted when a redemption has its corresponding priceId set\n   *\n   * @param redemptionIdSet The Redemption Id for which the price Id is being\n   *                        set\n   * @param priceIdSet      The Price Id being associated with a redemption Id\n   */\n  event PriceIdSetForRedemption(\n    bytes32 indexed redemptionIdSet,\n    uint256 indexed priceIdSet\n  );\n\n  /**\n   * @notice Event emitted when a new Pricer contract is set\n   *\n   * @param oldPricer The address of the old pricer contract\n   * @param newPricer The address of the new pricer contract\n   */\n  event NewPricerSet(address oldPricer, address newPricer);\n\n  /**\n   * @notice Event emitted when deposit proof has been added\n   *\n   * @param txHash                Tx hash of the deposit\n   * @param user                  Address of the user who made the deposit\n   * @param depositAmountAfterFee Amount of the deposit after fees\n   * @param feeAmount             Amount of fees taken\n   * @param timestamp             Timestamp of the deposit\n   */\n  event DepositProofAdded(\n    bytes32 indexed txHash,\n    address indexed user,\n    uint256 depositAmountAfterFee,\n    uint256 feeAmount,\n    uint256 timestamp\n  );\n\n  /**\n   * @notice Event emitted when subscriptions are paused\n   *\n   * @param caller Address which initiated the pause\n   */\n  event SubscriptionPaused(address caller);\n\n  /**\n   * @notice Event emitted when redemptions are paused\n   *\n   * @param caller Address which initiated the pause\n   */\n  event RedemptionPaused(address caller);\n\n  /**\n   * @notice Event emitted when subscriptions are unpaused\n   *\n   * @param caller Address which initiated the unpause\n   */\n  event SubscriptionUnpaused(address caller);\n\n  /**\n   * @notice Event emitted when redemptions are unpaused\n   *\n   * @param caller Address which initiated the unpause\n   */\n  event RedemptionUnpaused(address caller);\n\n  event DepositorOverwritten(\n    bytes32 indexed depositId,\n    address oldDepositor,\n    address newDepositor,\n    uint256 oldPriceId,\n    uint256 newPriceId,\n    uint256 oldDepositAmount,\n    uint256 newDepositAmount\n  );\n\n  event RedeemerOverwritten(\n    bytes32 indexed redemptionId,\n    address oldRedeemer,\n    address newRedeemer,\n    uint256 oldPriceId,\n    uint256 newPriceId,\n    uint256 oldRWATokenAmountBurned,\n    uint256 newRWATokenAmountBurned\n  );\n\n  /// ERRORS ///\n  error PriceIdNotSet();\n  error ArraySizeMismatch();\n  error DepositTooSmall();\n  error RedemptionTooSmall();\n  error TxnAlreadyValidated();\n  error CollateralCannotBeZero();\n  error RWACannotBeZero();\n  error AssetSenderCannotBeZero();\n  error FeeRecipientCannotBeZero();\n  error FeeTooLarge();\n  error AmountTooSmall();\n  error DepositorNull();\n  error RedeemerNull();\n  error DepositProofAlreadyExists();\n  error FeaturePaused();\n  error PriceIdAlreadySet();\n}\n"},{"file_path":"contracts/interfaces/IRWAHubOffChainRedemptions.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\ninterface IRWAHubOffChainRedemptions {\n  function requestRedemptionServicedOffchain(\n    uint256 amountRWATokenToRedeem,\n    bytes32 offChainDestination\n  ) external;\n\n  function pauseOffChainRedemption() external;\n\n  function unpauseOffChainRedemption() external;\n\n  function setOffChainRedemptionMinimum(uint256 minimumAmount) external;\n\n  /**\n   * @notice Event emitted when redemption request is submitted\n   *\n   * @param user                The user submitting the offchain redemption request\n   * @param redemptionId        The id corresponding to a given offchain redemption request\n   * @param rwaTokenAmountIn    The amount of cash being burned\n   * @param offChainDestination Hash of destination to which the request\n   *                            should be serviced to\n   */\n  event RedemptionRequestedServicedOffChain(\n    address indexed user,\n    bytes32 indexed redemptionId,\n    uint256 rwaTokenAmountIn,\n    bytes32 offChainDestination\n  );\n\n  /**\n   * @notice Event emitted when the off chain redemption feature is\n   *         paused\n   *\n   * @param caller Address which initiated the pause\n   */\n  event OffChainRedemptionPaused(address caller);\n\n  /**\n   * @notice Event emitted when the off chain redemption feature is\n   *         unpaused\n   *\n   * @param caller Address which initiated the unpause\n   */\n  event OffChainRedemptionUnpaused(address caller);\n\n  /**\n   * @notice Event emitted when the off chain redemption minimum is\n   *         updated\n   *\n   * @param oldMinimum the old minimum redemption amount\n   * @param newMinimum the new minimum redemption amount\n   */\n  event OffChainRedemptionMinimumSet(uint256 oldMinimum, uint256 newMinimum);\n}\n"},{"file_path":"contracts/interfaces/IRWALike.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\n// This interface is not inherited directly by RWA, instead, it is a\n// subset of functions provided by all RWA tokens that the RWA Hub\n// Client uses.\nimport \"contracts/external/openzeppelin/contracts/token/IERC20.sol\";\n\ninterface IRWALike is IERC20 {\n  function mint(address to, uint256 amount) external;\n\n  function burn(uint256 amount) external;\n\n  function burnFrom(address from, uint256 amount) external;\n}\n"},{"file_path":"contracts/interfaces/IUSDYManager.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n */\npragma solidity 0.8.16;\n\ninterface IUSDYManager {\n  function setClaimableTimestamp(\n    uint256 claimDate,\n    bytes32[] calldata depositIds\n  ) external;\n\n  /**\n   * @notice Event emitted when claimable timestamp is set\n   *\n   * @param claimTimestamp The timestamp at which the mint can be claimed\n   * @param depositId      The depositId that can claim at the given \n                           `claimTimestamp`\n   */\n  event ClaimableTimestampSet(\n    uint256 indexed claimTimestamp,\n    bytes32 indexed depositId\n  );\n\n  /// ERRORS ///\n  error MintNotYetClaimable();\n  error ClaimableTimestampInPast();\n  error ClaimableTimestampNotSet();\n}\n"},{"file_path":"contracts/sanctions/ISanctionsListClient.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/external/chainalysis/ISanctionsList.sol\";\n\n/**\n * @title ISanctionsListClient\n * @author Ondo Finance\n * @notice The client interface for sanctions contract.\n */\ninterface ISanctionsListClient {\n  /// @notice Returns reference to the sanctions list that this client queries\n  function sanctionsList() external view returns (ISanctionsList);\n\n  /// @notice Sets the sanctions list reference\n  function setSanctionsList(address sanctionsList) external;\n\n  /// @notice Error for when caller attempts to set the `sanctionsList`\n  ///         reference to the zero address\n  error SanctionsListZeroAddress();\n\n  /// @notice Error for when caller attempts to perform an action on a\n  ///         sanctioned account\n  error SanctionedAccount();\n\n  /**\n   * @dev Event for when the sanctions list reference is set\n   *\n   * @param oldSanctionsList The old list\n   * @param newSanctionsList The new list\n   */\n  event SanctionsListSet(address oldSanctionsList, address newSanctionsList);\n}\n"},{"file_path":"contracts/sanctions/SanctionsListClient.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/external/chainalysis/ISanctionsList.sol\";\nimport \"contracts/sanctions/ISanctionsListClient.sol\";\n\n/**\n * @title SanctionsListClient\n * @author Ondo Finance\n * @notice This abstract contract manages state required for clients\n *         of the sanctions list\n */\nabstract contract SanctionsListClient is ISanctionsListClient {\n  // Sanctions list address\n  ISanctionsList public override sanctionsList;\n\n  /**\n   * @notice Constructor\n   *\n   * @param _sanctionsList Address of the sanctions list contract\n   */\n  constructor(address _sanctionsList) {\n    _setSanctionsList(_sanctionsList);\n  }\n\n  /**\n   * @notice Sets the sanctions list address for this client\n   *\n   * @param _sanctionsList The new sanctions list address\n   */\n  function _setSanctionsList(address _sanctionsList) internal {\n    if (_sanctionsList == address(0)) {\n      revert SanctionsListZeroAddress();\n    }\n    address oldSanctionsList = address(sanctionsList);\n    sanctionsList = ISanctionsList(_sanctionsList);\n    emit SanctionsListSet(oldSanctionsList, _sanctionsList);\n  }\n\n  /**\n   * @notice Checks whether an address has been sanctioned\n   *\n   * @param account The account to check\n   */\n  function _isSanctioned(address account) internal view returns (bool) {\n    return sanctionsList.isSanctioned(account);\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n   */\n  uint256[50] private __gap;\n}\n"},{"file_path":"contracts/usdy/blocklist/BlocklistClient.sol","source_code":"/**SPDX-License-Identifier: BUSL-1.1\n\n      ▄▄█████████▄\n   ╓██▀└ ,╓▄▄▄, '▀██▄\n  ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,\n ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,\n██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌\n██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██\n╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀\n ██ \"██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`\n  ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬\n   ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀\n      ╙▀▀██████R⌐\n\n */\npragma solidity 0.8.16;\n\nimport \"contracts/interfaces/IBlocklist.sol\";\nimport \"contracts/interfaces/IBlocklistClient.sol\";\n\n/**\n * @title BlocklistClient\n * @author Ondo Finance\n * @notice This abstract contract manages state for blocklist clients\n */\nabstract contract BlocklistClient is IBlocklistClient {\n  // blocklist address\n  IBlocklist public override blocklist;\n\n  /**\n   * @notice Constructor\n   *\n   * @param _blocklist Address of the blocklist contract\n   */\n  constructor(address _blocklist) {\n    _setBlocklist(_blocklist);\n  }\n\n  /**\n   * @notice Sets the blocklist address for this client\n   *\n   * @param _blocklist The new blocklist address\n   */\n  function _setBlocklist(address _blocklist) internal {\n    if (_blocklist == address(0)) {\n      revert BlocklistZeroAddress();\n    }\n    address oldBlocklist = address(blocklist);\n    blocklist = IBlocklist(_blocklist);\n    emit BlocklistSet(oldBlocklist, _blocklist);\n  }\n\n  /**\n   * @notice Checks whether an address has been blocked\n   *\n   * @param account The account to check\n   */\n  function _isBlocked(address account) internal view returns (bool) {\n    return blocklist.isBlocked(account);\n  }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_rwa","type":"address"},{"internalType":"address","name":"managerAdmin","type":"address"},{"internalType":"address","name":"pauser","type":"address"},{"internalType":"address","name":"_assetSender","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"uint256","name":"_minimumDepositAmount","type":"uint256"},{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"},{"internalType":"address","name":"blocklist","type":"address"},{"internalType":"address","name":"sanctionsList","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmountTooSmall","type":"error"},{"inputs":[],"name":"ArraySizeMismatch","type":"error"},{"inputs":[],"name":"AssetSenderCannotBeZero","type":"error"},{"inputs":[],"name":"BlockedAccount","type":"error"},{"inputs":[],"name":"BlocklistZeroAddress","type":"error"},{"inputs":[],"name":"ClaimableTimestampInPast","type":"error"},{"inputs":[],"name":"ClaimableTimestampNotSet","type":"error"},{"inputs":[],"name":"CollateralCannotBeZero","type":"error"},{"inputs":[],"name":"DepositProofAlreadyExists","type":"error"},{"inputs":[],"name":"DepositTooSmall","type":"error"},{"inputs":[],"name":"DepositorNull","type":"error"},{"inputs":[],"name":"FeaturePaused","type":"error"},{"inputs":[],"name":"FeeRecipientCannotBeZero","type":"error"},{"inputs":[],"name":"FeeTooLarge","type":"error"},{"inputs":[],"name":"MintNotYetClaimable","type":"error"},{"inputs":[],"name":"PriceIdAlreadySet","type":"error"},{"inputs":[],"name":"PriceIdNotSet","type":"error"},{"inputs":[],"name":"RWACannotBeZero","type":"error"},{"inputs":[],"name":"RedeemerNull","type":"error"},{"inputs":[],"name":"RedemptionTooSmall","type":"error"},{"inputs":[],"name":"SanctionedAccount","type":"error"},{"inputs":[],"name":"SanctionsListZeroAddress","type":"error"},{"inputs":[],"name":"TxnAlreadyValidated","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAssetSender","type":"address"},{"indexed":false,"internalType":"address","name":"newAssetSender","type":"address"}],"name":"AssetSenderSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldBlocklist","type":"address"},{"indexed":false,"internalType":"address","name":"newBlocklist","type":"address"}],"name":"BlocklistSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"claimTimestamp","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"}],"name":"ClaimableTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"DepositProofAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"oldDepositor","type":"address"},{"indexed":false,"internalType":"address","name":"newDepositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldDepositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositAmount","type":"uint256"}],"name":"DepositorOverwritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldFeeRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"MinimumDepositAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRedemptionMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRedemptionMin","type":"uint256"}],"name":"MinimumRedemptionAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmountDeposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"MintCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"MintFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"collateralAmountDeposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"MintRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPricer","type":"address"},{"indexed":false,"internalType":"address","name":"newPricer","type":"address"}],"name":"NewPricerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"OffChainRedemptionMinimumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"OffChainRedemptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"OffChainRedemptionUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositIdSet","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"priceIdSet","type":"uint256"}],"name":"PriceIdSetForDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"redemptionIdSet","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"priceIdSet","type":"uint256"}],"name":"PriceIdSetForRedemption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"oldRedeemer","type":"address"},{"indexed":false,"internalType":"address","name":"newRedeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldRWATokenAmountBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRWATokenAmountBurned","type":"uint256"}],"name":"RedeemerOverwritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountRequested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmountReturned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"RedemptionCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"RedemptionFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"RedemptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountIn","type":"uint256"}],"name":"RedemptionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaTokenAmountIn","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"offChainDestination","type":"bytes32"}],"name":"RedemptionRequestedServicedOffChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"RedemptionUnpaused","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":false,"internalType":"address","name":"oldSanctionsList","type":"address"},{"indexed":false,"internalType":"address","name":"newSanctionsList","type":"address"}],"name":"SanctionsListSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SubscriptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SubscriptionUnpaused","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_ID_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"addProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocklist","outputs":[{"internalType":"contract IBlocklist","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"}],"name":"claimMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"redemptionIds","type":"bytes32[]"}],"name":"claimRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalsMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositIdToClaimableTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositIdToDepositor","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amountDepositedMinusFees","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","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":[],"name":"minimumDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumOffChainRedemptionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumRedemptionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"offChainRedemptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"depositIdToOverwrite","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"overwriteDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redemptionIdToOverwrite","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"rwaTokenAmountBurned","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"overwriteRedeemer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseOffChainRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pricer","outputs":[{"internalType":"contract IPricerReader","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"redemptionIdToRedeemer","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amountRwaTokenBurned","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRequestCounter","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":"uint256","name":"amount","type":"uint256"}],"name":"requestRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountRWATokenToRedeem","type":"uint256"},{"internalType":"bytes32","name":"offChainDestination","type":"bytes32"}],"name":"requestRedemptionServicedOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"requestSubscription","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":"rwa","outputs":[{"internalType":"contract IRWALike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sanctionsList","outputs":[{"internalType":"contract ISanctionsList","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAssetSender","type":"address"}],"name":"setAssetSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"blocklist","type":"address"}],"name":"setBlocklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"claimTimestamp","type":"uint256"},{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"}],"name":"setClaimableTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minDepositAmount","type":"uint256"}],"name":"setMinimumDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"}],"name":"setMinimumRedemptionAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintFee","type":"uint256"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumOffChainRedemptionAmount","type":"uint256"}],"name":"setOffChainRedemptionMinimum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"priceIds","type":"uint256[]"}],"name":"setPriceIdForDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"redemptionIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"priceIds","type":"uint256[]"}],"name":"setPriceIdForRedemptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPricer","type":"address"}],"name":"setPricer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redemptionFee","type":"uint256"}],"name":"setRedemptionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sanctionsList","type":"address"}],"name":"setSanctionsList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"subscriptionRequestCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseOffChainRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad70000000000000000000000002e55b738f5969eea10fb67e326bee5e2fa15a2cc0000000000000000000000005eb3ac7d9b8220c484307a2506d611cc759626ca0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7000000000000000000000000000000000000000000000000000000001dcd650000000000000000000000000000000000000000000000001b1ae4d6e2ef500000000000000000000000000000d8c8174691d936e2c80114ec449037b13421b0a800000000000000000000000040c57923924b5c5c5455c48d93317139addac8fb"}