{"file_path":"contracts/CgUSD.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IBurner } from \"./interfaces/IBurner.sol\";\nimport { ILocator } from \"./interfaces/ILocator.sol\";\nimport { IOracleReportSanityChecker } from \"./interfaces/IOracleReportSanityChecker.sol\";\nimport { IWithdrawVault } from \"./interfaces/IWithdrawVault.sol\";\nimport { IWithdrawQueueERC721 } from \"./interfaces/IWithdrawQueueERC721.sol\";\nimport { ICgUSD } from \"./interfaces/ICgUSD.sol\";\nimport { IPausable } from \"./interfaces/IPausable.sol\";\nimport { UnstructuredStorage } from \"./lib/UnstructuredStorage.sol\";\nimport { StToken } from \"./StToken.sol\";\n\ncontract CgUSD is StToken, Ownable, Initializable, ICgUSD, IPausable {\n    using SafeERC20 for IERC20;\n    using UnstructuredStorage for bytes32;\n\n    address public asset;\n\n    bytes32 internal constant LOCATOR_POSITION =\n        0x1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625; // keccak256(\"cygnus.CgUSD.locator\")\n\n    bytes32 internal constant BUFFERED_ASSET_POSITION =\n        0x0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6; // keccak256(\"cygnus.CgUSD.bufferedAsset\");\n\n    bytes32 internal constant INVESTED_ASSET_POSITION =\n        0x2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b; // keccak256(\"cygnus.CgUSD.investedAsset\");\n\n    struct OracleReportedData {\n        uint256 reportTimestamp;\n        uint256 timeElapsed;\n        uint256 newInvestedAssets;\n        uint256 withdrawalVaultBalance;\n        uint256 sharesRequestedToBurn;\n        uint256[] withdrawalFinalizationBatches;\n        uint256 simulatedShareRate;\n    }\n\n    struct OracleReportContracts {\n        address accountingOracle;\n        address oracleReportSanityChecker;\n        address burner;\n        address withdrawQueue;\n        address withdrawVault;\n    }\n\n    struct OracleReportContext {\n        uint256 preTotalPooledAssets;\n        uint256 preTotalShares;\n        uint256 assetsToLockOnWithdrawalQueue;\n        uint256 sharesToBurnFromWithdrawalQueue;\n        uint256 simulatedSharesToBurn;\n        uint256 sharesToBurn;\n    }\n\n    event AssetsDistributed(\n        uint256 indexed reportTimestamp,\n        uint256 withdrawalsWithdrawn,\n        uint256 postBufferedAssets,\n        uint256 postInvestedAssets\n    );\n\n    event TokenRebased(\n        uint256 indexed reportTimestamp,\n        uint256 timeElapsed,\n        uint256 preTotalShares,\n        uint256 preTotalAssets,\n        uint256 postTotalShares,\n        uint256 postTotalAssets\n    );\n\n    event LocatorSet(address locator);\n\n    event WithdrawalsReceived(uint256 amount);\n\n    event Submitted(address indexed sender, uint256 amount, address referral);\n\n    event Invested(uint256 amount, uint256 postBufferedAssets, uint256 postInvestedAssets);\n\n    constructor(\n        address _asset,\n        address _owner\n    ) Ownable(_owner) {\n        asset = _asset;\n    }\n\n    function initialize(address _locator) external initializer {\n        _bootstrapInitialHolder();\n\n        LOCATOR_POSITION.setStorageAddress(_locator);\n        _approve(\n            ILocator(_locator).withdrawQueue(),\n            ILocator(_locator).burner(),\n            INFINITE_ALLOWANCE\n        );\n\n        emit LocatorSet(_locator);\n    }\n\n    function decimals() external view override returns (uint8) {\n        return IERC20Metadata(asset).decimals();\n    }\n\n    function resume() external onlyOwner {\n        _unpause();\n    }\n\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    function _getTotalPooledAssets() internal view override returns (uint256) {\n        return _getBufferedAssets() + _getInvestedAssets();\n    }\n\n    function getTotalAssets() external view returns (uint256, uint256) {\n        return (_getBufferedAssets(), _getInvestedAssets());\n    }\n\n    function canDeposit() public view returns (bool) {\n        return !_withdrawalQueue().isBunkerModeActive() && !paused();\n    }\n\n    function mint(address _referral, uint256 _assetsAmount)\n        external\n        returns (uint256 sharesAmount)\n    {\n        require((sharesAmount = previewDeposit(_assetsAmount)) != 0, \"ZERO_SHARES\");\n\n        // TODO: check if oracle price deviated\n\n        IERC20(asset).safeTransferFrom(msg.sender, address(this), _assetsAmount);\n\n        _mintShares(msg.sender, sharesAmount);\n\n        _setBufferedAssets(_getBufferedAssets() + _assetsAmount);\n        emit Submitted(msg.sender, _assetsAmount, _referral);\n\n        _emitTransferAfterMintingShares(msg.sender, sharesAmount);\n    }\n\n    function invest(address _to, uint256 _assetsAmount) external onlyOwner {\n        require(canDeposit(), \"CAN_NOT_INVEST\");\n\n        IERC20(asset).safeTransfer(_to, _assetsAmount);\n\n        uint256 postBufferedAssets = _getBufferedAssets() - _assetsAmount;\n        uint256 postInvestedAssets = _getInvestedAssets() + _assetsAmount;\n        _setBufferedAssets(postBufferedAssets);\n        _setInvestedAssets(postInvestedAssets);\n        emit Invested(_assetsAmount, postBufferedAssets, postInvestedAssets);\n    }\n\n    function handleOracleReport(\n        uint256 _reportTimestamp,\n        uint256 _timeElapsed,\n        uint256 _newInvestedAssets,\n        uint256 _withdrawalVaultBalance,\n        uint256 _sharesRequestedToBurn,\n        uint256[] calldata _withdrawalFinalizationBatches,\n        uint256 _simulatedShareRate\n    ) external whenNotPaused returns (uint256[3] memory postRebaseAmounts) {\n        return _handleOracleReport(\n            OracleReportedData(\n                _reportTimestamp,\n                _timeElapsed,\n                _newInvestedAssets,\n                _withdrawalVaultBalance,\n                _sharesRequestedToBurn,\n                _withdrawalFinalizationBatches,\n                _simulatedShareRate\n            )\n        );\n    }\n\n    function _handleOracleReport(OracleReportedData memory _reportedData) internal returns (uint256[3] memory) {\n        OracleReportContracts memory contracts = _loadOracleReportContracts();\n\n        require(msg.sender == contracts.accountingOracle, \"APP_AUTH_FAILED\");\n        require(_reportedData.reportTimestamp <= block.timestamp, \"INVALID_REPORT_TIMESTAMP\");\n\n        OracleReportContext memory reportContext;\n\n        // Step 1.\n        // Take a snapshot of the current (pre-) state\n        reportContext.preTotalPooledAssets = _getTotalPooledAssets();\n        reportContext.preTotalShares = _getTotalShares();\n\n        // Step 2.\n        // Pass the report data to sanity checker (reverts if malformed)\n        _checkAccountingOracleReport(contracts, _reportedData);\n\n        // Step 3.\n        // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt\n        // due to withdrawal requests to finalize\n        if (_reportedData.withdrawalFinalizationBatches.length != 0) {\n            (\n                reportContext.assetsToLockOnWithdrawalQueue,\n                reportContext.sharesToBurnFromWithdrawalQueue\n            ) = _calculateWithdrawals(contracts, _reportedData);\n\n            if (reportContext.sharesToBurnFromWithdrawalQueue > 0) {\n                IBurner(contracts.burner).requestBurnShares(\n                    contracts.withdrawQueue,\n                    reportContext.sharesToBurnFromWithdrawalQueue\n                );\n            }\n        }\n\n        // Step 4.\n        // Pass the accounting values to sanity checker to smoothen positive token rebase\n\n        uint256 withdrawals;\n        (\n            withdrawals, reportContext.simulatedSharesToBurn, reportContext.sharesToBurn\n        ) = IOracleReportSanityChecker(contracts.oracleReportSanityChecker).smoothenTokenRebase(\n            reportContext.preTotalPooledAssets,\n            reportContext.preTotalShares,\n            _reportedData.withdrawalVaultBalance,\n            _reportedData.sharesRequestedToBurn,\n            reportContext.assetsToLockOnWithdrawalQueue,\n            reportContext.sharesToBurnFromWithdrawalQueue\n        );\n\n        // Step 5.\n        // Invoke finalization of the withdrawal requests (send ether to withdrawal queue, assign shares to be burnt)\n        _collectRewardsAndProcessWithdrawals(\n            contracts,\n            withdrawals,\n            _reportedData.withdrawalFinalizationBatches,\n            _reportedData.simulatedShareRate,\n            reportContext.assetsToLockOnWithdrawalQueue\n        );\n\n        // Step 6.\n        // Update invested assets\n        _setInvestedAssets(_reportedData.newInvestedAssets);\n\n        emit AssetsDistributed(\n            _reportedData.reportTimestamp,\n            withdrawals,\n            _getBufferedAssets(),\n            _getInvestedAssets()\n        );\n\n        // Step 7.\n        // Burn the previously requested shares\n        if (reportContext.sharesToBurn > 0) {\n            IBurner(contracts.burner).commitSharesToBurn(reportContext.sharesToBurn);\n            _burnShares(contracts.burner, reportContext.sharesToBurn);\n        }\n\n        // Step 8.\n        // Complete token rebase (emit an event)\n        (\n            uint256 postTotalShares,\n            uint256 postTotalPooledAssets\n        ) = _completeTokenRebase(\n            _reportedData,\n            reportContext\n        );\n\n        // Step 9. Sanity check for the provided simulated share rate\n        if (_reportedData.withdrawalFinalizationBatches.length != 0) {\n            IOracleReportSanityChecker(contracts.oracleReportSanityChecker).checkSimulatedShareRate(\n                postTotalPooledAssets,\n                postTotalShares,\n                reportContext.assetsToLockOnWithdrawalQueue,\n                reportContext.sharesToBurn - reportContext.simulatedSharesToBurn,\n                _reportedData.simulatedShareRate\n            );\n        }\n\n        return [postTotalPooledAssets, postTotalShares, withdrawals];\n    }\n\n    function _collectRewardsAndProcessWithdrawals(\n        OracleReportContracts memory _contracts,\n        uint256 _withdrawalsToWithdraw,\n        uint256[] memory _withdrawalFinalizationBatches,\n        uint256 _simulatedShareRate,\n        uint256 _assetsToLockOnWithdrawalQueue\n    ) internal {\n        // withdraw withdrawals and put them to the buffer\n        if (_withdrawalsToWithdraw > 0) {\n            IWithdrawVault(_contracts.withdrawVault).withdrawWithdrawals(_withdrawalsToWithdraw);\n        }\n\n        // finalize withdrawals (send ether, assign shares for burning)\n        if (_assetsToLockOnWithdrawalQueue > 0) { // TODO\n            IWithdrawQueueERC721 withdrawalQueue = IWithdrawQueueERC721(_contracts.withdrawQueue);\n            IERC20(asset).safeTransfer(_contracts.withdrawQueue, _assetsToLockOnWithdrawalQueue);\n            withdrawalQueue.finalize(\n                _withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1],\n                _simulatedShareRate,\n                _assetsToLockOnWithdrawalQueue\n            );\n        }\n\n        uint256 postBufferedAssets = _getBufferedAssets() + _withdrawalsToWithdraw - _assetsToLockOnWithdrawalQueue;\n\n        _setBufferedAssets(postBufferedAssets);\n    }\n\n    function _calculateWithdrawals(\n        OracleReportContracts memory _contracts,\n        OracleReportedData memory _reportedData\n    ) internal view returns (\n        uint256 assetsToLock, uint256 sharesToBurn\n    ) {\n        IWithdrawQueueERC721 withdrawalQueue = IWithdrawQueueERC721(_contracts.withdrawQueue);\n\n        //if (!withdrawalQueue.isPaused()) { TODO\n        {\n            IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkWithdrawalQueueOracleReport(\n                _reportedData.withdrawalFinalizationBatches[_reportedData.withdrawalFinalizationBatches.length - 1],\n                _reportedData.reportTimestamp\n            );\n\n            (assetsToLock, sharesToBurn) = withdrawalQueue.prefinalize(\n                _reportedData.withdrawalFinalizationBatches,\n                _reportedData.simulatedShareRate\n            );\n        }\n    }\n\n    function _checkAccountingOracleReport(\n        OracleReportContracts memory _contracts,\n        OracleReportedData memory _reportedData\n    ) internal view {\n        IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkAccountingOracleReport(\n            _reportedData.timeElapsed,\n            _reportedData.withdrawalVaultBalance,\n            _reportedData.sharesRequestedToBurn\n        );\n    }\n\n    function _completeTokenRebase(\n        OracleReportedData memory _reportedData,\n        OracleReportContext memory _reportContext\n    ) internal returns (uint256 postTotalShares, uint256 postTotalPooledAssets) {\n        postTotalShares = _getTotalShares();\n        postTotalPooledAssets = _getTotalPooledAssets();\n\n        emit TokenRebased(\n            _reportedData.reportTimestamp,\n            _reportedData.timeElapsed,\n            _reportContext.preTotalShares,\n            _reportContext.preTotalPooledAssets,\n            postTotalShares,\n            postTotalPooledAssets\n        );\n    }\n\n    function _loadOracleReportContracts() internal view returns (OracleReportContracts memory ret) {\n        (\n            ret.accountingOracle,\n            ret.oracleReportSanityChecker,\n            ret.burner,\n            ret.withdrawQueue,\n            ret.withdrawVault\n        ) = getLocator().oracleReportComponents();\n    }\n\n    function getLocator() public view returns (ILocator) {\n        return ILocator(LOCATOR_POSITION.getStorageAddress());\n    }\n\n    function _withdrawalQueue() internal view returns (IWithdrawQueueERC721) {\n        return IWithdrawQueueERC721(getLocator().withdrawQueue());\n    }\n\n    function _getBufferedAssets() internal view returns (uint256) {\n        return BUFFERED_ASSET_POSITION.getStorageUint256();\n    }\n\n    function _setBufferedAssets(uint256 _newBufferedAssets) internal {\n        BUFFERED_ASSET_POSITION.setStorageUint256(_newBufferedAssets);\n    }\n\n    function _getInvestedAssets() internal view returns (uint256) {\n        return INVESTED_ASSET_POSITION.getStorageUint256();\n    }\n\n    function _setInvestedAssets(uint256 _newInvestedAssets) internal {\n        INVESTED_ASSET_POSITION.setStorageUint256(_newInvestedAssets);\n    }\n\n    function _bootstrapInitialHolder() internal {\n        uint256 balance = IERC20(asset).balanceOf(address(this));\n        assert(balance != 0);\n\n        if (_getTotalShares() == 0) {\n            _setBufferedAssets(balance);\n            emit Submitted(INITIAL_TOKEN_HOLDER, balance, address(0));\n            _mintInitialShares(balance);\n        }\n    }\n}","deployed_bytecode":"0x608060405234801561001057600080fd5b506004361061025c5760003560e01c80638da5cb5b11610145578063c6e6f592116100bd578063e745ad191161008c578063ef8b30f711610071578063ef8b30f714610544578063f2fde38b14610557578063f5eb42dc1461056a57600080fd5b8063e745ad191461030d578063e78a58751461053c57600080fd5b8063c6e6f592146104e0578063d5002f2e146104f3578063d8343dcb146104fb578063dd62ed3e1461050357600080fd5b8063a9059cbb11610114578063b823fba2116100f9578063b823fba21461049a578063b9b8c246146104ba578063c4d66de8146104cd57600080fd5b8063a9059cbb14610474578063b3d7f6b91461048757600080fd5b80638da5cb5b146104045780638fcb4e5b1461041557806395d89b4114610428578063a457c2d71461046157600080fd5b806339509351116101d85780636d780459116101a757806370a082311161018c57806370a08231146103e1578063715018a6146103f45780638456cb59146103fc57600080fd5b80636d780459146103b15780636e07302b146103c457600080fd5b8063395093511461036d57806340c10f19146103805780634cdad506146103935780635c975abb146103a657600080fd5b80630a28a4771161022f57806323b872dd1161021457806323b872dd14610315578063313ce5671461032857806338d52e0f1461034257600080fd5b80630a28a477146102fa57806318160ddd1461030d57600080fd5b8063046f7da21461026157806306fdde031461026b57806307a2d13a146102b6578063095ea7b3146102d7575b600080fd5b61026961057d565b005b60408051808201909152601181527f4379676e757320476c6f62616c2055534400000000000000000000000000000060208201525b6040516102ad919061255a565b60405180910390f35b6102c96102c43660046125ab565b61058f565b6040519081526020016102ad565b6102ea6102e53660046125d9565b6105b2565b60405190151581526020016102ad565b6102c96103083660046125ab565b6105c8565b6102c96105e5565b6102ea610323366004612605565b6105f4565b610330610617565b60405160ff90911681526020016102ad565b600454610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102ad565b6102ea61037b3660046125d9565b610690565b6102c961038e3660046125d9565b6106cc565b6102c96103a13660046125ab565b6107b9565b60005460ff166102ea565b6102c96103bf366004612605565b6107c4565b6103cc6107fc565b604080519283526020830191909152016102ad565b6102c96103ef366004612646565b610817565b610269610839565b61026961084b565b6003546001600160a01b0316610355565b6102c96104233660046125d9565b61085b565b60408051808201909152600581527f636755534400000000000000000000000000000000000000000000000000000060208201526102a0565b6102ea61046f3660046125d9565b610881565b6102ea6104823660046125d9565b610904565b6102c96104953660046125ab565b610911565b6104ad6104a8366004612663565b610926565b6040516102ad9190612712565b6102696104c83660046125d9565b6109b0565b6102696104db366004612646565b610aaa565b6102c96104ee3660046125ab565b610d31565b6102c9610d46565b610355610d50565b6102c9610511366004612743565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102ea610d7a565b6102c96105523660046125ab565b610df8565b610269610565366004612646565b610e03565b6102c9610578366004612646565b610e5a565b610585610e78565b61058d610ebe565b565b60006105ac61059c610f10565b6105a4610f2c565b849190610f56565b92915050565b60006105bf338484610f74565b50600192915050565b60006105ac6105d5610f2c565b6105dd610f10565b849190611081565b60006105ef610f10565b905090565b60006106018433846110a7565b61060c84848461113b565b5060015b9392505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef919061277c565b3360008181526002602090815260408083206001600160a01b038716845290915281205490916105bf9185906106c79086906127b5565b610f74565b60006106d782610df8565b90508060000361072e5760405162461bcd60e51b815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600454610746906001600160a01b031633308561115f565b61075033826111db565b5061076c8261075d6112b6565b61076791906127b5565b6112e0565b604080518381526001600160a01b038516602082015233917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a26105ac3382611309565b60006105ac8261058f565b6000806107d08361058f565b90506107dd8533836110a7565b6107e8858585611322565b6107f4858583866114f3565b949350505050565b6000806108076112b6565b61080f611593565b915091509091565b6001600160a01b0381166000908152600160205260408120546105ac9061058f565b610841610e78565b61058d60006115bd565b610853610e78565b61058d611627565b6000610868338484611322565b60006108738361058f565b9050610610338583866114f3565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156108f55760405162461bcd60e51b815260206004820152601460248201527f414c4c4f57414e43455f42454c4f575f5a45524f0000000000000000000000006044820152606401610725565b61060c33856106c786856127c8565b60006105bf33848461113b565b60006105ac61091e610f10565b6105dd610f2c565b61092e612518565b610936611664565b6109a36040518060e001604052808b81526020018a81526020018981526020018881526020018781526020018686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020018490526116a1565b9998505050505050505050565b6109b8610e78565b6109c0610d7a565b610a0c5760405162461bcd60e51b815260206004820152600e60248201527f43414e5f4e4f545f494e564553540000000000000000000000000000000000006044820152606401610725565b600454610a23906001600160a01b03168383611b3f565b600081610a2e6112b6565b610a3891906127c8565b9050600082610a45611593565b610a4f91906127b5565b9050610a5a826112e0565b610a6381611b75565b60408051848152602081018490529081018290527f15294ad9d42e2bbd446d4ff6ca28fef807d1631ad53c688303fe468410830f329060600160405180910390a150505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af55750825b905060008267ffffffffffffffff166001148015610b125750303b155b905081158015610b20575080155b15610b57576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610ba257845468ff00000000000000001916680100000000000000001785555b610baa611b9e565b610bd37f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625879055565b610ca2866001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906127db565b876001600160a01b03166327810b6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906127db565b600019610f74565b6040516001600160a01b03871681527f8cb16e06ecfafbed13687256a764058471060b490b62dc8b3e4ea2f395ec29599060200160405180910390a18315610d2957845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60006105ac610d3e610f2c565b6105a4610f10565b60006105ef610f2c565b60006105ef7f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e426255490565b6000610d84611c99565b6001600160a01b0316632b95b7816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de591906127f8565b1580156105ef57505060005460ff161590565b60006105ac82610d31565b610e0b610e78565b6001600160a01b038116610e4e576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610725565b610e57816115bd565b50565b6001600160a01b0381166000908152600160205260408120546105ac565b6003546001600160a01b0316331461058d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610725565b610ec6611d04565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f1a611593565b610f226112b6565b6105ef91906127b5565b60006105ef7f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be5490565b6000826000190484118302158202610f6d57600080fd5b5091020490565b6001600160a01b038316610fca5760405162461bcd60e51b815260206004820152601660248201527f415050524f56455f46524f4d5f5a45524f5f41444452000000000000000000006044820152606401610725565b6001600160a01b0382166110205760405162461bcd60e51b815260206004820152601460248201527f415050524f56455f544f5f5a45524f5f414444520000000000000000000000006044820152606401610725565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600082600019048411830215820261109857600080fd5b50910281810615159190040190565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054600019811461113557818110156111265760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f455843454544454400000000000000000000000000006044820152606401610725565b61113584846106c785856127c8565b50505050565b600061114682610d31565b9050611153848483611322565b611135848484846114f3565b6040516001600160a01b0384811660248301528381166044830152606482018390526111359186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d40565b60006001600160a01b0383166112335760405162461bcd60e51b815260206004820152601160248201527f4d494e545f544f5f5a45524f5f414444520000000000000000000000000000006044820152606401610725565b8161123c610f2c565b61124691906127b5565b90506112717f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be829055565b6001600160a01b0383166000908152600160205260409020546112959083906127b5565b6001600160a01b039093166000908152600160205260409020929092555090565b60006105ef7f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a65490565b610e577f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6829055565b61131e6000836113188461058f565b846114f3565b5050565b61132a611664565b6001600160a01b0383166113805760405162461bcd60e51b815260206004820152601760248201527f5452414e534645525f46524f4d5f5a45524f5f414444520000000000000000006044820152606401610725565b6001600160a01b0382166113d65760405162461bcd60e51b815260206004820152601560248201527f5452414e534645525f544f5f5a45524f5f4144445200000000000000000000006044820152606401610725565b306001600160a01b0383160361142e5760405162461bcd60e51b815260206004820152601a60248201527f5452414e534645525f544f5f53544554485f434f4e54524143540000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808211156114975760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b6114a182826127c8565b6001600160a01b0380861660009081526001602052604080822093909355908516815220546114d19083906127b5565b6001600160a01b03909316600090815260016020526040902092909255505050565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161153891815260200190565b60405180910390a3826001600160a01b0316846001600160a01b03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb8360405161158591815260200190565b60405180910390a350505050565b60006105ef7f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b5490565b600380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61162f611664565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ef33390565b60005460ff161561058d576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a9612518565b60006116b3611dbc565b80519091506001600160a01b0316331461170f5760405162461bcd60e51b815260206004820152600f60248201527f4150505f415554485f4641494c454400000000000000000000000000000000006044820152606401610725565b82514210156117605760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245504f52545f54494d455354414d5000000000000000006044820152606401610725565b6117996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6117a1610f10565b81526117ab610f2c565b60208201526117ba8285611e7e565b60a0840151511561186e576117cf8285611f0e565b6060830181905260408301919091521561186e576040808301516060808501519084015192517f461149280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101939093521690634611492890604401600060405180830381600087803b15801561185557600080fd5b505af1158015611869573d6000803e3d6000fd5b505050505b60208083015182519183015160608088015160808901516040808801519388015190517f3cf7df960000000000000000000000000000000000000000000000000000000081526004810197909752602487019490945260448601919091526064850152608484015260a48301526000916001600160a01b0390911690633cf7df969060c401606060405180830381865afa158015611910573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611934919061281a565b846080018560a001828152508281525082935050505061196383828760a001518860c001518660400151612050565b6119708560400151611b75565b84517f224918cef3c8dd950405e7cd332c2d23ff756244eb4ae4f3e81f6bf8f14d78ad8261199c6112b6565b6119a4611593565b6040805193845260208401929092529082015260600160405180910390a260a082015115611a485782604001516001600160a01b031663636e6b668360a001516040518263ffffffff1660e01b8152600401611a0291815260200190565b600060405180830381600087803b158015611a1c57600080fd5b505af1158015611a30573d6000803e3d6000fd5b50505050611a4683604001518360a001516121b8565b505b600080611a55878561234b565b915091508660a0015151600014611b1b5784602001516001600160a01b03166363e56b9f8284876040015188608001518960a00151611a9491906127c8565b60c08d01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a40160006040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050505b60408051606081018252918252602082019290925290810191909152949350505050565b6040516001600160a01b03838116602483015260448201839052611b7091859182169063a9059cbb90606401611194565b505050565b610e577f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b829055565b600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c299190612848565b905080600003611c3b57611c3b612861565b611c43610f2c565b600003610e5757611c53816112e0565b604080518281526000602082015261dead917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a2610e57816123c6565b6000611ca3610d50565b6001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ce0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef91906127db565b60005460ff1661058d576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d556001600160a01b038416836123df565b90508051600014158015611d7a575080806020019051810190611d7891906127f8565b155b15611b70576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610725565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611def610d50565b6001600160a01b031663b2ad11046040518163ffffffff1660e01b815260040160a060405180830381865afa158015611e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e509190612877565b6001600160a01b03908116608087015290811660608601529081166040850152908116602084015216815290565b60208083015190820151606083015160808401516040517f848b2d7c0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526001600160a01b039091169063848b2d7c9060640160006040518083038186803b158015611efa57600080fd5b505afa158015610d29573d6000803e3d6000fd5b60008060008460600151905084602001516001600160a01b0316636a84f2fd8560a0015160018760a0015151611f4491906127c8565b81518110611f5457611f546128ec565b602002602001015186600001516040518363ffffffff1660e01b8152600401611f87929190918252602082015260400190565b60006040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b5050505060a084015160c08501516040517fa52e9c9f0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263a52e9c9f9261200492600401612902565b6040805180830381865afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612044919061294a565b90969095509350505050565b83156120d05760808501516040517f3194528a000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0390911690633194528a90602401600060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050505b801561218d5760608501516004546120f2906001600160a01b03168284611b3f565b806001600160a01b0316635b206ec5856001875161211091906127c8565b81518110612120576121206128ec565b602002602001015185856040518463ffffffff1660e01b8152600401612159939291909283526020830191909152604082015260600190565b600060405180830381600087803b15801561217357600080fd5b505af1158015612187573d6000803e3d6000fd5b50505050505b600081856121996112b6565b6121a391906127b5565b6121ad91906127c8565b9050610d29816112e0565b60006001600160a01b0383166122105760405162461bcd60e51b815260206004820152601360248201527f4255524e5f46524f4d5f5a45524f5f41444452000000000000000000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808311156122795760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b60006122848461058f565b90508361228f610f2c565b61229991906127c8565b92506122c47f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be849055565b6122ce84836127c8565b6001600160a01b0386166000908152600160205260408120919091556122f38561058f565b60408051848152602081018390529081018790529091506001600160a01b038716907f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649060600160405180910390a250505092915050565b600080612356610f2c565b9150612360610f10565b84516020808701518682015187516040805193845293830191909152818301526060810186905260808101849052905192935090917f56a90fb9987084b721919e7e877c8c06757ce01d02952ca54cb1155774abfaea9181900360a00190a29250929050565b6123d261dead826111db565b50610e5761dead82611309565b60606106108383600084600080856001600160a01b03168486604051612405919061296e565b60006040518083038185875af1925050503d8060008114612442576040519150601f19603f3d011682016040523d82523d6000602084013e612447565b606091505b5091509150612457868383612461565b9695505050505050565b60608261247657612471826124d6565b610610565b815115801561248d57506001600160a01b0384163b155b156124cf576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610725565b5080610610565b8051156124e65780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180606001604052806003906020820280368337509192915050565b60005b83811015612551578181015183820152602001612539565b50506000910152565b6020815260008251806020840152612579816040850160208701612536565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156125bd57600080fd5b5035919050565b6001600160a01b0381168114610e5757600080fd5b600080604083850312156125ec57600080fd5b82356125f7816125c4565b946020939093013593505050565b60008060006060848603121561261a57600080fd5b8335612625816125c4565b92506020840135612635816125c4565b929592945050506040919091013590565b60006020828403121561265857600080fd5b8135610610816125c4565b60008060008060008060008060e0898b03121561267f57600080fd5b883597506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff808211156126ba57600080fd5b818b0191508b601f8301126126ce57600080fd5b8135818111156126dd57600080fd5b8c60208260051b85010111156126f257600080fd5b60208301955080945050505060c089013590509295985092959890939650565b60608101818360005b600381101561273a57815183526020928301929091019060010161271b565b50505092915050565b6000806040838503121561275657600080fd5b8235612761816125c4565b91506020830135612771816125c4565b809150509250929050565b60006020828403121561278e57600080fd5b815160ff8116811461061057600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105ac576105ac61279f565b818103818111156105ac576105ac61279f565b6000602082840312156127ed57600080fd5b8151610610816125c4565b60006020828403121561280a57600080fd5b8151801515811461061057600080fd5b60008060006060848603121561282f57600080fd5b8351925060208401519150604084015190509250925092565b60006020828403121561285a57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a0868803121561288f57600080fd5b855161289a816125c4565b60208701519095506128ab816125c4565b60408701519094506128bc816125c4565b60608701519093506128cd816125c4565b60808701519092506128de816125c4565b809150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561293b5781518452928401929084019060010161291f565b50505092019290925292915050565b6000806040838503121561295d57600080fd5b505080516020909101519092909150565b60008251612980818460208701612536565b919091019291505056fea2646970667358221220850d22b1ba11f035bf015364ee858924d9af209cfdf73e7b69f4938235c7c48264736f6c63430008140033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":2000},"remappings":[]},"optimization_runs":2000,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/8453/0xCa72827a3D211CfD8F6b00Ac98824872b72CAb49/","decoded_constructor_args":[["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",{"internalType":"address","name":"_asset","type":"address"}],["0xfECAB866b450b97dB38500898e9272c1D18918b7",{"internalType":"address","name":"_owner","type":"address"}]],"compiler_version":"0.8.20+commit.a1b79de6","is_verified_via_verifier_alliance":false,"verified_at":"2024-03-22T15:39:36.270503Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60806040523480156200001157600080fd5b5060405162002b1838038062002b18833981016040819052620000349162000110565b6000805460ff19169055806001600160a01b0381166200006e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200007981620000a1565b5050600480546001600160a01b0319166001600160a01b039290921691909117905562000148565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200010b57600080fd5b919050565b600080604083850312156200012457600080fd5b6200012f83620000f3565b91506200013f60208401620000f3565b90509250929050565b6129c080620001586000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c80638da5cb5b11610145578063c6e6f592116100bd578063e745ad191161008c578063ef8b30f711610071578063ef8b30f714610544578063f2fde38b14610557578063f5eb42dc1461056a57600080fd5b8063e745ad191461030d578063e78a58751461053c57600080fd5b8063c6e6f592146104e0578063d5002f2e146104f3578063d8343dcb146104fb578063dd62ed3e1461050357600080fd5b8063a9059cbb11610114578063b823fba2116100f9578063b823fba21461049a578063b9b8c246146104ba578063c4d66de8146104cd57600080fd5b8063a9059cbb14610474578063b3d7f6b91461048757600080fd5b80638da5cb5b146104045780638fcb4e5b1461041557806395d89b4114610428578063a457c2d71461046157600080fd5b806339509351116101d85780636d780459116101a757806370a082311161018c57806370a08231146103e1578063715018a6146103f45780638456cb59146103fc57600080fd5b80636d780459146103b15780636e07302b146103c457600080fd5b8063395093511461036d57806340c10f19146103805780634cdad506146103935780635c975abb146103a657600080fd5b80630a28a4771161022f57806323b872dd1161021457806323b872dd14610315578063313ce5671461032857806338d52e0f1461034257600080fd5b80630a28a477146102fa57806318160ddd1461030d57600080fd5b8063046f7da21461026157806306fdde031461026b57806307a2d13a146102b6578063095ea7b3146102d7575b600080fd5b61026961057d565b005b60408051808201909152601181527f4379676e757320476c6f62616c2055534400000000000000000000000000000060208201525b6040516102ad919061255a565b60405180910390f35b6102c96102c43660046125ab565b61058f565b6040519081526020016102ad565b6102ea6102e53660046125d9565b6105b2565b60405190151581526020016102ad565b6102c96103083660046125ab565b6105c8565b6102c96105e5565b6102ea610323366004612605565b6105f4565b610330610617565b60405160ff90911681526020016102ad565b600454610355906001600160a01b031681565b6040516001600160a01b0390911681526020016102ad565b6102ea61037b3660046125d9565b610690565b6102c961038e3660046125d9565b6106cc565b6102c96103a13660046125ab565b6107b9565b60005460ff166102ea565b6102c96103bf366004612605565b6107c4565b6103cc6107fc565b604080519283526020830191909152016102ad565b6102c96103ef366004612646565b610817565b610269610839565b61026961084b565b6003546001600160a01b0316610355565b6102c96104233660046125d9565b61085b565b60408051808201909152600581527f636755534400000000000000000000000000000000000000000000000000000060208201526102a0565b6102ea61046f3660046125d9565b610881565b6102ea6104823660046125d9565b610904565b6102c96104953660046125ab565b610911565b6104ad6104a8366004612663565b610926565b6040516102ad9190612712565b6102696104c83660046125d9565b6109b0565b6102696104db366004612646565b610aaa565b6102c96104ee3660046125ab565b610d31565b6102c9610d46565b610355610d50565b6102c9610511366004612743565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102ea610d7a565b6102c96105523660046125ab565b610df8565b610269610565366004612646565b610e03565b6102c9610578366004612646565b610e5a565b610585610e78565b61058d610ebe565b565b60006105ac61059c610f10565b6105a4610f2c565b849190610f56565b92915050565b60006105bf338484610f74565b50600192915050565b60006105ac6105d5610f2c565b6105dd610f10565b849190611081565b60006105ef610f10565b905090565b60006106018433846110a7565b61060c84848461113b565b5060015b9392505050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef919061277c565b3360008181526002602090815260408083206001600160a01b038716845290915281205490916105bf9185906106c79086906127b5565b610f74565b60006106d782610df8565b90508060000361072e5760405162461bcd60e51b815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600454610746906001600160a01b031633308561115f565b61075033826111db565b5061076c8261075d6112b6565b61076791906127b5565b6112e0565b604080518381526001600160a01b038516602082015233917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a26105ac3382611309565b60006105ac8261058f565b6000806107d08361058f565b90506107dd8533836110a7565b6107e8858585611322565b6107f4858583866114f3565b949350505050565b6000806108076112b6565b61080f611593565b915091509091565b6001600160a01b0381166000908152600160205260408120546105ac9061058f565b610841610e78565b61058d60006115bd565b610853610e78565b61058d611627565b6000610868338484611322565b60006108738361058f565b9050610610338583866114f3565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156108f55760405162461bcd60e51b815260206004820152601460248201527f414c4c4f57414e43455f42454c4f575f5a45524f0000000000000000000000006044820152606401610725565b61060c33856106c786856127c8565b60006105bf33848461113b565b60006105ac61091e610f10565b6105dd610f2c565b61092e612518565b610936611664565b6109a36040518060e001604052808b81526020018a81526020018981526020018881526020018781526020018686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506020018490526116a1565b9998505050505050505050565b6109b8610e78565b6109c0610d7a565b610a0c5760405162461bcd60e51b815260206004820152600e60248201527f43414e5f4e4f545f494e564553540000000000000000000000000000000000006044820152606401610725565b600454610a23906001600160a01b03168383611b3f565b600081610a2e6112b6565b610a3891906127c8565b9050600082610a45611593565b610a4f91906127b5565b9050610a5a826112e0565b610a6381611b75565b60408051848152602081018490529081018290527f15294ad9d42e2bbd446d4ff6ca28fef807d1631ad53c688303fe468410830f329060600160405180910390a150505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af55750825b905060008267ffffffffffffffff166001148015610b125750303b155b905081158015610b20575080155b15610b57576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610ba257845468ff00000000000000001916680100000000000000001785555b610baa611b9e565b610bd37f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e42625879055565b610ca2866001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906127db565b876001600160a01b03166327810b6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906127db565b600019610f74565b6040516001600160a01b03871681527f8cb16e06ecfafbed13687256a764058471060b490b62dc8b3e4ea2f395ec29599060200160405180910390a18315610d2957845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60006105ac610d3e610f2c565b6105a4610f10565b60006105ef610f2c565b60006105ef7f1718d90604c88f478732e809519e74c5c9a3a2b5dc95162ccc63d61800e426255490565b6000610d84611c99565b6001600160a01b0316632b95b7816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de591906127f8565b1580156105ef57505060005460ff161590565b60006105ac82610d31565b610e0b610e78565b6001600160a01b038116610e4e576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610725565b610e57816115bd565b50565b6001600160a01b0381166000908152600160205260408120546105ac565b6003546001600160a01b0316331461058d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610725565b610ec6611d04565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f1a611593565b610f226112b6565b6105ef91906127b5565b60006105ef7f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be5490565b6000826000190484118302158202610f6d57600080fd5b5091020490565b6001600160a01b038316610fca5760405162461bcd60e51b815260206004820152601660248201527f415050524f56455f46524f4d5f5a45524f5f41444452000000000000000000006044820152606401610725565b6001600160a01b0382166110205760405162461bcd60e51b815260206004820152601460248201527f415050524f56455f544f5f5a45524f5f414444520000000000000000000000006044820152606401610725565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600082600019048411830215820261109857600080fd5b50910281810615159190040190565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054600019811461113557818110156111265760405162461bcd60e51b815260206004820152601260248201527f414c4c4f57414e43455f455843454544454400000000000000000000000000006044820152606401610725565b61113584846106c785856127c8565b50505050565b600061114682610d31565b9050611153848483611322565b611135848484846114f3565b6040516001600160a01b0384811660248301528381166044830152606482018390526111359186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d40565b60006001600160a01b0383166112335760405162461bcd60e51b815260206004820152601160248201527f4d494e545f544f5f5a45524f5f414444520000000000000000000000000000006044820152606401610725565b8161123c610f2c565b61124691906127b5565b90506112717f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be829055565b6001600160a01b0383166000908152600160205260409020546112959083906127b5565b6001600160a01b039093166000908152600160205260409020929092555090565b60006105ef7f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a65490565b610e577f0afc87acedeee8c4193ad63118c06a9f961d4d6f3e34515e102d41596851b1a6829055565b61131e6000836113188461058f565b846114f3565b5050565b61132a611664565b6001600160a01b0383166113805760405162461bcd60e51b815260206004820152601760248201527f5452414e534645525f46524f4d5f5a45524f5f414444520000000000000000006044820152606401610725565b6001600160a01b0382166113d65760405162461bcd60e51b815260206004820152601560248201527f5452414e534645525f544f5f5a45524f5f4144445200000000000000000000006044820152606401610725565b306001600160a01b0383160361142e5760405162461bcd60e51b815260206004820152601a60248201527f5452414e534645525f544f5f53544554485f434f4e54524143540000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808211156114975760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b6114a182826127c8565b6001600160a01b0380861660009081526001602052604080822093909355908516815220546114d19083906127b5565b6001600160a01b03909316600090815260016020526040902092909255505050565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161153891815260200190565b60405180910390a3826001600160a01b0316846001600160a01b03167f9d9c909296d9c674451c0c24f02cb64981eb3b727f99865939192f880a755dcb8360405161158591815260200190565b60405180910390a350505050565b60006105ef7f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b5490565b600380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61162f611664565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610ef33390565b60005460ff161561058d576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a9612518565b60006116b3611dbc565b80519091506001600160a01b0316331461170f5760405162461bcd60e51b815260206004820152600f60248201527f4150505f415554485f4641494c454400000000000000000000000000000000006044820152606401610725565b82514210156117605760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245504f52545f54494d455354414d5000000000000000006044820152606401610725565b6117996040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6117a1610f10565b81526117ab610f2c565b60208201526117ba8285611e7e565b60a0840151511561186e576117cf8285611f0e565b6060830181905260408301919091521561186e576040808301516060808501519084015192517f461149280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101939093521690634611492890604401600060405180830381600087803b15801561185557600080fd5b505af1158015611869573d6000803e3d6000fd5b505050505b60208083015182519183015160608088015160808901516040808801519388015190517f3cf7df960000000000000000000000000000000000000000000000000000000081526004810197909752602487019490945260448601919091526064850152608484015260a48301526000916001600160a01b0390911690633cf7df969060c401606060405180830381865afa158015611910573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611934919061281a565b846080018560a001828152508281525082935050505061196383828760a001518860c001518660400151612050565b6119708560400151611b75565b84517f224918cef3c8dd950405e7cd332c2d23ff756244eb4ae4f3e81f6bf8f14d78ad8261199c6112b6565b6119a4611593565b6040805193845260208401929092529082015260600160405180910390a260a082015115611a485782604001516001600160a01b031663636e6b668360a001516040518263ffffffff1660e01b8152600401611a0291815260200190565b600060405180830381600087803b158015611a1c57600080fd5b505af1158015611a30573d6000803e3d6000fd5b50505050611a4683604001518360a001516121b8565b505b600080611a55878561234b565b915091508660a0015151600014611b1b5784602001516001600160a01b03166363e56b9f8284876040015188608001518960a00151611a9491906127c8565b60c08d01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a40160006040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050505b60408051606081018252918252602082019290925290810191909152949350505050565b6040516001600160a01b03838116602483015260448201839052611b7091859182169063a9059cbb90606401611194565b505050565b610e577f2c852a3a34b8266c1f4cf623581e3b3686edf6412c376db5da52f02d19ef925b829055565b600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c299190612848565b905080600003611c3b57611c3b612861565b611c43610f2c565b600003610e5757611c53816112e0565b604080518281526000602082015261dead917f96a25c8ce0baabc1fdefd93e9ed25d8e092a3332f3aa9a41722b5697231d1d1a910160405180910390a2610e57816123c6565b6000611ca3610d50565b6001600160a01b03166351a2d6d16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ce0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef91906127db565b60005460ff1661058d576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611d556001600160a01b038416836123df565b90508051600014158015611d7a575080806020019051810190611d7891906127f8565b155b15611b70576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610725565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611def610d50565b6001600160a01b031663b2ad11046040518163ffffffff1660e01b815260040160a060405180830381865afa158015611e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e509190612877565b6001600160a01b03908116608087015290811660608601529081166040850152908116602084015216815290565b60208083015190820151606083015160808401516040517f848b2d7c0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526001600160a01b039091169063848b2d7c9060640160006040518083038186803b158015611efa57600080fd5b505afa158015610d29573d6000803e3d6000fd5b60008060008460600151905084602001516001600160a01b0316636a84f2fd8560a0015160018760a0015151611f4491906127c8565b81518110611f5457611f546128ec565b602002602001015186600001516040518363ffffffff1660e01b8152600401611f87929190918252602082015260400190565b60006040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b5050505060a084015160c08501516040517fa52e9c9f0000000000000000000000000000000000000000000000000000000081526001600160a01b0384169263a52e9c9f9261200492600401612902565b6040805180830381865afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612044919061294a565b90969095509350505050565b83156120d05760808501516040517f3194528a000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0390911690633194528a90602401600060405180830381600087803b1580156120b757600080fd5b505af11580156120cb573d6000803e3d6000fd5b505050505b801561218d5760608501516004546120f2906001600160a01b03168284611b3f565b806001600160a01b0316635b206ec5856001875161211091906127c8565b81518110612120576121206128ec565b602002602001015185856040518463ffffffff1660e01b8152600401612159939291909283526020830191909152604082015260600190565b600060405180830381600087803b15801561217357600080fd5b505af1158015612187573d6000803e3d6000fd5b50505050505b600081856121996112b6565b6121a391906127b5565b6121ad91906127c8565b9050610d29816112e0565b60006001600160a01b0383166122105760405162461bcd60e51b815260206004820152601360248201527f4255524e5f46524f4d5f5a45524f5f41444452000000000000000000000000006044820152606401610725565b6001600160a01b038316600090815260016020526040902054808311156122795760405162461bcd60e51b815260206004820152601060248201527f42414c414e43455f4558434545444544000000000000000000000000000000006044820152606401610725565b60006122848461058f565b90508361228f610f2c565b61229991906127c8565b92506122c47f83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be849055565b6122ce84836127c8565b6001600160a01b0386166000908152600160205260408120919091556122f38561058f565b60408051848152602081018390529081018790529091506001600160a01b038716907f8b2a1e1ad5e0578c3dd82494156e985dade827a87c573b5c1c7716a32162ad649060600160405180910390a250505092915050565b600080612356610f2c565b9150612360610f10565b84516020808701518682015187516040805193845293830191909152818301526060810186905260808101849052905192935090917f56a90fb9987084b721919e7e877c8c06757ce01d02952ca54cb1155774abfaea9181900360a00190a29250929050565b6123d261dead826111db565b50610e5761dead82611309565b60606106108383600084600080856001600160a01b03168486604051612405919061296e565b60006040518083038185875af1925050503d8060008114612442576040519150601f19603f3d011682016040523d82523d6000602084013e612447565b606091505b5091509150612457868383612461565b9695505050505050565b60608261247657612471826124d6565b610610565b815115801561248d57506001600160a01b0384163b155b156124cf576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610725565b5080610610565b8051156124e65780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180606001604052806003906020820280368337509192915050565b60005b83811015612551578181015183820152602001612539565b50506000910152565b6020815260008251806020840152612579816040850160208701612536565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156125bd57600080fd5b5035919050565b6001600160a01b0381168114610e5757600080fd5b600080604083850312156125ec57600080fd5b82356125f7816125c4565b946020939093013593505050565b60008060006060848603121561261a57600080fd5b8335612625816125c4565b92506020840135612635816125c4565b929592945050506040919091013590565b60006020828403121561265857600080fd5b8135610610816125c4565b60008060008060008060008060e0898b03121561267f57600080fd5b883597506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff808211156126ba57600080fd5b818b0191508b601f8301126126ce57600080fd5b8135818111156126dd57600080fd5b8c60208260051b85010111156126f257600080fd5b60208301955080945050505060c089013590509295985092959890939650565b60608101818360005b600381101561273a57815183526020928301929091019060010161271b565b50505092915050565b6000806040838503121561275657600080fd5b8235612761816125c4565b91506020830135612771816125c4565b809150509250929050565b60006020828403121561278e57600080fd5b815160ff8116811461061057600080fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105ac576105ac61279f565b818103818111156105ac576105ac61279f565b6000602082840312156127ed57600080fd5b8151610610816125c4565b60006020828403121561280a57600080fd5b8151801515811461061057600080fd5b60008060006060848603121561282f57600080fd5b8351925060208401519150604084015190509250925092565b60006020828403121561285a57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a0868803121561288f57600080fd5b855161289a816125c4565b60208701519095506128ab816125c4565b60408701519094506128bc816125c4565b60608701519093506128cd816125c4565b60808701519092506128de816125c4565b809150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561293b5781518452928401929084019060010161291f565b50505092019290925292915050565b6000806040838503121561295d57600080fd5b505080516020909101519092909150565b60008251612980818460208701612536565b919091019291505056fea2646970667358221220850d22b1ba11f035bf015364ee858924d9af209cfdf73e7b69f4938235c7c48264736f6c63430008140033000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000fecab866b450b97db38500898e9272c1d18918b7","name":"CgUSD","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"@openzeppelin/contracts/access/Ownable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\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":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../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    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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 cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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":"@openzeppelin/contracts/utils/Pausable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    bool private _paused;\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"contracts/StToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { Pausable } from \"@openzeppelin/contracts/utils/Pausable.sol\";\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\nimport { UnstructuredStorage } from \"./lib/UnstructuredStorage.sol\";\n\nabstract contract StToken is IERC20, Pausable {\n    using FixedPointMathLib for uint256;\n    using UnstructuredStorage for bytes32;\n\n    address constant internal INITIAL_TOKEN_HOLDER = address(0xDEAD);\n    uint256 constant internal INFINITE_ALLOWANCE = type(uint256).max;\n\n    mapping (address => uint256) private shares;\n\n    mapping (address => mapping (address => uint256)) private allowances;\n\n    bytes32 internal constant TOTAL_SHARES_POSITION =\n        0x83da5a14a875cd105129c6639940ca67c63bf644cb010f348eec1dbad1a679be; // keccak256('cygnus.StToken.totalShares')\n\n    event TransferShares(\n        address indexed from,\n        address indexed to,\n        uint256 sharesValue\n    );\n\n    event SharesBurnt(\n        address indexed account,\n        uint256 preRebaseTokenAmount,\n        uint256 postRebaseTokenAmount,\n        uint256 sharesAmount\n    );\n\n    function name() external pure returns (string memory) {\n        return \"Cygnus Global USD\";\n    }\n\n    function symbol() external pure returns (string memory) {\n        return \"cgUSD\";\n    }\n\n    function decimals() external view virtual returns (uint8);\n\n    function totalSupply() external view returns (uint256) {\n        return _getTotalPooledAssets();\n    }\n\n    function getTotalPooledAssets() external view returns (uint256) {\n        return _getTotalPooledAssets();\n    }\n\n    function balanceOf(address _account) external view returns (uint256) {\n        return convertToAssets(_sharesOf(_account));\n    }\n\n    function transfer(address _recipient, uint256 _amount) external returns (bool) {\n        _transfer(msg.sender, _recipient, _amount);\n        return true;\n    }\n\n    function allowance(address _owner, address _spender) external view returns (uint256) {\n        return allowances[_owner][_spender];\n    }\n\n    function approve(address _spender, uint256 _amount) external returns (bool) {\n        _approve(msg.sender, _spender, _amount);\n        return true;\n    }\n\n    function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool) {\n        _spendAllowance(_sender, msg.sender, _amount);\n        _transfer(_sender, _recipient, _amount);\n        return true;\n    }\n\n    function increaseAllowance(address _spender, uint256 _addedValue) external returns (bool) {\n        _approve(msg.sender, _spender, allowances[msg.sender][_spender] + _addedValue);\n        return true;\n    }\n\n    function decreaseAllowance(address _spender, uint256 _subtractedValue) external returns (bool) {\n        uint256 currentAllowance = allowances[msg.sender][_spender];\n        require(currentAllowance >= _subtractedValue, \"ALLOWANCE_BELOW_ZERO\");\n        _approve(msg.sender, _spender, currentAllowance - _subtractedValue);\n        return true;\n    }\n\n    function getTotalShares() external view returns (uint256) {\n        return _getTotalShares();\n    }\n\n    function sharesOf(address _account) external view returns (uint256) {\n        return _sharesOf(_account);\n    }\n\n    function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256) {\n        _transferShares(msg.sender, _recipient, _sharesAmount);\n        uint256 tokensAmount = convertToAssets(_sharesAmount);\n        _emitTransferEvents(msg.sender, _recipient, tokensAmount, _sharesAmount);\n        return tokensAmount;\n    }\n\n    function transferSharesFrom(\n        address _sender, address _recipient, uint256 _sharesAmount\n    ) external returns (uint256) {\n        uint256 tokensAmount = convertToAssets(_sharesAmount);\n        _spendAllowance(_sender, msg.sender, tokensAmount);\n        _transferShares(_sender, _recipient, _sharesAmount);\n        _emitTransferEvents(_sender, _recipient, tokensAmount, _sharesAmount);\n        return tokensAmount;\n    }\n\n    function _getTotalPooledAssets() internal view virtual returns (uint256);\n\n    function _transfer(address _sender, address _recipient, uint256 _amount) internal {\n        uint256 _sharesToTransfer = convertToShares(_amount);\n        _transferShares(_sender, _recipient, _sharesToTransfer);\n        _emitTransferEvents(_sender, _recipient, _amount, _sharesToTransfer);\n    }\n\n    function _approve(address _owner, address _spender, uint256 _amount) internal {\n        require(_owner != address(0), \"APPROVE_FROM_ZERO_ADDR\");\n        require(_spender != address(0), \"APPROVE_TO_ZERO_ADDR\");\n\n        allowances[_owner][_spender] = _amount;\n        emit Approval(_owner, _spender, _amount);\n    }\n\n    function _spendAllowance(address _owner, address _spender, uint256 _amount) internal {\n        uint256 currentAllowance = allowances[_owner][_spender];\n        if (currentAllowance != INFINITE_ALLOWANCE) {\n            require(currentAllowance >= _amount, \"ALLOWANCE_EXCEEDED\");\n            _approve(_owner, _spender, currentAllowance - _amount);\n        }\n    }\n\n    function _getTotalShares() internal view returns (uint256) {\n        return TOTAL_SHARES_POSITION.getStorageUint256();\n    }\n\n    function _sharesOf(address _account) internal view returns (uint256) {\n        return shares[_account];\n    }\n\n    function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal {\n        _requireNotPaused();\n        require(_sender != address(0), \"TRANSFER_FROM_ZERO_ADDR\");\n        require(_recipient != address(0), \"TRANSFER_TO_ZERO_ADDR\");\n        require(_recipient != address(this), \"TRANSFER_TO_STETH_CONTRACT\");\n\n        uint256 currentSenderShares = shares[_sender];\n        require(_sharesAmount <= currentSenderShares, \"BALANCE_EXCEEDED\");\n\n        shares[_sender] = currentSenderShares - _sharesAmount;\n        shares[_recipient] = shares[_recipient] + _sharesAmount;\n    }\n\n    function _mintShares(address _recipient, uint256 _sharesAmount) internal returns (uint256 newTotalShares) {\n        require(_recipient != address(0), \"MINT_TO_ZERO_ADDR\");\n\n        newTotalShares = _getTotalShares() + _sharesAmount;\n        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);\n\n        shares[_recipient] = shares[_recipient] + _sharesAmount;\n    }\n\n    function _burnShares(address _account, uint256 _sharesAmount) internal returns (uint256 newTotalShares) {\n        require(_account != address(0), \"BURN_FROM_ZERO_ADDR\");\n\n        uint256 accountShares = shares[_account];\n        require(_sharesAmount <= accountShares, \"BALANCE_EXCEEDED\");\n\n        uint256 preRebaseTokenAmount = convertToAssets(_sharesAmount);\n\n        newTotalShares = _getTotalShares() - _sharesAmount;\n        TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares);\n\n        shares[_account] = accountShares - _sharesAmount;\n\n        uint256 postRebaseTokenAmount = convertToAssets(_sharesAmount);\n\n        emit SharesBurnt(_account, preRebaseTokenAmount, postRebaseTokenAmount, _sharesAmount);\n    }\n\n    function convertToShares(uint256 _assetsAmount) public view virtual returns (uint256) {\n        return _assetsAmount.mulDivDown(_getTotalShares(), _getTotalPooledAssets());\n    }\n\n    function convertToAssets(uint256 _sharesAmount) public view virtual returns (uint256) {\n        return _sharesAmount.mulDivDown(_getTotalPooledAssets(), _getTotalShares());\n    }\n\n    function _emitTransferEvents(address _from, address _to, uint _tokenAmount, uint256 _sharesAmount) internal {\n        emit Transfer(_from, _to, _tokenAmount);\n        emit TransferShares(_from, _to, _sharesAmount);\n    }\n\n    function _emitTransferAfterMintingShares(address _to, uint256 _sharesAmount) internal {\n        _emitTransferEvents(address(0), _to, convertToAssets(_sharesAmount), _sharesAmount);\n    }\n\n    function _mintInitialShares(uint256 _sharesAmount) internal {\n        _mintShares(INITIAL_TOKEN_HOLDER, _sharesAmount);\n        _emitTransferAfterMintingShares(INITIAL_TOKEN_HOLDER, _sharesAmount);\n    }\n\n    function previewDeposit(uint256 _assetsAmount) public view virtual returns (uint256) {\n        return convertToShares(_assetsAmount);\n    }\n\n    function previewMint(uint256 _sharesAmount) public view virtual returns (uint256) {\n        return _sharesAmount.mulDivUp(_getTotalPooledAssets(), _getTotalShares());\n    }\n\n    function previewWithdraw(uint256 _assetsAmount) public view virtual returns (uint256) {\n        return _assetsAmount.mulDivUp(_getTotalShares(), _getTotalPooledAssets());\n    }\n\n    function previewRedeem(uint256 _sharesAmount) public view virtual returns (uint256) {\n        return convertToAssets(_sharesAmount);\n    }\n}"},{"file_path":"contracts/interfaces/IBurner.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IBurner {\n    function commitSharesToBurn(uint256 _stETHSharesToBurn) external;\n\n    function requestBurnShares(address _from, uint256 _sharesAmount) external;\n\n    function getSharesRequestedToBurn() external view returns (uint256 coverShares, uint256 nonCoverShares);\n\n    function getCoverSharesBurnt() external view returns (uint256);\n\n    function getNonCoverSharesBurnt() external view returns (uint256);\n}"},{"file_path":"contracts/interfaces/ICgUSD.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ICgUSD {\n    function asset() external view returns (address);\n\n    function getTotalAssets() external view returns (uint256, uint256);\n\n    function mint(address _referral, uint256 _assetsAmount)\n        external\n        returns (uint256);\n\n    function invest(address _to, uint256 _assetsAmount) external;\n\n    function handleOracleReport(\n        uint256 _reportTimestamp,\n        uint256 _timeElapsed,\n        uint256 _newInvestedAssets,\n        uint256 _withdrawalVaultBalance,\n        uint256 _sharesRequestedToBurn,\n        uint256[] calldata _withdrawalFinalizationBatches,\n        uint256 _simulatedShareRate\n    ) external returns (uint256[3] memory);\n}"},{"file_path":"contracts/interfaces/ILocator.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ILocator {\n    function accountingOracle() external view returns (address);\n    function burner() external view returns (address);\n    function priceOracle() external view returns (address);\n    function withdrawQueue() external view returns (address);\n    function withdrawVault() external view returns (address);\n    function underlyingToken() external view returns (address);\n    function stToken() external view returns (address);\n    function treasury() external view returns (address);\n    function oracleReportSanityChecker() external view returns (address);\n\n    function coreComponents() external view returns (\n        address oracleReportSanityChecker,\n        address treasury,\n        address withdrawalQueue,\n        address withdrawalVault\n    );\n\n    function oracleReportComponents() external view returns (\n        address accountingOracle,\n        address oracleReportSanityChecker,\n        address burner,\n        address withdrawalQueue,\n        address withdrawalVault\n    );\n}"},{"file_path":"contracts/interfaces/IOracleReportSanityChecker.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IOracleReportSanityChecker {\n    function checkAccountingOracleReport(\n        uint256 _timeElapsed,\n        uint256 _withdrawalVaultBalance,\n        uint256 _sharesRequestedToBurn\n    ) external view;\n\n    function smoothenTokenRebase(\n        uint256 _preTotalPooledAssets,\n        uint256 _preTotalShares,\n        uint256 _withdrawalVaultBalance,\n        uint256 _sharesRequestedToBurn,\n        uint256 _assetsToLockForWithdrawals,\n        uint256 _newSharesToBurnForWithdrawals\n    ) external view returns (\n        uint256 withdrawals,\n        uint256 simulatedSharesToBurn,\n        uint256 sharesToBurn\n    );\n\n    function checkWithdrawalQueueOracleReport(\n        uint256 _lastFinalizableRequestId,\n        uint256 _reportTimestamp\n    ) external view;\n\n    function checkSimulatedShareRate(\n        uint256 _postTotalPooledAssets,\n        uint256 _postTotalShares,\n        uint256 _assetsLockedOnWithdrawalQueue,\n        uint256 _sharesBurntDueToWithdrawals,\n        uint256 _simulatedShareRate\n    ) external view;\n}"},{"file_path":"contracts/interfaces/IPausable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IPausable {\n    function pause() external;\n\n    function resume() external;\n}"},{"file_path":"contracts/interfaces/IWithdrawQueue.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IWithdrawQueueBase } from \"./IWithdrawQueueBase.sol\";\n\ninterface IWithdrawQueue is IWithdrawQueueBase {\n    struct PermitInput {\n        uint256 value;\n        uint256 deadline;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    function requestWithdrawals(\n        uint256[] calldata _amounts,\n        address _owner\n    ) external returns (uint256[] memory);\n\n    function requestWithdrawalsWstToken(\n        uint256[] calldata _amounts,\n        address _owner\n    ) external returns (uint256[] memory);\n\n    function requestWithdrawalsWithPermit(\n        uint256[] calldata _amounts,\n        address _owner,\n        PermitInput calldata _permit\n    ) external returns (uint256[] memory);\n\n    function requestWithdrawalsWstTokenWithPermit(\n        uint256[] calldata _amounts,\n        address _owner,\n        PermitInput calldata _permit\n    ) external returns (uint256[] memory);\n\n    function getWithdrawalRequests(address _owner) external view returns (uint256[] memory);\n\n    function getWithdrawalStatus(uint256[] calldata _requestIds)\n        external\n        view\n        returns (WithdrawalRequestStatus[] memory);\n\n    function getClaimableAssets(uint256[] calldata _requestIds, uint256[] calldata _hints)\n        external\n        view\n        returns (uint256[] memory);\n\n    function claimWithdrawalsTo(\n        uint256[] calldata _requestIds,\n        uint256[] calldata _hints,\n        address _recipient\n    ) external;\n\n    function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;\n\n    function claimWithdrawal(uint256 _requestId) external;\n\n    function findCheckpointHints(uint256[] calldata _requestIds, uint256 _firstIndex, uint256 _lastIndex)\n        external\n        view\n        returns (uint256[] memory);\n\n    function onOracleReport(\n        bool _isBunkerModeNow,\n        uint256 _bunkerStartTimestamp,\n        uint256 _currentReportTimestamp\n    ) external;\n\n    function isBunkerModeActive() external view returns (bool);\n\n    function bunkerModeSinceTimestamp() external view returns (uint256);\n}"},{"file_path":"contracts/interfaces/IWithdrawQueueBase.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IWithdrawQueueBase {\n    struct WithdrawalRequestStatus {\n        uint256 amountOfAssets;\n        uint256 amountOfShares;\n        address owner;\n        uint256 timestamp;\n        bool isFinalized;\n        bool isClaimed;\n    }\n\n    struct BatchesCalculationState {\n        uint256 remainingAssetsBudget;\n        bool finished;\n        uint256[36] batches;\n        uint256 batchesLength;\n    }\n\n    function getLastRequestId() external view returns (uint256);\n\n    function getLastFinalizedRequestId() external view returns (uint256);\n\n    function getLockedAssetsAmount() external view returns (uint256);\n\n    function getLastCheckpointIndex() external view returns (uint256);\n\n    function unfinalizedRequestNumber() external view returns (uint256);\n\n    function unfinalizedAssets() external view returns (uint256);\n\n    function calculateFinalizationBatches(\n        uint256 _maxShareRate,\n        uint256 _maxTimestamp,\n        uint256 _maxRequestsPerCall,\n        BatchesCalculationState memory _state\n    ) external view returns (BatchesCalculationState memory);\n\n    function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate)\n        external\n        view\n        returns (uint256 assetsToLock, uint256 sharesToBurn);\n}"},{"file_path":"contracts/interfaces/IWithdrawQueueERC721.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IWithdrawQueue } from \"./IWithdrawQueue.sol\";\n\ninterface IWithdrawQueueERC721 is IWithdrawQueue {\n    function finalize(\n        uint256 _lastRequestIdToBeFinalized,\n        uint256 _maxShareRate,\n        uint256 _amount\n    ) external;\n}"},{"file_path":"contracts/interfaces/IWithdrawVault.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IWithdrawVault {\n    function asset() external view returns (address);\n    function withdrawWithdrawals(uint256 _amount) external;\n}"},{"file_path":"contracts/lib/UnstructuredStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary UnstructuredStorage {\n    function getStorageBool(bytes32 position) internal view returns (bool data) {\n        assembly { data := sload(position) }\n    }\n\n    function getStorageAddress(bytes32 position) internal view returns (address data) {\n        assembly { data := sload(position) }\n    }\n\n    function getStorageBytes32(bytes32 position) internal view returns (bytes32 data) {\n        assembly { data := sload(position) }\n    }\n\n    function getStorageUint256(bytes32 position) internal view returns (uint256 data) {\n        assembly { data := sload(position) }\n    }\n\n    function setStorageBool(bytes32 position, bool data) internal {\n        assembly { sstore(position, data) }\n    }\n\n    function setStorageAddress(bytes32 position, address data) internal {\n        assembly { sstore(position, data) }\n    }\n\n    function setStorageBytes32(bytes32 position, bytes32 data) internal {\n        assembly { sstore(position, data) }\n    }\n\n    function setStorageUint256(bytes32 position, uint256 data) internal {\n        assembly { sstore(position, data) }\n    }\n}"},{"file_path":"solmate/src/utils/FixedPointMathLib.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(\n        uint256 x,\n        uint256 n,\n        uint256 scalar\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"reportTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postBufferedAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postInvestedAssets","type":"uint256"}],"name":"AssetsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postBufferedAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postInvestedAssets","type":"uint256"}],"name":"Invested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"locator","type":"address"}],"name":"LocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"reportTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeElapsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"preTotalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"preTotalAssets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postTotalShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"postTotalAssets","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLocator","outputs":[{"internalType":"contract ILocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPooledAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"},{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_newInvestedAssets","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256[]","name":"_withdrawalFinalizationBatches","type":"uint256[]"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"internalType":"uint256[3]","name":"postRebaseAmounts","type":"uint256[3]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_locator","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"invest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referral","type":"address"},{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetsAmount","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000fecab866b450b97db38500898e9272c1d18918b7"}