creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/v2/AeraVaultAssetRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/ERC165.sol\";\nimport \"@openzeppelin/IERC4626.sol\";\nimport \"./Sweepable.sol\";\nimport \"./interfaces/IAssetRegistry.sol\";\nimport \"./interfaces/IVault.sol\";\nimport {ONE} from \"./Constants.sol\";\n\n/// @title AeraVaultAssetRegistry\n/// @notice Maintains a list of registered assets and their oracles (when applicable).\ncontract AeraVaultAssetRegistry is IAssetRegistry, Sweepable, ERC165 {\n    /// @notice Maximum number of assets.\n    uint256 public constant MAX_ASSETS = 50;\n\n    /// @notice Time to pass before accepting answers when sequencer comes back up.\n    uint256 public constant GRACE_PERIOD_TIME = 3600;\n\n    /// @notice Vault address.\n    address public immutable vault;\n\n    /// @notice Numeraire token.\n    IERC20 public immutable numeraireToken;\n\n    /// @notice Fee token.\n    IERC20 public immutable feeToken;\n\n    /// @notice Wrapped native token.\n    IERC20 public immutable wrappedNativeToken;\n\n    /// @notice Sequencer Uptime Feed address for L2.\n    AggregatorV2V3Interface public immutable sequencer;\n\n    /// STORAGE ///\n\n    /// @notice List of currently registered assets.\n    AssetInformation[] internal _assets;\n\n    /// @notice Number of ERC4626 assets. Maintained for more efficient calculation of spotPrices.\n    uint256 public numYieldAssets;\n\n    /// EVENTS ///\n\n    /// @notice Emitted when a new asset is added.\n    /// @param asset New asset details.\n    event AssetAdded(address indexed asset, AssetInformation assetInfo);\n\n    /// @notice Emitted when an asset is removed.\n    /// @param asset Address of removed asset.\n    event AssetRemoved(address indexed asset);\n\n    /// @notice Emitted in constructor.\n    /// @param owner Owner address.\n    /// @param vault Vault address.\n    /// @param assets Initial list of registered assets.\n    /// @param numeraireToken Numeraire token address.\n    /// @param feeToken Fee token address.\n    /// @param wrappedNativeToken Wrapped native token.\n    /// @param sequencer Sequencer Uptime Feed address for L2.\n    event Created(\n        address indexed owner,\n        address indexed vault,\n        AssetInformation[] assets,\n        address indexed numeraireToken,\n        address feeToken,\n        address wrappedNativeToken,\n        address sequencer\n    );\n\n    /// ERRORS ///\n\n    error Aera__NumberOfAssetsExceedsMaximum(uint256 max);\n    error Aera__NumeraireTokenIsNotRegistered(address numeraireToken);\n    error Aera__NumeraireTokenIsERC4626();\n    error Aera__NumeraireOracleIsNotZeroAddress();\n    error Aera__FeeTokenIsNotRegistered(address feeToken);\n    error Aera__FeeTokenIsERC4626(address feeToken);\n    error Aera__WrappedNativeTokenIsNotRegistered(address wrappedNativeToken);\n    error Aera__WrappedNativeTokenIsERC4626(address wrappedNativeToken);\n    error Aera__AssetOrderIsIncorrect(uint256 index);\n    error Aera__AssetRegistryInitialOwnerIsZeroAddress();\n    error Aera__AssetRegistryOwnerIsGuardian();\n    error Aera__AssetRegistryOwnerIsVault();\n    error Aera__ERC20OracleIsZeroAddress(address asset);\n    error Aera__ERC4626OracleIsNotZeroAddress(address asset);\n    error Aera__UnderlyingAssetIsNotRegistered(\n        address asset, address underlyingAsset\n    );\n    error Aera__UnderlyingAssetIsItselfERC4626();\n    error Aera__AssetIsUnderlyingAssetOfERC4626(address erc4626Asset);\n    error Aera__AssetIsAlreadyRegistered(uint256 index);\n    error Aera__AssetNotRegistered(address asset);\n    error Aera__CannotRemoveNumeraireToken(address asset);\n    error Aera__CannotRemoveFeeToken(address feeToken);\n    error Aera__CannotRemoveWrappedNativeToken(address wrappedNativeToken);\n    error Aera__VaultIsZeroAddress();\n    error Aera__SequencerIsDown();\n    error Aera__GracePeriodNotOver();\n    error Aera__OraclePriceIsInvalid(AssetInformation asset, int256 actual);\n    error Aera__OraclePriceIsTooOld(AssetInformation asset, uint256 updatedAt);\n\n    /// FUNCTIONS ///\n\n    /// @param owner_ Initial owner address.\n    /// @param vault_ Vault address.\n    /// @param assets_ Initial list of registered assets.\n    /// @param numeraireToken_ Numeraire token address.\n    /// @param feeToken_ Fee token address.\n    /// @param wrappedNativeToken_ Wrapped native token address.\n    /// @param sequencer_ Sequencer Uptime Feed address for L2.\n    constructor(\n        address owner_,\n        address vault_,\n        AssetInformation[] memory assets_,\n        IERC20 numeraireToken_,\n        IERC20 feeToken_,\n        IERC20 wrappedNativeToken_,\n        AggregatorV2V3Interface sequencer_\n    ) Ownable() {\n        // Requirements: confirm that owner is not zero address.\n        if (owner_ == address(0)) {\n            revert Aera__AssetRegistryInitialOwnerIsZeroAddress();\n        }\n\n        // Requirements: check that an address has been provided.\n        if (vault_ == address(0)) {\n            revert Aera__VaultIsZeroAddress();\n        }\n\n        // Requirements: check that asset registry initial owner is not the computed vault address.\n        if (owner_ == vault_) {\n            revert Aera__AssetRegistryOwnerIsVault();\n        }\n\n        uint256 numAssets = assets_.length;\n\n        // Requirements: confirm that number of assets is within bounds.\n        if (numAssets > MAX_ASSETS) {\n            revert Aera__NumberOfAssetsExceedsMaximum(MAX_ASSETS);\n        }\n\n        // Calculate the Numeraire token index.\n        uint256 numeraireIndex = 0;\n        for (; numeraireIndex < numAssets;) {\n            if (assets_[numeraireIndex].asset == numeraireToken_) {\n                break;\n            }\n            unchecked {\n                numeraireIndex++; // gas savings\n            }\n        }\n\n        // Calculate the fee token index.\n        uint256 feeTokenIndex = 0;\n        for (; feeTokenIndex < numAssets;) {\n            if (assets_[feeTokenIndex].asset == feeToken_) {\n                break;\n            }\n            unchecked {\n                feeTokenIndex++; // gas savings\n            }\n        }\n\n        // Calculate the wrapped native token index.\n        uint256 wrappedNativeTokenIndex = 0;\n        for (; wrappedNativeTokenIndex < numAssets;) {\n            if (assets_[wrappedNativeTokenIndex].asset == wrappedNativeToken_)\n            {\n                break;\n            }\n            unchecked {\n                wrappedNativeTokenIndex++; // gas savings\n            }\n        }\n\n        // Requirements: confirm that Numeraire token is present.\n        if (numeraireIndex >= numAssets) {\n            revert Aera__NumeraireTokenIsNotRegistered(\n                address(numeraireToken_)\n            );\n        }\n\n        // Requirements: confirm that numeraire is not an ERC4626 asset.\n        if (assets_[numeraireIndex].isERC4626) {\n            revert Aera__NumeraireTokenIsERC4626();\n        }\n\n        // Requirements: confirm that numeraire does not have a specified oracle.\n        if (address(assets_[numeraireIndex].oracle) != address(0)) {\n            revert Aera__NumeraireOracleIsNotZeroAddress();\n        }\n\n        // Requirements: confirm that fee token is present.\n        if (feeTokenIndex >= numAssets) {\n            revert Aera__FeeTokenIsNotRegistered(address(feeToken_));\n        }\n\n        // Requirements: check that fee token is not an ERC4626.\n        if (assets_[feeTokenIndex].isERC4626) {\n            revert Aera__FeeTokenIsERC4626(address(feeToken_));\n        }\n\n        // Requirements: confirm that wrapped native token is present.\n        if (wrappedNativeTokenIndex >= numAssets) {\n            revert Aera__WrappedNativeTokenIsNotRegistered(\n                address(wrappedNativeToken_)\n            );\n        }\n\n        // Requirements: check that wrapped native token is not an ERC4626.\n        if (assets_[wrappedNativeTokenIndex].isERC4626) {\n            revert Aera__WrappedNativeTokenIsERC4626(\n                address(wrappedNativeToken_)\n            );\n        }\n\n        // Requirements: confirm that assets are sorted by address.\n        for (uint256 i = 1; i < numAssets;) {\n            if (assets_[i - 1].asset >= assets_[i].asset) {\n                revert Aera__AssetOrderIsIncorrect(i);\n            }\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        for (uint256 i = 0; i < numAssets;) {\n            if (i != numeraireIndex) {\n                // Requirements: check asset oracle is correctly specified.\n                _checkAssetOracle(assets_[i]);\n\n                if (assets_[i].isERC4626) {\n                    // Requirements: check that underlying asset is a registered ERC20.\n                    _checkUnderlyingAsset(assets_[i], assets_);\n                }\n            }\n\n            // Effects: add asset to array.\n            _insertAsset(assets_[i], i);\n\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        // Effects: set vault, numeraire, fee token, wrapped native token\n        //          and sequencer uptime feed.\n        vault = vault_;\n        numeraireToken = numeraireToken_;\n        feeToken = feeToken_;\n        wrappedNativeToken = wrappedNativeToken_;\n        sequencer = sequencer_;\n\n        // Effects: set new owner.\n        _transferOwnership(owner_);\n\n        // Log asset registry creation.\n        emit Created(\n            owner_,\n            vault_,\n            assets_,\n            address(numeraireToken_),\n            address(feeToken_),\n            address(wrappedNativeToken_),\n            address(sequencer)\n        );\n    }\n\n    /// @notice Add a new asset.\n    /// @param asset Asset information for new asset.\n    /// @dev MUST revert if not called by owner.\n    /// @dev MUST revert if asset with the same address exists.\n    function addAsset(AssetInformation calldata asset) external onlyOwner {\n        uint256 numAssets = _assets.length;\n\n        // Requirements: validate number of assets doesn't exceed bound.\n        if (numAssets >= MAX_ASSETS) {\n            revert Aera__NumberOfAssetsExceedsMaximum(MAX_ASSETS);\n        }\n\n        // Requirements: validate oracle field for asset struct.\n        _checkAssetOracle(asset);\n\n        uint256 i = 0;\n\n        // Find the index to insert the new asset.\n        for (; i < numAssets;) {\n            if (asset.asset < _assets[i].asset) {\n                break;\n            }\n\n            // Requirements: check that asset is not already present.\n            if (asset.asset == _assets[i].asset) {\n                revert Aera__AssetIsAlreadyRegistered(i);\n            }\n\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        // Requirements: check that underlying asset is a registered ERC20.\n        if (asset.isERC4626) {\n            _checkUnderlyingAsset(asset, _assets);\n        }\n\n        // Effects: insert asset at position i.\n        _insertAsset(asset, i);\n    }\n\n    /// @notice Remove an asset.\n    /// @param asset An asset to remove.\n    /// @dev MUST revert if not called by owner.\n    function removeAsset(address asset) external onlyOwner {\n        // Requirements: confirm that asset to remove is not numeraire.\n        if (asset == address(numeraireToken)) {\n            revert Aera__CannotRemoveNumeraireToken(asset);\n        }\n\n        // Requirements: check that asset to remove is not fee token.\n        if (asset == address(feeToken)) {\n            revert Aera__CannotRemoveFeeToken(asset);\n        }\n\n        // Requirements: check that asset to remove is not wrapped native token.\n        if (asset == address(wrappedNativeToken)) {\n            revert Aera__CannotRemoveWrappedNativeToken(asset);\n        }\n\n        uint256 numAssets = _assets.length;\n        uint256 oldAssetIndex = 0;\n        // Find index of asset.\n        for (\n            ;\n            oldAssetIndex < numAssets\n                && address(_assets[oldAssetIndex].asset) != asset;\n        ) {\n            unchecked {\n                oldAssetIndex++; // gas savings\n            }\n        }\n\n        // Requirements: check that asset is registered.\n        if (oldAssetIndex >= numAssets) {\n            revert Aera__AssetNotRegistered(asset);\n        }\n\n        // Effects: adjust the number of ERC4626 assets.\n        if (_assets[oldAssetIndex].isERC4626) {\n            numYieldAssets--;\n        } else {\n            for (uint256 i = 0; i < numAssets;) {\n                if (\n                    i != oldAssetIndex && _assets[i].isERC4626\n                        && IERC4626(address(_assets[i].asset)).asset() == asset\n                ) {\n                    revert Aera__AssetIsUnderlyingAssetOfERC4626(\n                        address(_assets[i].asset)\n                    );\n                }\n                unchecked {\n                    i++; // gas savings\n                }\n            }\n        }\n\n        uint256 nextIndex;\n        uint256 lastIndex = numAssets - 1;\n        // Slide all elements after oldAssetIndex left.\n        for (uint256 i = oldAssetIndex; i < lastIndex;) {\n            nextIndex = i + 1;\n            _assets[i] = _assets[nextIndex];\n\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        // Effects: remove asset from array.\n        _assets.pop();\n\n        // Log removal.\n        emit AssetRemoved(asset);\n    }\n\n    /// @inheritdoc IAssetRegistry\n    function assets()\n        external\n        view\n        override\n        returns (AssetInformation[] memory)\n    {\n        return _assets;\n    }\n\n    /// @inheritdoc IAssetRegistry\n    function spotPrices()\n        external\n        view\n        override\n        returns (AssetPriceReading[] memory)\n    {\n        int256 answer;\n        uint256 startedAt;\n\n        // Requirements: check that sequencer is up.\n        if (address(sequencer) != address(0)) {\n            (, answer, startedAt,,) = sequencer.latestRoundData();\n\n            // Answer == 0: Sequencer is up\n            // Requirements: check that the sequencer is up.\n            if (answer != 0) {\n                revert Aera__SequencerIsDown();\n            }\n\n            // Requirements: check that the grace period has passed after the\n            //               sequencer is back up.\n            if (block.timestamp < startedAt + GRACE_PERIOD_TIME) {\n                revert Aera__GracePeriodNotOver();\n            }\n        }\n\n        // Prepare price array.\n        uint256 numAssets = _assets.length;\n        AssetPriceReading[] memory prices = new AssetPriceReading[](\n            numAssets - numYieldAssets\n        );\n\n        uint256 oracleDecimals;\n        uint256 price;\n        uint256 index = 0;\n        for (uint256 i = 0; i < numAssets;) {\n            if (_assets[i].isERC4626) {\n                unchecked {\n                    i++; // gas savings\n                }\n                continue;\n            }\n\n            if (_assets[i].asset == numeraireToken) {\n                // Numeraire has price 1 by definition.\n                prices[index] = AssetPriceReading({\n                    asset: _assets[i].asset,\n                    spotPrice: ONE\n                });\n            } else {\n                price = _checkOraclePrice(_assets[i]);\n                oracleDecimals = _assets[i].oracle.decimals();\n\n                if (oracleDecimals < 18) {\n                    // slither-disable-next-line divide-before-multiply\n                    price = price * (10 ** (18 - oracleDecimals));\n                } else if (oracleDecimals > 18) {\n                    // slither-disable-next-line divide-before-multiply\n                    price = price / (10 ** (oracleDecimals - 18));\n                }\n\n                prices[index] = AssetPriceReading({\n                    asset: _assets[i].asset,\n                    spotPrice: price\n                });\n            }\n\n            unchecked {\n                // gas savings\n                index++;\n                i++;\n            }\n        }\n\n        return prices;\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override\n        returns (bool)\n    {\n        return interfaceId == type(IAssetRegistry).interfaceId\n            || super.supportsInterface(interfaceId);\n    }\n\n    /// INTERNAL FUNCTIONS ///\n\n    /// @notice Ensure non-zero oracle address for ERC20\n    ///         and zero oracle address for ERC4626.\n    /// @param asset Asset details to check\n    function _checkAssetOracle(AssetInformation memory asset) internal view {\n        if (asset.isERC4626) {\n            // ERC4626 asset should not have a specified oracle.\n            if (address(asset.oracle) != address(0)) {\n                revert Aera__ERC4626OracleIsNotZeroAddress(\n                    address(asset.asset)\n                );\n            }\n        } else {\n            // ERC20 asset should have non-zero oracle address.\n            if (address(asset.oracle) == address(0)) {\n                revert Aera__ERC20OracleIsZeroAddress(address(asset.asset));\n            }\n\n            // Requirements: validate oracle price.\n            _checkOraclePrice(asset);\n        }\n    }\n\n    /// @notice Ensure oracle returns valid value and it's up to date.\n    /// @param asset Asset details to check.\n    /// @return price Valid oracle price.\n    function _checkOraclePrice(AssetInformation memory asset)\n        internal\n        view\n        returns (uint256 price)\n    {\n        (, int256 answer,, uint256 updatedAt,) = asset.oracle.latestRoundData();\n\n        // Check price staleness\n        if (answer <= 0) {\n            revert Aera__OraclePriceIsInvalid(asset, answer);\n        }\n        if (\n            asset.heartbeat > 0\n                && updatedAt + asset.heartbeat + 1 hours < block.timestamp\n        ) {\n            revert Aera__OraclePriceIsTooOld(asset, updatedAt);\n        }\n\n        price = uint256(answer);\n    }\n\n    /// @notice Check whether the underlying asset is listed as an ERC20.\n    /// @dev Will revert if underlying asset is an ERC4626.\n    /// @param asset ERC4626 asset to check underlying asset.\n    /// @param assetsToCheck Array of assets.\n    function _checkUnderlyingAsset(\n        AssetInformation memory asset,\n        AssetInformation[] memory assetsToCheck\n    ) internal view {\n        uint256 numAssets = assetsToCheck.length;\n\n        address underlyingAsset = IERC4626(address(asset.asset)).asset();\n        uint256 underlyingIndex = 0;\n\n        for (; underlyingIndex < numAssets;) {\n            if (\n                underlyingAsset\n                    == address(assetsToCheck[underlyingIndex].asset)\n            ) {\n                break;\n            }\n\n            unchecked {\n                underlyingIndex++; // gas savings\n            }\n        }\n\n        if (underlyingIndex >= numAssets) {\n            revert Aera__UnderlyingAssetIsNotRegistered(\n                address(asset.asset), underlyingAsset\n            );\n        }\n\n        if (assetsToCheck[underlyingIndex].isERC4626) {\n            revert Aera__UnderlyingAssetIsItselfERC4626();\n        }\n    }\n\n    /// @notice Insert asset at the given index in an array of assets.\n    /// @param asset New asset details.\n    /// @param index Index of the new asset in the asset array.\n    function _insertAsset(\n        AssetInformation memory asset,\n        uint256 index\n    ) internal {\n        uint256 numAssets = _assets.length;\n\n        if (index == numAssets) {\n            // Effects: insert new asset at the end.\n            _assets.push(asset);\n        } else {\n            // Effects: push last elements to the right and insert new asset.\n            _assets.push(_assets[numAssets - 1]);\n\n            uint256 prevIndex;\n            for (uint256 i = numAssets - 1; i > index; i--) {\n                prevIndex = i - 1;\n                _assets[i] = _assets[prevIndex];\n            }\n\n            _assets[index] = asset;\n        }\n\n        // Effects: adjust the number of ERC4626 assets.\n        if (asset.isERC4626) {\n            numYieldAssets++;\n        }\n\n        // Log asset added.\n        emit AssetAdded(address(asset.asset), asset);\n    }\n\n    /// @notice Check that owner is not the vault or the guardian.\n    /// @param owner_ Asset registry owner address.\n    /// @param vault_ Vault address.\n    function _checkAssetRegistryOwner(\n        address owner_,\n        address vault_\n    ) internal view {\n        if (owner_ == vault_) {\n            revert Aera__AssetRegistryOwnerIsVault();\n        }\n\n        address guardian = IVault(vault_).guardian();\n        if (owner_ == guardian) {\n            revert Aera__AssetRegistryOwnerIsGuardian();\n        }\n    }\n\n    /// @inheritdoc Ownable2Step\n    function transferOwnership(address newOwner) public override onlyOwner {\n        // Requirements: check that new owner is disaffiliated from existing roles.\n        _checkAssetRegistryOwner(newOwner, vault);\n\n        // Effects: initiate ownership transfer.\n        super.transferOwnership(newOwner);\n    }\n}\n"
      },
      "src/v2/dependencies/openzeppelin/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC165.sol\";\r\n\r\n/**\r\n * @dev Implementation of the {IERC165} interface.\r\n *\r\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\r\n * for the additional interface id that will be supported. For example:\r\n *\r\n * ```solidity\r\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\r\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\r\n * }\r\n * ```\r\n *\r\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\r\n */\r\nabstract contract ERC165 is IERC165 {\r\n    /**\r\n     * @dev See {IERC165-supportsInterface}.\r\n     */\r\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\r\n        return interfaceId == type(IERC165).interfaceId;\r\n    }\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/IERC4626.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20.sol\";\r\nimport \"./IERC20Metadata.sol\";\r\n\r\n/**\r\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\r\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\r\n *\r\n * _Available since v4.7._\r\n */\r\ninterface IERC4626 is IERC20, IERC20Metadata {\r\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\r\n\r\n    event Withdraw(\r\n        address indexed sender,\r\n        address indexed receiver,\r\n        address indexed owner,\r\n        uint256 assets,\r\n        uint256 shares\r\n    );\r\n\r\n    /**\r\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\r\n     *\r\n     * - MUST be an ERC-20 token contract.\r\n     * - MUST NOT revert.\r\n     */\r\n    function asset() external view returns (address assetTokenAddress);\r\n\r\n    /**\r\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\r\n     *\r\n     * - SHOULD include any compounding that occurs from yield.\r\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT revert.\r\n     */\r\n    function totalAssets() external view returns (uint256 totalManagedAssets);\r\n\r\n    /**\r\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\r\n     * scenario where all the conditions are met.\r\n     *\r\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT show any variations depending on the caller.\r\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\r\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\r\n     * from.\r\n     */\r\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\r\n     * scenario where all the conditions are met.\r\n     *\r\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\r\n     * - MUST NOT show any variations depending on the caller.\r\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\r\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\r\n     * from.\r\n     */\r\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\r\n     * through a deposit call.\r\n     *\r\n     * - MUST return a limited value if receiver is subject to some deposit limit.\r\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\r\n     * current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\r\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\r\n     *   in the same transaction.\r\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\r\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\r\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\r\n     */\r\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\r\n     *\r\n     * - MUST emit the Deposit event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   deposit execution, and are accounted for during deposit.\r\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\r\n     *   approving enough underlying tokens to the Vault contract, etc).\r\n     *\r\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\r\n     */\r\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\r\n     * - MUST return a limited value if receiver is subject to some mint limit.\r\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxMint(address receiver) external view returns (uint256 maxShares);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\r\n     * current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\r\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\r\n     *   same transaction.\r\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\r\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\r\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\r\n     */\r\n    function previewMint(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\r\n     *\r\n     * - MUST emit the Deposit event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\r\n     *   execution, and are accounted for during mint.\r\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\r\n     *   approving enough underlying tokens to the Vault contract, etc).\r\n     *\r\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\r\n     */\r\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\r\n     * Vault, through a withdraw call.\r\n     *\r\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\r\n     * given current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\r\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\r\n     *   called\r\n     *   in the same transaction.\r\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\r\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\r\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\r\n     */\r\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\r\n     *\r\n     * - MUST emit the Withdraw event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   withdraw execution, and are accounted for during withdraw.\r\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\r\n     *   not having enough shares, etc).\r\n     *\r\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\r\n     * Those methods should be performed separately.\r\n     */\r\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\r\n\r\n    /**\r\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\r\n     * through a redeem call.\r\n     *\r\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\r\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\r\n     * - MUST NOT revert.\r\n     */\r\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\r\n\r\n    /**\r\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\r\n     * given current on-chain conditions.\r\n     *\r\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\r\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\r\n     *   same transaction.\r\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\r\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\r\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\r\n     * - MUST NOT revert.\r\n     *\r\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\r\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\r\n     */\r\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\r\n\r\n    /**\r\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\r\n     *\r\n     * - MUST emit the Withdraw event.\r\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\r\n     *   redeem execution, and are accounted for during redeem.\r\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\r\n     *   not having enough shares, etc).\r\n     *\r\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\r\n     * Those methods should be performed separately.\r\n     */\r\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\r\n}\r\n"
      },
      "src/v2/Sweepable.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/Ownable2Step.sol\";\nimport \"@openzeppelin/SafeERC20.sol\";\nimport \"./interfaces/ISweepable.sol\";\n\n/// @title Sweepable.\n/// @notice Aera Sweepable contract.\n/// @dev Allows owner of the contract to restore accidentally send tokens\n//       and the chain's native token.\ncontract Sweepable is ISweepable, Ownable2Step {\n    using SafeERC20 for IERC20;\n\n    /// @inheritdoc ISweepable\n    function sweep(address token, uint256 amount) external onlyOwner {\n        if (token == address(0)) {\n            msg.sender.call{value: amount}(\"\");\n        } else {\n            IERC20(token).safeTransfer(msg.sender, amount);\n        }\n\n        emit Sweep(token, amount);\n    }\n}\n"
      },
      "src/v2/interfaces/IAssetRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@chainlink/interfaces/AggregatorV2V3Interface.sol\";\nimport \"@openzeppelin/IERC20.sol\";\n\n/// @title IAssetRegistry\n/// @notice Asset registry interface.\n/// @dev Any implementation MUST also implement Ownable2Step and ERC165.\ninterface IAssetRegistry {\n    /// @param asset Asset address.\n    /// @param heartbeat Frequency of oracle price updates.\n    /// @param isERC4626 True if yield-bearing asset, false if just an ERC20 asset.\n    /// @param oracle If applicable, oracle address for asset.\n    struct AssetInformation {\n        IERC20 asset;\n        uint256 heartbeat;\n        bool isERC4626;\n        AggregatorV2V3Interface oracle;\n    }\n\n    /// @param asset Asset address.\n    /// @param spotPrice Spot price of an asset in Numeraire token terms.\n    struct AssetPriceReading {\n        IERC20 asset;\n        uint256 spotPrice;\n    }\n\n    /// @notice Get address of vault.\n    /// @return vault Address of vault.\n    function vault() external view returns (address vault);\n\n    /// @notice Get a list of all registered assets.\n    /// @return assets List of assets.\n    /// @dev MUST return assets in an order sorted by address.\n    function assets()\n        external\n        view\n        returns (AssetInformation[] memory assets);\n\n    /// @notice Get address of fee token.\n    /// @return feeToken Address of fee token.\n    /// @dev Represented as an address for efficiency reasons.\n    /// @dev MUST be present in assets array.\n    function feeToken() external view returns (IERC20 feeToken);\n\n    /// @notice Get the index of the Numeraire token in the assets array.\n    /// @return numeraireToken Numeraire token address.\n    /// @dev Represented as an index for efficiency reasons.\n    /// @dev MUST be a number between 0 (inclusive) and the length of assets array (exclusive).\n    function numeraireToken() external view returns (IERC20 numeraireToken);\n\n    /// @notice Calculate spot prices of non-ERC4626 assets.\n    /// @return spotPrices Spot prices of non-ERC4626 assets in 18 decimals.\n    /// @dev MUST return assets in the same order as in assets but with ERC4626 assets filtered out.\n    /// @dev MUST also include Numeraire token (spot price = 1).\n    /// @dev MAY revert if oracle prices for any asset are unreliable at the time.\n    function spotPrices()\n        external\n        view\n        returns (AssetPriceReading[] memory spotPrices);\n}\n"
      },
      "src/v2/interfaces/IVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/IERC20.sol\";\nimport \"./IAssetRegistry.sol\";\nimport \"./IVaultEvents.sol\";\nimport \"./IHooks.sol\";\n\n/// @title IVault\n/// @notice Interface for the vault.\n/// @dev Any implementation MUST also implement Ownable2Step.\ninterface IVault is IVaultEvents {\n    /// ERRORS ///\n\n    error Aera__AssetRegistryIsZeroAddress();\n    error Aera__AssetRegistryIsNotValid(address assetRegistry);\n    error Aera__AssetRegistryHasInvalidVault();\n    error Aera__HooksIsZeroAddress();\n    error Aera__HooksIsNotValid(address hooks);\n    error Aera__HooksHasInvalidVault();\n    error Aera__GuardianIsZeroAddress();\n    error Aera__GuardianIsOwner();\n    error Aera__InitialOwnerIsZeroAddress();\n    error Aera__FeeRecipientIsZeroAddress();\n    error Aera__ExecuteTargetIsHooksAddress();\n    error Aera__ExecuteTargetIsVaultAddress();\n    error Aera__SubmitTransfersAssetFromOwner();\n    error Aera__SubmitRedeemERC4626AssetFromOwner();\n    error Aera__SubmitTargetIsVaultAddress();\n    error Aera__SubmitTargetIsHooksAddress(uint256 index);\n    error Aera__FeeRecipientIsOwner();\n    error Aera__FeeIsAboveMax(uint256 actual, uint256 max);\n    error Aera__CallerIsNotOwnerAndGuardian();\n    error Aera__CallerIsNotGuardian();\n    error Aera__AssetIsNotRegistered(IERC20 asset);\n    error Aera__AmountExceedsAvailable(\n        IERC20 asset, uint256 amount, uint256 available\n    );\n    error Aera__ExecutionFailed(bytes result);\n    error Aera__VaultIsFinalized();\n    error Aera__SubmissionFailed(uint256 index, bytes result);\n    error Aera__CannotUseReservedFees();\n    error Aera__SpotPricesReverted();\n    error Aera__AmountsOrderIsIncorrect(uint256 index);\n    error Aera__NoAvailableFeesForCaller(address caller);\n    error Aera__NoClaimableFeesForCaller(address caller);\n    error Aera__NotWrappedNativeTokenContract();\n    error Aera__CannotRenounceOwnership();\n\n    /// FUNCTIONS ///\n\n    /// @notice Deposit assets.\n    /// @param amounts Assets and amounts to deposit.\n    /// @dev MUST revert if not called by owner.\n    function deposit(AssetValue[] memory amounts) external;\n\n    /// @notice Withdraw assets.\n    /// @param amounts Assets and amounts to withdraw.\n    /// @dev MUST revert if not called by owner.\n    function withdraw(AssetValue[] memory amounts) external;\n\n    /// @notice Set current guardian and fee recipient.\n    /// @param guardian New guardian address.\n    /// @param feeRecipient New fee recipient address.\n    /// @dev MUST revert if not called by owner.\n    function setGuardianAndFeeRecipient(\n        address guardian,\n        address feeRecipient\n    ) external;\n\n    /// @notice Sets the current hooks module.\n    /// @param hooks New hooks module address.\n    /// @dev MUST revert if not called by owner.\n    function setHooks(address hooks) external;\n\n    /// @notice Execute a transaction via the vault.\n    /// @dev Execution still should work when vault is finalized.\n    /// @param operation Struct details for target and calldata to execute.\n    /// @dev MUST revert if not called by owner.\n    function execute(Operation memory operation) external;\n\n    /// @notice Terminate the vault and return all funds to owner.\n    /// @dev MUST revert if not called by owner.\n    function finalize() external;\n\n    /// @notice Stops the guardian from submission and halts fee accrual.\n    /// @dev MUST revert if not called by owner or guardian.\n    function pause() external;\n\n    /// @notice Resume fee accrual and guardian submissions.\n    /// @dev MUST revert if not called by owner.\n    function resume() external;\n\n    /// @notice Submit a series of transactions for execution via the vault.\n    /// @param operations Sequence of operations to execute.\n    /// @dev MUST revert if not called by guardian.\n    function submit(Operation[] memory operations) external;\n\n    /// @notice Claim fees on behalf of a current or previous fee recipient.\n    function claim() external;\n\n    /// @notice Get the current guardian.\n    /// @return guardian Address of guardian.\n    function guardian() external view returns (address guardian);\n\n    /// @notice Get the current fee recipient.\n    /// @return feeRecipient Address of fee recipient.\n    function feeRecipient() external view returns (address feeRecipient);\n\n    /// @notice Get the current asset registry.\n    /// @return assetRegistry Address of asset registry.\n    function assetRegistry()\n        external\n        view\n        returns (IAssetRegistry assetRegistry);\n\n    /// @notice Get the current hooks module address.\n    /// @return hooks Address of hooks module.\n    function hooks() external view returns (IHooks hooks);\n\n    /// @notice Get fee per second.\n    /// @return fee Fee per second in 18 decimal fixed point format.\n    function fee() external view returns (uint256 fee);\n\n    /// @notice Get current balances of all assets.\n    /// @return assetAmounts Amounts of registered assets.\n    function holdings()\n        external\n        view\n        returns (AssetValue[] memory assetAmounts);\n\n    /// @notice Get current total value of assets in vault.\n    /// @return value Current total value.\n    function value() external view returns (uint256 value);\n}\n"
      },
      "src/v2/Constants.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n// Constants.sol\n//\n// This file defines the constants used across several contracts in V2.\n\n/// @dev Fixed point multiplier.\nuint256 constant ONE = 1e18;\n"
      },
      "src/v2/dependencies/openzeppelin/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC165 standard, as defined in the\r\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\r\n *\r\n * Implementers can declare support of contract interfaces, which can then be\r\n * queried by others ({ERC165Checker}).\r\n *\r\n * For an implementation, see {ERC165}.\r\n */\r\ninterface IERC165 {\r\n    /**\r\n     * @dev Returns true if this contract implements the interface defined by\r\n     * `interfaceId`. See the corresponding\r\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\r\n     * to learn more about how these ids are created.\r\n     *\r\n     * This function call must use less than 30 000 gas.\r\n     */\r\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `to`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address to, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `from` to `to` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20.sol\";\r\n\r\n/**\r\n * @dev Interface for the optional metadata functions from the ERC20 standard.\r\n *\r\n * _Available since v4.1._\r\n */\r\ninterface IERC20Metadata is IERC20 {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the decimals places of the token.\r\n     */\r\n    function decimals() external view returns (uint8);\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/Ownable2Step.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n}\n"
      },
      "src/v2/dependencies/openzeppelin/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC20.sol\";\r\nimport \"./IERC20Permit.sol\";\r\nimport \"./Address.sol\";\r\n\r\n/**\r\n * @title SafeERC20\r\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\r\n * contract returns false). Tokens that return no value (and instead revert or\r\n * throw on failure) are also supported, non-reverting calls are assumed to be\r\n * successful.\r\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\r\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\r\n */\r\nlibrary SafeERC20 {\r\n    using Address for address;\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\r\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Deprecated. This function has issues similar to the ones found in\r\n     * {IERC20-approve}, and its usage is discouraged.\r\n     *\r\n     * Whenever possible, use {safeIncreaseAllowance} and\r\n     * {safeDecreaseAllowance} instead.\r\n     */\r\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\r\n        // safeApprove should only be called when setting an initial allowance,\r\n        // or when resetting it to zero. To increase and decrease it, use\r\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\r\n        require(\r\n            (value == 0) || (token.allowance(address(this), spender) == 0),\r\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\r\n        );\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\r\n    }\r\n\r\n    /**\r\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 oldAllowance = token.allowance(address(this), spender);\r\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\r\n    }\r\n\r\n    /**\r\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful.\r\n     */\r\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        unchecked {\r\n            uint256 oldAllowance = token.allowance(address(this), spender);\r\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\r\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\r\n     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\r\n     * 0 before setting it to a non-zero value.\r\n     */\r\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\r\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\r\n\r\n        if (!_callOptionalReturnBool(token, approvalCall)) {\r\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\r\n            _callOptionalReturn(token, approvalCall);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\r\n     * Revert on invalid signature.\r\n     */\r\n    function safePermit(\r\n        IERC20Permit token,\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) internal {\r\n        uint256 nonceBefore = token.nonces(owner);\r\n        token.permit(owner, spender, value, deadline, v, r, s);\r\n        uint256 nonceAfter = token.nonces(owner);\r\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     */\r\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\r\n        // the target address contains contract code and also asserts for success in the low-level call.\r\n\r\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\r\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     *\r\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\r\n     */\r\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\r\n        // and not revert is the subcall reverts.\r\n\r\n        (bool success, bytes memory returndata) = address(token).call(data);\r\n        return\r\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\r\n    }\r\n}\r\n"
      },
      "src/v2/interfaces/ISweepable.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title Interface for sweepable module.\ninterface ISweepable {\n    /// @notice Emitted when sweep is called.\n    /// @param token Token address or zero address if recovering the chain's native token.\n    /// @param amount Withdrawn amount of token.\n    event Sweep(address token, uint256 amount);\n\n    /// @notice Withdraw any tokens accidentally sent to contract.\n    /// @param token Token address to withdraw or zero address for the chain's native token.\n    /// @param amount Amount to withdraw.\n    function sweep(address token, uint256 amount) external;\n}\n"
      },
      "src/v2/dependencies/chainlink/interfaces/AggregatorV2V3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./AggregatorInterface.sol\";\r\nimport \"./AggregatorV3Interface.sol\";\r\n\r\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}"
      },
      "src/v2/interfaces/IVaultEvents.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/IERC20.sol\";\n\nimport {AssetValue, Operation} from \"../Types.sol\";\n\n/// @title Interface for vault events.\ninterface IVaultEvents {\n    /// @notice Emitted when deposit is called.\n    /// @param owner Owner address.\n    /// @param asset Deposited asset.\n    /// @param amount Deposited asset amount.\n    event Deposit(address indexed owner, IERC20 indexed asset, uint256 amount);\n\n    /// @notice Emitted when withdraw is called.\n    /// @param owner Owner address.\n    /// @param asset Withdrawn asset.\n    /// @param amount Withdrawn asset amount.\n    event Withdraw(\n        address indexed owner, IERC20 indexed asset, uint256 amount\n    );\n\n    /// @notice Emitted when guardian is set.\n    /// @param guardian Address of new guardian.\n    /// @param feeRecipient Address of new fee recipient.\n    event SetGuardianAndFeeRecipient(\n        address indexed guardian, address indexed feeRecipient\n    );\n\n    /// @notice Emitted when asset registry is set.\n    /// @param assetRegistry Address of new asset registry.\n    event SetAssetRegistry(address assetRegistry);\n\n    /// @notice Emitted when hooks is set.\n    /// @param hooks Address of new hooks.\n    event SetHooks(address hooks);\n\n    /// @notice Emitted when execute is called.\n    /// @param owner Owner address.\n    /// @param operation Struct details for target and calldata.\n    event Executed(address indexed owner, Operation operation);\n\n    /// @notice Emitted when vault is finalized.\n    /// @param owner Owner address.\n    /// @param withdrawnAmounts Struct details for withdrawn assets and amounts (sent to owner).\n    event Finalized(address indexed owner, AssetValue[] withdrawnAmounts);\n\n    /// @notice Emitted when submit is called.\n    /// @param guardian Guardian address.\n    /// @param operations Array of struct details for targets and calldatas.\n    event Submitted(address indexed guardian, Operation[] operations);\n\n    /// @notice Emitted when guardian fees are claimed.\n    /// @param feeRecipient Fee recipient address.\n    /// @param claimedFee Claimed amount of fee token.\n    /// @param unclaimedFee Unclaimed amount of fee token (unclaimed because Vault does not have enough balance of feeToken).\n    /// @param feeTotal New total reserved fee value.\n    event Claimed(\n        address indexed feeRecipient,\n        uint256 claimedFee,\n        uint256 unclaimedFee,\n        uint256 feeTotal\n    );\n\n    /// @notice Emitted when new fees are reserved for recipient.\n    /// @param feeRecipient Fee recipient address.\n    /// @param newFee Fee amount reserved.\n    /// @param lastFeeCheckpoint Updated fee checkpoint.\n    /// @param lastValue Last registered vault value.\n    /// @param lastFeeTokenPrice Last registered fee token price.\n    /// @param feeTotal New total reserved fee value.\n    event FeesReserved(\n        address indexed feeRecipient,\n        uint256 newFee,\n        uint256 lastFeeCheckpoint,\n        uint256 lastValue,\n        uint256 lastFeeTokenPrice,\n        uint256 feeTotal\n    );\n\n    /// @notice Emitted when no fees are reserved.\n    /// @param lastFeeCheckpoint Updated fee checkpoint.\n    /// @param lastValue Last registered vault value.\n    /// @param feeTotal New total reserved fee value.\n    event NoFeesReserved(\n        uint256 lastFeeCheckpoint,\n        uint256 lastValue,\n        uint256 feeTotal\n    );\n\n    /// @notice Emitted when the call to get spot prices from the asset registry reverts.\n    /// @param reason Revert reason.\n    event SpotPricesReverted(bytes reason);\n}\n"
      },
      "src/v2/interfaces/IHooks.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport {AssetValue, Operation} from \"../Types.sol\";\n\n/// @title IHooks\n/// @notice Interface for the hooks module.\ninterface IHooks {\n    /// @notice Get address of vault.\n    /// @return vault Vault address.\n    function vault() external view returns (address vault);\n\n    /// @notice Hook that runs before deposit.\n    /// @param amounts Struct details for assets and amounts to deposit.\n    /// @dev MUST revert if not called by vault.\n    function beforeDeposit(AssetValue[] memory amounts) external;\n\n    /// @notice Hook that runs after deposit.\n    /// @param amounts Struct details for assets and amounts to deposit.\n    /// @dev MUST revert if not called by vault.\n    function afterDeposit(AssetValue[] memory amounts) external;\n\n    /// @notice Hook that runs before withdraw.\n    /// @param amounts Struct details for assets and amounts to withdraw.\n    /// @dev MUST revert if not called by vault.\n    function beforeWithdraw(AssetValue[] memory amounts) external;\n\n    /// @notice Hook that runs after withdraw.\n    /// @param amounts Struct details for assets and amounts to withdraw.\n    /// @dev MUST revert if not called by vault.\n    function afterWithdraw(AssetValue[] memory amounts) external;\n\n    /// @notice Hook that runs before submit.\n    /// @param operations Array of struct details for target and calldata to submit.\n    /// @dev MUST revert if not called by vault.\n    function beforeSubmit(Operation[] memory operations) external;\n\n    /// @notice Hook that runs after submit.\n    /// @param operations Array of struct details for target and calldata to submit.\n    /// @dev MUST revert if not called by vault.\n    function afterSubmit(Operation[] memory operations) external;\n\n    /// @notice Hook that runs before finalize.\n    /// @dev MUST revert if not called by vault.\n    function beforeFinalize() external;\n\n    /// @notice Hook that runs after finalize.\n    /// @dev MUST revert if not called by vault.\n    function afterFinalize() external;\n\n    /// @notice Take hooks out of use.\n    function decommission() external;\n}\n"
      },
      "src/v2/dependencies/openzeppelin/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./Context.sol\";\r\n\r\n/**\r\n * @dev Contract module which provides a basic access control mechanism, where\r\n * there is an account (an owner) that can be granted exclusive access to\r\n * specific functions.\r\n *\r\n * By default, the owner account will be the one that deploys the contract. This\r\n * can later be changed with {transferOwnership}.\r\n *\r\n * This module is used through inheritance. It will make available the modifier\r\n * `onlyOwner`, which can be applied to your functions to restrict their use to\r\n * the owner.\r\n */\r\nabstract contract Ownable is Context {\r\n    address private _owner;\r\n\r\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n    /**\r\n     * @dev Initializes the contract setting the deployer as the initial owner.\r\n     */\r\n    constructor() {\r\n        _transferOwnership(_msgSender());\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if called by any account other than the owner.\r\n     */\r\n    modifier onlyOwner() {\r\n        _checkOwner();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address of the current owner.\r\n     */\r\n    function owner() public view virtual returns (address) {\r\n        return _owner;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the sender is not the owner.\r\n     */\r\n    function _checkOwner() internal view virtual {\r\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\r\n    }\r\n\r\n    /**\r\n     * @dev Leaves the contract without owner. It will not be possible to call\r\n     * `onlyOwner` functions. Can only be called by the current owner.\r\n     *\r\n     * NOTE: Renouncing ownership will leave the contract without an owner,\r\n     * thereby disabling any functionality that is only available to the owner.\r\n     */\r\n    function renounceOwnership() public virtual onlyOwner {\r\n        _transferOwnership(address(0));\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Can only be called by the current owner.\r\n     */\r\n    function transferOwnership(address newOwner) public virtual onlyOwner {\r\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\r\n        _transferOwnership(newOwner);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Internal function without access restriction.\r\n     */\r\n    function _transferOwnership(address newOwner) internal virtual {\r\n        address oldOwner = _owner;\r\n        _owner = newOwner;\r\n        emit OwnershipTransferred(oldOwner, newOwner);\r\n    }\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\r\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\r\n *\r\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\r\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\r\n * need to send a transaction, and thus is not required to hold Ether at all.\r\n */\r\ninterface IERC20Permit {\r\n    /**\r\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\r\n     * given ``owner``'s signed approval.\r\n     *\r\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\r\n     * ordering also apply here.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `deadline` must be a timestamp in the future.\r\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\r\n     * over the EIP712-formatted function arguments.\r\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\r\n     *\r\n     * For more information on the signature format, see the\r\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\r\n     * section].\r\n     */\r\n    function permit(\r\n        address owner,\r\n        address spender,\r\n        uint256 value,\r\n        uint256 deadline,\r\n        uint8 v,\r\n        bytes32 r,\r\n        bytes32 s\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Returns the current nonce for `owner`. This value must be\r\n     * included whenever a signature is generated for {permit}.\r\n     *\r\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\r\n     * prevents a signature from being used multiple times.\r\n     */\r\n    function nonces(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\r\n     */\r\n    // solhint-disable-next-line func-name-mixedcase\r\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\r\n\r\npragma solidity ^0.8.1;\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     *\r\n     * Furthermore, `isContract` will also return true if the target contract within\r\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\r\n     * which only has an effect at the end of a transaction.\r\n     * ====\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\r\n     *\r\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\r\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\r\n     * constructor.\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // This method relies on extcodesize/address.code.length, which returns 0\r\n        // for contracts in construction, since the code is only stored at the end\r\n        // of the constructor execution.\r\n\r\n        return account.code.length > 0;\r\n    }\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\r\n\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        require(success, \"Address: unable to send value, recipient may have reverted\");\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain `call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason, it is bubbled up by this\r\n     * function (like regular Solidity function calls).\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r\n     * `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(\r\n        address target,\r\n        bytes memory data,\r\n        uint256 value,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\r\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(\r\n        address target,\r\n        bytes memory data,\r\n        string memory errorMessage\r\n    ) internal returns (bytes memory) {\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\r\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\r\n     *\r\n     * _Available since v4.8._\r\n     */\r\n    function verifyCallResultFromTarget(\r\n        address target,\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal view returns (bytes memory) {\r\n        if (success) {\r\n            if (returndata.length == 0) {\r\n                // only check isContract if the call was successful and the return data is empty\r\n                // otherwise we already know that it was a contract\r\n                require(isContract(target), \"Address: call to non-contract\");\r\n            }\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\r\n     * revert reason or using the provided one.\r\n     *\r\n     * _Available since v4.3._\r\n     */\r\n    function verifyCallResult(\r\n        bool success,\r\n        bytes memory returndata,\r\n        string memory errorMessage\r\n    ) internal pure returns (bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            _revert(returndata, errorMessage);\r\n        }\r\n    }\r\n\r\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\r\n        // Look for revert reason and bubble it up if present\r\n        if (returndata.length > 0) {\r\n            // The easiest way to bubble the revert reason is using memory via assembly\r\n            /// @solidity memory-safe-assembly\r\n            assembly {\r\n                let returndata_size := mload(returndata)\r\n                revert(add(32, returndata), returndata_size)\r\n            }\r\n        } else {\r\n            revert(errorMessage);\r\n        }\r\n    }\r\n}\r\n"
      },
      "src/v2/dependencies/chainlink/interfaces/AggregatorInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\ninterface AggregatorInterface {\r\n  function latestAnswer() external view returns (int256);\r\n\r\n  function latestTimestamp() external view returns (uint256);\r\n\r\n  function latestRound() external view returns (uint256);\r\n\r\n  function getAnswer(uint256 roundId) external view returns (int256);\r\n\r\n  function getTimestamp(uint256 roundId) external view returns (uint256);\r\n\r\n  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\r\n\r\n  event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\r\n}"
      },
      "src/v2/dependencies/chainlink/interfaces/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\ninterface AggregatorV3Interface {\r\n  function decimals() external view returns (uint8);\r\n\r\n  function description() external view returns (string memory);\r\n\r\n  function version() external view returns (uint256);\r\n\r\n  // getRoundData and latestRoundData should both raise \"No data present\"\r\n  // if they do not have data to report, instead of returning unset values\r\n  // which could be misinterpreted as actual reported values.\r\n  function getRoundData(uint80 _roundId)\r\n    external\r\n    view\r\n    returns (\r\n      uint80 roundId,\r\n      int256 answer,\r\n      uint256 startedAt,\r\n      uint256 updatedAt,\r\n      uint80 answeredInRound\r\n    );\r\n\r\n  function latestRoundData()\r\n    external\r\n    view\r\n    returns (\r\n      uint80 roundId,\r\n      int256 answer,\r\n      uint256 startedAt,\r\n      uint256 updatedAt,\r\n      uint80 answeredInRound\r\n    );\r\n}"
      },
      "src/v2/Types.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/IERC20.sol\";\nimport \"./interfaces/IAssetRegistry.sol\";\n\n// Types.sol\n//\n// This file defines the types used in V2.\n\n/// @notice Combination of contract address and sighash to be used in allowlist.\n/// @dev It's packed as follows:\n///      [target 160 bits] [selector 32 bits] [<empty> 64 bits]\ntype TargetSighash is bytes32;\n\n/// @notice Struct encapulating an asset and an associated value.\n/// @param asset Asset address.\n/// @param value The associated value for this asset (e.g., amount or price).\nstruct AssetValue {\n    IERC20 asset;\n    uint256 value;\n}\n\n/// @notice Execution details for a vault operation.\n/// @param target Target contract address.\n/// @param value Native token amount.\n/// @param data Calldata.\nstruct Operation {\n    address target;\n    uint256 value;\n    bytes data;\n}\n\n/// @notice Contract address and sighash struct to be used in the public interface.\nstruct TargetSighashData {\n    address target;\n    bytes4 selector;\n}\n\n/// @notice Parameters for vault deployment.\n/// @param owner Initial owner address.\n/// @param assetRegistry Asset registry address.\n/// @param hooks Hooks address.\n/// @param guardian Guardian address.\n/// @param feeRecipient Fee recipient address.\n/// @param fee Fees accrued per second, denoted in 18 decimal fixed point format.\nstruct Parameters {\n    address owner;\n    address assetRegistry;\n    address hooks;\n    address guardian;\n    address feeRecipient;\n    uint256 fee;\n}\n\n/// @notice Vault parameters for vault deployment.\n/// @param owner Initial owner address.\n/// @param guardian Guardian address.\n/// @param feeRecipient Fee recipient address.\n/// @param fee Fees accrued per second, denoted in 18 decimal fixed point format.\nstruct VaultParameters {\n    address owner;\n    address guardian;\n    address feeRecipient;\n    uint256 fee;\n}\n\n/// @notice Asset registry parameters for asset registry deployment.\n/// @param factory Asset registry factory address.\n/// @param owner Initial owner address.\n/// @param assets Initial list of registered assets.\n/// @param numeraireToken Numeraire token address.\n/// @param feeToken Fee token address.\n/// @param sequencer Sequencer Uptime Feed address for L2.\nstruct AssetRegistryParameters {\n    address factory;\n    address owner;\n    IAssetRegistry.AssetInformation[] assets;\n    IERC20 numeraireToken;\n    IERC20 feeToken;\n    AggregatorV2V3Interface sequencer;\n}\n\n/// @notice Hooks parameters for hooks deployment.\n/// @param factory Hooks factory address.\n/// @param owner Initial owner address.\n/// @param minDailyValue The fraction of value that the vault has to retain per day\n///                      in the course of submissions.\n/// @param targetSighashAllowlist Array of target contract and sighash combinations to allow.\nstruct HooksParameters {\n    address factory;\n    address owner;\n    uint256 minDailyValue;\n    TargetSighashData[] targetSighashAllowlist;\n}\n"
      },
      "src/v2/dependencies/openzeppelin/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract Context {\r\n    function _msgSender() internal view virtual returns (address) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes calldata) {\r\n        return msg.data;\r\n    }\r\n}\r\n"
      }
    },
    "settings": {
      "remappings": [
        "src/=src/",
        "test/=test/",
        "@chainlink/=src/v2/dependencies/chainlink/",
        "@openzeppelin/=src/v2/dependencies/openzeppelin/",
        "@uniswap/v3-periphery/=lib/v3-periphery/",
        "@uniswap/v3-core/=lib/v3-core/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "v3-core/=lib/v3-core/",
        "v3-periphery/=lib/v3-periphery/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "abi"
          ]
        }
      },
      "evmVersion": "shanghai",
      "viaIR": true,
      "libraries": {}
    }
  }}