creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/v2/AeraVaultV2.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"@openzeppelin/ERC165.sol\";\nimport \"@openzeppelin/ERC165Checker.sol\";\nimport \"@openzeppelin/IERC4626.sol\";\nimport \"@openzeppelin/Math.sol\";\nimport \"@openzeppelin/Ownable2Step.sol\";\nimport \"@openzeppelin/Pausable.sol\";\nimport \"@openzeppelin/ReentrancyGuard.sol\";\nimport \"@openzeppelin/SafeERC20.sol\";\nimport \"./interfaces/IAeraV2Factory.sol\";\nimport \"./interfaces/IHooks.sol\";\nimport \"./interfaces/IVault.sol\";\nimport {ONE} from \"./Constants.sol\";\n\n/// @title AeraVaultV2.\n/// @notice Aera Vault V2 Vault contract.\ncontract AeraVaultV2 is\n    IVault,\n    ERC165,\n    Ownable2Step,\n    Pausable,\n    ReentrancyGuard\n{\n    using SafeERC20 for IERC20;\n\n    /// @notice Largest possible fee earned proportion per one second.\n    /// @dev 0.0000001% per second, i.e. 3.1536% per year.\n    ///      0.0000001% * (365 * 24 * 60 * 60) = 3.1536%\n    ///      or 3.16224% per year in leap years.\n    uint256 private constant _MAX_FEE = 10 ** 9;\n\n    /// @notice Number of decimals for fee token.\n    uint256 private immutable _feeTokenDecimals;\n\n    /// @notice Number of decimals for numeraire token.\n    uint256 private immutable _numeraireTokenDecimals;\n\n    /// @notice Fee token used by asset registry.\n    IERC20 private immutable _feeToken;\n\n    /// @notice Fee per second in 18 decimal fixed point format.\n    uint256 public immutable fee;\n\n    /// @notice Asset registry address.\n    IAssetRegistry public immutable assetRegistry;\n\n    /// @notice The address of wrapped native token.\n    address public immutable wrappedNativeToken;\n\n    /// STORAGE ///\n\n    /// @notice Hooks module address.\n    IHooks public hooks;\n\n    /// @notice Guardian address.\n    address public guardian;\n\n    /// @notice Fee recipient address.\n    address public feeRecipient;\n\n    /// @notice True if vault has been finalized.\n    bool public finalized;\n\n    /// @notice Last measured value of assets in vault.\n    uint256 public lastValue;\n\n    /// @notice Last spot price of fee token.\n    uint256 public lastFeeTokenPrice;\n\n    /// @notice Fee earned amount for each prior fee recipient.\n    mapping(address => uint256) public fees;\n\n    /// @notice Total fee earned and unclaimed amount by all fee recipients.\n    uint256 public feeTotal;\n\n    /// @notice Last timestamp when fee index was reserved.\n    uint256 public lastFeeCheckpoint;\n\n    /// MODIFIERS ///\n\n    /// @dev Throws if called by any account other than the owner or guardian.\n    modifier onlyOwnerOrGuardian() {\n        if (msg.sender != owner() && msg.sender != guardian) {\n            revert Aera__CallerIsNotOwnerAndGuardian();\n        }\n        _;\n    }\n\n    /// @dev Throws if called by any account other than the guardian.\n    modifier onlyGuardian() {\n        if (msg.sender != guardian) {\n            revert Aera__CallerIsNotGuardian();\n        }\n        _;\n    }\n\n    /// @dev Throws if called after the vault is finalized.\n    modifier whenNotFinalized() {\n        if (finalized) {\n            revert Aera__VaultIsFinalized();\n        }\n        _;\n    }\n\n    /// @dev Throws if hooks is not set\n    modifier whenHooksSet() {\n        if (address(hooks) == address(0)) {\n            revert Aera__HooksIsZeroAddress();\n        }\n        _;\n    }\n\n    /// @dev Calculate current guardian fees.\n    modifier reserveFees() {\n        _reserveFees();\n        _;\n    }\n\n    /// @dev Check insolvency of fee token was not made worse.\n    modifier checkReservedFees() {\n        uint256 prevFeeTokenBalance =\n            IERC20(_feeToken).balanceOf(address(this));\n        _;\n        _checkReservedFees(prevFeeTokenBalance);\n    }\n\n    /// FUNCTIONS ///\n\n    constructor() Ownable() ReentrancyGuard() {\n        (\n            address owner_,\n            address assetRegistry_,\n            address hooks_,\n            address guardian_,\n            address feeRecipient_,\n            uint256 fee_\n        ) = IAeraV2Factory(msg.sender).parameters();\n\n        // Requirements: check provided addresses.\n        _checkAssetRegistryAddress(assetRegistry_);\n        _checkHooksAddress(hooks_);\n        _checkGuardianAddress(guardian_, owner_);\n        _checkFeeRecipientAddress(feeRecipient_, owner_);\n\n        // Requirements: check that initial owner is not zero address.\n        if (owner_ == address(0)) {\n            revert Aera__InitialOwnerIsZeroAddress();\n        }\n        // Requirements: check if fee is within bounds.\n        if (fee_ > _MAX_FEE) {\n            revert Aera__FeeIsAboveMax(fee_, _MAX_FEE);\n        }\n\n        // Effects: initialize vault state.\n        wrappedNativeToken = IAeraV2Factory(msg.sender).wrappedNativeToken();\n        assetRegistry = IAssetRegistry(assetRegistry_);\n        hooks = IHooks(hooks_);\n        guardian = guardian_;\n        feeRecipient = feeRecipient_;\n        fee = fee_;\n        lastFeeCheckpoint = block.timestamp;\n\n        // Effects: cache numeraire and fee token decimals.\n        _feeToken = IAssetRegistry(assetRegistry_).feeToken();\n        _feeTokenDecimals = IERC20Metadata(address(_feeToken)).decimals();\n        _numeraireTokenDecimals =\n            IERC20Metadata(address(assetRegistry.numeraireToken())).decimals();\n\n        // Effects: set new owner.\n        _transferOwnership(owner_);\n\n        // Effects: pause vault.\n        _pause();\n\n        // Log setting of asset registry.\n        emit SetAssetRegistry(assetRegistry_);\n\n        // Log new hooks address.\n        emit SetHooks(hooks_);\n\n        // Log the current guardian and fee recipient.\n        emit SetGuardianAndFeeRecipient(guardian_, feeRecipient_);\n    }\n\n    /// @inheritdoc IVault\n    function deposit(AssetValue[] calldata amounts)\n        external\n        override\n        nonReentrant\n        onlyOwner\n        whenHooksSet\n        whenNotFinalized\n        reserveFees\n    {\n        // Hooks: before transferring assets.\n        hooks.beforeDeposit(amounts);\n\n        // Requirements: check that provided amounts are sorted by asset and unique.\n        _checkAmountsSorted(amounts);\n\n        IAssetRegistry.AssetInformation[] memory assets =\n            assetRegistry.assets();\n\n        uint256 numAmounts = amounts.length;\n        AssetValue memory assetValue;\n        bool isRegistered;\n\n        for (uint256 i = 0; i < numAmounts;) {\n            assetValue = amounts[i];\n            (isRegistered,) = _isAssetRegistered(assetValue.asset, assets);\n\n            // Requirements: check that deposited assets are registered.\n            if (!isRegistered) {\n                revert Aera__AssetIsNotRegistered(assetValue.asset);\n            }\n\n            // Interactions: transfer asset from owner to vault.\n            assetValue.asset.safeTransferFrom(\n                msg.sender, address(this), assetValue.value\n            );\n\n            unchecked {\n                i++; // gas savings\n            }\n\n            // Log deposit for this asset.\n            emit Deposit(msg.sender, assetValue.asset, assetValue.value);\n        }\n\n        // Hooks: after transferring assets.\n        hooks.afterDeposit(amounts);\n    }\n\n    /// @inheritdoc IVault\n    function withdraw(AssetValue[] calldata amounts)\n        external\n        override\n        nonReentrant\n        onlyOwner\n        whenHooksSet\n        whenNotFinalized\n        reserveFees\n    {\n        IAssetRegistry.AssetInformation[] memory assets =\n            assetRegistry.assets();\n\n        // Requirements: check the withdraw request.\n        _checkWithdrawRequest(assets, amounts);\n\n        // Requirements: check that provided amounts are sorted by asset and unique.\n        _checkAmountsSorted(amounts);\n\n        // Hooks: before transferring assets.\n        hooks.beforeWithdraw(amounts);\n\n        uint256 numAmounts = amounts.length;\n        AssetValue memory assetValue;\n\n        for (uint256 i = 0; i < numAmounts;) {\n            assetValue = amounts[i];\n\n            if (assetValue.value == 0) {\n                unchecked {\n                    i++; // gas savings\n                }\n\n                continue;\n            }\n\n            // Interactions: withdraw assets.\n            assetValue.asset.safeTransfer(msg.sender, assetValue.value);\n\n            // Log withdrawal for this asset.\n            emit Withdraw(msg.sender, assetValue.asset, assetValue.value);\n\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        // Hooks: after transferring assets.\n        hooks.afterWithdraw(amounts);\n    }\n\n    /// @inheritdoc IVault\n    function setGuardianAndFeeRecipient(\n        address newGuardian,\n        address newFeeRecipient\n    ) external override onlyOwner whenNotFinalized reserveFees {\n        // Requirements: check guardian and fee recipient addresses.\n        _checkGuardianAddress(newGuardian, msg.sender);\n        _checkFeeRecipientAddress(newFeeRecipient, msg.sender);\n\n        // Effects: update guardian and fee recipient addresses.\n        guardian = newGuardian;\n        // slither-disable-next-line missing-zero-check\n        feeRecipient = newFeeRecipient;\n\n        // Log new guardian and fee recipient addresses.\n        emit SetGuardianAndFeeRecipient(newGuardian, newFeeRecipient);\n    }\n\n    /// @inheritdoc IVault\n    function setHooks(address newHooks)\n        external\n        override\n        nonReentrant\n        onlyOwner\n        whenNotFinalized\n        reserveFees\n    {\n        // Requirements: validate hooks address.\n        _checkHooksAddress(newHooks);\n\n        // Effects: decommission old hooks contract.\n        if (address(hooks) != address(0)) {\n            hooks.decommission();\n        }\n\n        // Effects: set new hooks address.\n        hooks = IHooks(newHooks);\n\n        // Log new hooks address.\n        emit SetHooks(newHooks);\n    }\n\n    /// @inheritdoc IVault\n    /// @dev reserveFees modifier is not used to avoid reverts.\n    function execute(Operation calldata operation)\n        external\n        override\n        nonReentrant\n        onlyOwner\n    {\n        // Requirements: check that the target contract is not hooks.\n        if (operation.target == address(hooks)) {\n            revert Aera__ExecuteTargetIsHooksAddress();\n        }\n        // Requirements: check that the target contract is not vault itself.\n        if (operation.target == address(this)) {\n            revert Aera__ExecuteTargetIsVaultAddress();\n        }\n\n        // Interactions: execute operation.\n        (bool success, bytes memory result) =\n            operation.target.call{value: operation.value}(operation.data);\n\n        // Invariants: check that the operation was successful.\n        if (!success) {\n            revert Aera__ExecutionFailed(result);\n        }\n\n        // Log that the operation was executed.\n        emit Executed(msg.sender, operation);\n    }\n\n    /// @inheritdoc IVault\n    function finalize()\n        external\n        override\n        nonReentrant\n        onlyOwner\n        whenHooksSet\n        whenNotFinalized\n        reserveFees\n    {\n        // Hooks: before finalizing.\n        hooks.beforeFinalize();\n\n        // Effects: mark the vault as finalized.\n        finalized = true;\n\n        IAssetRegistry.AssetInformation[] memory assets =\n            assetRegistry.assets();\n        AssetValue[] memory assetAmounts = _getHoldings(assets);\n        uint256 numAssetAmounts = assetAmounts.length;\n\n        for (uint256 i = 0; i < numAssetAmounts;) {\n            // Effects: transfer registered assets to owner.\n            // Excludes reserved fee tokens and native token (e.g., ETH).\n            if (assetAmounts[i].value > 0) {\n                assetAmounts[i].asset.safeTransfer(\n                    msg.sender, assetAmounts[i].value\n                );\n            }\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        // Hooks: after finalizing.\n        hooks.afterFinalize();\n\n        // Log finalization.\n        emit Finalized(msg.sender, assetAmounts);\n    }\n\n    /// @inheritdoc IVault\n    function pause()\n        external\n        override\n        nonReentrant\n        onlyOwnerOrGuardian\n        whenNotFinalized\n        reserveFees\n    {\n        // Requirements and Effects: checks contract is unpaused and pauses it.\n        _pause();\n    }\n\n    /// @inheritdoc IVault\n    function resume()\n        external\n        override\n        onlyOwner\n        whenHooksSet\n        whenNotFinalized\n    {\n        // Effects: start a new fee checkpoint.\n        lastFeeCheckpoint = block.timestamp;\n\n        // Requirements and Effects: checks contract is paused and unpauses it.\n        _unpause();\n    }\n\n    /// @inheritdoc IVault\n    function submit(Operation[] calldata operations)\n        external\n        override\n        nonReentrant\n        onlyGuardian\n        whenHooksSet\n        whenNotFinalized\n        whenNotPaused\n        reserveFees\n        checkReservedFees\n    {\n        // Hooks: before executing operations.\n        hooks.beforeSubmit(operations);\n\n        uint256 numOperations = operations.length;\n\n        Operation calldata operation;\n        bytes4 selector;\n        bool success;\n        bytes memory result;\n        address hooksAddress = address(hooks);\n\n        for (uint256 i = 0; i < numOperations;) {\n            operation = operations[i];\n            selector = bytes4(operation.data[0:4]);\n\n            // Requirements: validate that it doesn't transfer asset from owner.\n            if (\n                selector == IERC20.transferFrom.selector\n                    && abi.decode(operation.data[4:], (address)) == owner()\n            ) {\n                revert Aera__SubmitTransfersAssetFromOwner();\n            }\n\n            // Requirements: check that operation is not trying to redeem ERC4626 shares from owner.\n            // This could occur if the owner had a pre-existing allowance introduced during deposit.\n            if (\n                selector == IERC4626.withdraw.selector\n                    || selector == IERC4626.redeem.selector\n            ) {\n                (,, address assetOwner) =\n                    abi.decode(operation.data[4:], (uint256, address, address));\n\n                if (assetOwner == owner()) {\n                    revert Aera__SubmitRedeemERC4626AssetFromOwner();\n                }\n            }\n\n            // Requirements: check that the target contract is not hooks.\n            if (operation.target == hooksAddress) {\n                revert Aera__SubmitTargetIsHooksAddress(i);\n            }\n            // Requirements: check that the target contract is not vault itself.\n            if (operation.target == address(this)) {\n                revert Aera__SubmitTargetIsVaultAddress();\n            }\n\n            // Interactions: execute operation.\n            (success, result) =\n                operation.target.call{value: operation.value}(operation.data);\n\n            // Invariants: confirm that operation succeeded.\n            if (!success) {\n                revert Aera__SubmissionFailed(i, result);\n            }\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        if (address(this).balance > 0) {\n            wrappedNativeToken.call{value: address(this).balance}(\"\");\n        }\n\n        // Hooks: after executing operations.\n        hooks.afterSubmit(operations);\n\n        // Log submission.\n        emit Submitted(guardian, operations);\n    }\n\n    /// @inheritdoc IVault\n    function claim() external override nonReentrant reserveFees {\n        uint256 reservedFee = fees[msg.sender];\n\n        // Requirements: check that there are fees to claim.\n        if (reservedFee == 0) {\n            revert Aera__NoClaimableFeesForCaller(msg.sender);\n        }\n\n        uint256 availableFee =\n            Math.min(_feeToken.balanceOf(address(this)), reservedFee);\n\n        // Requirements: check that fees are available to claim.\n        if (availableFee == 0) {\n            revert Aera__NoAvailableFeesForCaller(msg.sender);\n        }\n\n        // Effects: update fee total.\n        feeTotal -= availableFee;\n        reservedFee -= availableFee;\n\n        // Effects: update leftover fee.\n        fees[msg.sender] = reservedFee;\n\n        // Interactions: transfer fee to caller.\n        _feeToken.safeTransfer(msg.sender, availableFee);\n\n        // Log the claim.\n        emit Claimed(msg.sender, availableFee, reservedFee, feeTotal);\n    }\n\n    /// @inheritdoc IVault\n    function holdings() external view override returns (AssetValue[] memory) {\n        IAssetRegistry.AssetInformation[] memory assets =\n            assetRegistry.assets();\n\n        return _getHoldings(assets);\n    }\n\n    /// @inheritdoc IVault\n    function value() external view override returns (uint256 vaultValue) {\n        IAssetRegistry.AssetPriceReading[] memory erc20SpotPrices =\n            assetRegistry.spotPrices();\n\n        (vaultValue,) = _value(erc20SpotPrices);\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override\n        returns (bool)\n    {\n        return interfaceId == type(IVault).interfaceId\n            || super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc Ownable\n    function renounceOwnership() public view override onlyOwner {\n        revert Aera__CannotRenounceOwnership();\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        if (newOwner == guardian) {\n            revert Aera__GuardianIsOwner();\n        }\n        if (newOwner == feeRecipient) {\n            revert Aera__FeeRecipientIsOwner();\n        }\n\n        // Effects: initiate ownership transfer.\n        super.transferOwnership(newOwner);\n    }\n\n    /// @notice Only accept native token from the wrapped native token contract\n    ///         when burning wrapped native tokens.\n    receive() external payable {\n        // Requirements: verify that the sender is wrapped native token.\n        if (msg.sender != wrappedNativeToken) {\n            revert Aera__NotWrappedNativeTokenContract();\n        }\n    }\n\n    /// INTERNAL FUNCTIONS ///\n\n    /// @notice Calculate guardian fee index.\n    /// @return feeIndex Guardian fee index.\n    function _getFeeIndex() internal view returns (uint256 feeIndex) {\n        if (block.timestamp > lastFeeCheckpoint) {\n            unchecked {\n                feeIndex = block.timestamp - lastFeeCheckpoint;\n            }\n        }\n\n        return feeIndex;\n    }\n\n    /// @notice Calculate current guardian fees.\n    function _reserveFees() internal {\n        // Requirements: check if fees are being accrued.\n        if (fee == 0 || paused() || finalized) {\n            return;\n        }\n\n        uint256 feeIndex = _getFeeIndex();\n\n        // Requirements: check if fees have been accruing.\n        if (feeIndex == 0) {\n            return;\n        }\n\n        // Calculate vault value using oracle or backup value if oracle is reverting.\n        try assetRegistry.spotPrices() returns (\n            IAssetRegistry.AssetPriceReading[] memory erc20SpotPrices\n        ) {\n            (lastValue, lastFeeTokenPrice) = _value(erc20SpotPrices);\n        } catch (bytes memory reason) {\n            // Check if there is a clear reason for the revert.\n            if (reason.length == 0) {\n                revert Aera__SpotPricesReverted();\n            }\n            emit SpotPricesReverted(reason);\n        }\n\n        // Requirements: check that fee token has a positive price.\n        if (lastFeeTokenPrice == 0) {\n            emit NoFeesReserved(lastFeeCheckpoint, lastValue, feeTotal);\n            return;\n        }\n\n        // Calculate new fee for current fee recipient.\n        // It calculates the fee in fee token decimals.\n        uint256 newFee = lastValue * feeIndex * fee;\n\n        if (_numeraireTokenDecimals < _feeTokenDecimals) {\n            newFee =\n                newFee * (10 ** (_feeTokenDecimals - _numeraireTokenDecimals));\n        } else if (_numeraireTokenDecimals > _feeTokenDecimals) {\n            newFee =\n                newFee / (10 ** (_numeraireTokenDecimals - _feeTokenDecimals));\n        }\n\n        newFee /= lastFeeTokenPrice;\n\n        if (newFee == 0) {\n            return;\n        }\n\n        // Move fee checkpoint only if fee is nonzero\n        lastFeeCheckpoint = block.timestamp;\n\n        // Effects: accrue fee to fee recipient and remember new fee total.\n        fees[feeRecipient] += newFee;\n        feeTotal += newFee;\n\n        // Log fee reservation.\n        emit FeesReserved(\n            feeRecipient,\n            newFee,\n            lastFeeCheckpoint,\n            lastValue,\n            lastFeeTokenPrice,\n            feeTotal\n        );\n    }\n\n    /// @notice Get current total value of assets in vault and price of fee token.\n    /// @dev It calculates the value in Numeraire token decimals.\n    /// @param erc20SpotPrices Spot prices of ERC20 assets.\n    /// @return vaultValue Current total value.\n    /// @return feeTokenPrice Fee token price.\n    function _value(IAssetRegistry.AssetPriceReading[] memory erc20SpotPrices)\n        internal\n        view\n        returns (uint256 vaultValue, uint256 feeTokenPrice)\n    {\n        IAssetRegistry.AssetInformation[] memory assets =\n            assetRegistry.assets();\n        AssetValue[] memory assetAmounts = _getHoldings(assets);\n\n        (uint256[] memory spotPrices, uint256[] memory assetUnits) =\n            _getSpotPricesAndUnits(assets, erc20SpotPrices);\n\n        uint256 numAssets = assets.length;\n        uint256 balance;\n\n        for (uint256 i = 0; i < numAssets;) {\n            if (assets[i].isERC4626) {\n                balance = IERC4626(address(assets[i].asset)).convertToAssets(\n                    assetAmounts[i].value\n                );\n            } else {\n                balance = assetAmounts[i].value;\n            }\n\n            if (assets[i].asset == _feeToken) {\n                feeTokenPrice = spotPrices[i];\n            }\n\n            vaultValue += (balance * spotPrices[i]) / assetUnits[i];\n            unchecked {\n                i++; // gas savings\n            }\n        }\n\n        uint256 numeraireUnit = 10 ** _numeraireTokenDecimals;\n\n        if (numeraireUnit != ONE) {\n            vaultValue = vaultValue * numeraireUnit / ONE;\n        }\n    }\n\n    /// @notice Check that assets in provided amounts are sorted and unique.\n    /// @param amounts Struct details for assets and amounts to withdraw.\n    function _checkAmountsSorted(AssetValue[] memory amounts) internal pure {\n        uint256 numAssets = amounts.length;\n\n        for (uint256 i = 1; i < numAssets;) {\n            if (amounts[i - 1].asset >= amounts[i].asset) {\n                revert Aera__AmountsOrderIsIncorrect(i);\n            }\n            unchecked {\n                i++; // gas savings\n            }\n        }\n    }\n\n    /// @notice Check request to withdraw.\n    /// @param assets Struct details for asset information from asset registry.\n    /// @param amounts Struct details for assets and amounts to withdraw.\n    function _checkWithdrawRequest(\n        IAssetRegistry.AssetInformation[] memory assets,\n        AssetValue[] memory amounts\n    ) internal view {\n        uint256 numAmounts = amounts.length;\n\n        AssetValue[] memory assetAmounts = _getHoldings(assets);\n\n        bool isRegistered;\n        AssetValue memory assetValue;\n        uint256 assetIndex;\n\n        for (uint256 i = 0; i < numAmounts;) {\n            assetValue = amounts[i];\n            (isRegistered, assetIndex) =\n                _isAssetRegistered(assetValue.asset, assets);\n\n            if (!isRegistered) {\n                revert Aera__AssetIsNotRegistered(assetValue.asset);\n            }\n\n            if (assetAmounts[assetIndex].value < assetValue.value) {\n                revert Aera__AmountExceedsAvailable(\n                    assetValue.asset,\n                    assetValue.value,\n                    assetAmounts[assetIndex].value\n                );\n            }\n            unchecked {\n                i++; // gas savings\n            }\n        }\n    }\n\n    /// @notice Get spot prices and units of requested assets.\n    /// @dev Spot prices are scaled to 18 decimals.\n    /// @param assets Registered assets in asset registry and their information.\n    /// @param erc20SpotPrices Struct details for spot prices of ERC20 assets.\n    /// @return spotPrices Spot prices of assets.\n    /// @return assetUnits Units of assets.\n    function _getSpotPricesAndUnits(\n        IAssetRegistry.AssetInformation[] memory assets,\n        IAssetRegistry.AssetPriceReading[] memory erc20SpotPrices\n    )\n        internal\n        view\n        returns (uint256[] memory spotPrices, uint256[] memory assetUnits)\n    {\n        uint256 numAssets = assets.length;\n        uint256 numERC20SpotPrices = erc20SpotPrices.length;\n\n        spotPrices = new uint256[](numAssets);\n        assetUnits = new uint256[](numAssets);\n\n        IAssetRegistry.AssetInformation memory asset;\n\n        for (uint256 i = 0; i < numAssets;) {\n            asset = assets[i];\n\n            IERC20 assetToFind = (\n                asset.isERC4626\n                    ? IERC20(IERC4626(address(asset.asset)).asset())\n                    : asset.asset\n            );\n            uint256 j = 0;\n            for (; j < numERC20SpotPrices;) {\n                if (assetToFind == erc20SpotPrices[j].asset) {\n                    break;\n                }\n                unchecked {\n                    j++; // gas savings\n                }\n            }\n            spotPrices[i] = erc20SpotPrices[j].spotPrice;\n            assetUnits[i] =\n                10 ** IERC20Metadata(address(assetToFind)).decimals();\n\n            unchecked {\n                i++; // gas savings\n            }\n        }\n    }\n\n    /// @notice Get total amount of assets in vault.\n    /// @param assets Struct details for registered assets in asset registry.\n    /// @return assetAmounts Amount of assets.\n    function _getHoldings(IAssetRegistry.AssetInformation[] memory assets)\n        internal\n        view\n        returns (AssetValue[] memory assetAmounts)\n    {\n        uint256 numAssets = assets.length;\n\n        assetAmounts = new AssetValue[](numAssets);\n        IAssetRegistry.AssetInformation memory assetInfo;\n\n        for (uint256 i = 0; i < numAssets;) {\n            assetInfo = assets[i];\n            assetAmounts[i] = AssetValue({\n                asset: assetInfo.asset,\n                value: assetInfo.asset.balanceOf(address(this))\n            });\n\n            if (assetInfo.asset == _feeToken) {\n                assetAmounts[i].value -=\n                    Math.min(feeTotal, assetAmounts[i].value);\n            }\n\n            unchecked {\n                i++; //gas savings\n            }\n        }\n    }\n\n    /// @notice Check if balance of fee becomes insolvent or becomes more insolvent.\n    /// @param prevFeeTokenBalance Balance of fee token before action.\n    function _checkReservedFees(uint256 prevFeeTokenBalance) internal view {\n        uint256 feeTokenBalance = IERC20(_feeToken).balanceOf(address(this));\n\n        if (\n            feeTokenBalance < feeTotal && feeTokenBalance < prevFeeTokenBalance\n        ) {\n            revert Aera__CannotUseReservedFees();\n        }\n    }\n\n    /// @notice Check if the address can be a guardian.\n    /// @param newGuardian Address to check.\n    /// @param owner_ Owner address.\n    function _checkGuardianAddress(\n        address newGuardian,\n        address owner_\n    ) internal pure {\n        if (newGuardian == address(0)) {\n            revert Aera__GuardianIsZeroAddress();\n        }\n        if (newGuardian == owner_) {\n            revert Aera__GuardianIsOwner();\n        }\n    }\n\n    /// @notice Check if the address can be a fee recipient.\n    /// @param newFeeRecipient Address to check.\n    /// @param owner_ Owner address.\n    function _checkFeeRecipientAddress(\n        address newFeeRecipient,\n        address owner_\n    ) internal pure {\n        if (newFeeRecipient == address(0)) {\n            revert Aera__FeeRecipientIsZeroAddress();\n        }\n        if (newFeeRecipient == owner_) {\n            revert Aera__FeeRecipientIsOwner();\n        }\n    }\n\n    /// @notice Check if the address can be an asset registry.\n    /// @param newAssetRegistry Address to check.\n    function _checkAssetRegistryAddress(address newAssetRegistry)\n        internal\n        view\n    {\n        if (newAssetRegistry == address(0)) {\n            revert Aera__AssetRegistryIsZeroAddress();\n        }\n        if (\n            !ERC165Checker.supportsInterface(\n                newAssetRegistry, type(IAssetRegistry).interfaceId\n            )\n        ) {\n            revert Aera__AssetRegistryIsNotValid(newAssetRegistry);\n        }\n        if (IAssetRegistry(newAssetRegistry).vault() != address(this)) {\n            revert Aera__AssetRegistryHasInvalidVault();\n        }\n    }\n\n    /// @notice Check if the address can be a hooks contract.\n    /// @param newHooks Address to check.\n    function _checkHooksAddress(address newHooks) internal view {\n        if (newHooks == address(0)) {\n            revert Aera__HooksIsZeroAddress();\n        }\n        if (\n            !ERC165Checker.supportsInterface(newHooks, type(IHooks).interfaceId)\n        ) {\n            revert Aera__HooksIsNotValid(newHooks);\n        }\n        if (IHooks(newHooks).vault() != address(this)) {\n            revert Aera__HooksHasInvalidVault();\n        }\n    }\n\n    /// @notice Check whether asset is registered to asset registry or not.\n    /// @param asset Asset to check.\n    /// @param registeredAssets Array of registered assets.\n    /// @return isRegistered True if asset is registered.\n    /// @return index Index of asset in asset registry.\n    function _isAssetRegistered(\n        IERC20 asset,\n        IAssetRegistry.AssetInformation[] memory registeredAssets\n    ) internal pure returns (bool isRegistered, uint256 index) {\n        uint256 numAssets = registeredAssets.length;\n\n        for (uint256 i = 0; i < numAssets;) {\n            if (registeredAssets[i].asset < asset) {\n                unchecked {\n                    i++; // gas savings\n                }\n\n                continue;\n            }\n\n            if (registeredAssets[i].asset == asset) {\n                return (true, i);\n            }\n\n            break;\n        }\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/ERC165Checker.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\nimport \"./IERC165.sol\";\r\n\r\n/**\r\n * @dev Library used to query support of an interface declared via {IERC165}.\r\n *\r\n * Note that these functions return the actual result of the query: they do not\r\n * `revert` if an interface is not supported. It is up to the caller to decide\r\n * what to do in these cases.\r\n */\r\nlibrary ERC165Checker {\r\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\r\n    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\r\n\r\n    /**\r\n     * @dev Returns true if `account` supports the {IERC165} interface.\r\n     */\r\n    function supportsERC165(address account) internal view returns (bool) {\r\n        // Any contract that implements ERC165 must explicitly indicate support of\r\n        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\r\n        return\r\n            supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\r\n            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if `account` supports the interface defined by\r\n     * `interfaceId`. Support for {IERC165} itself is queried automatically.\r\n     *\r\n     * See {IERC165-supportsInterface}.\r\n     */\r\n    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\r\n        // query support of both ERC165 as per the spec and support of _interfaceId\r\n        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns a boolean array where each value corresponds to the\r\n     * interfaces passed in and whether they're supported or not. This allows\r\n     * you to batch check interfaces for a contract where your expectation\r\n     * is that some interfaces may not be supported.\r\n     *\r\n     * See {IERC165-supportsInterface}.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function getSupportedInterfaces(\r\n        address account,\r\n        bytes4[] memory interfaceIds\r\n    ) internal view returns (bool[] memory) {\r\n        // an array of booleans corresponding to interfaceIds and whether they're supported or not\r\n        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\r\n\r\n        // query support of ERC165 itself\r\n        if (supportsERC165(account)) {\r\n            // query support of each interface in interfaceIds\r\n            for (uint256 i = 0; i < interfaceIds.length; i++) {\r\n                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\r\n            }\r\n        }\r\n\r\n        return interfaceIdsSupported;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if `account` supports all the interfaces defined in\r\n     * `interfaceIds`. Support for {IERC165} itself is queried automatically.\r\n     *\r\n     * Batch-querying can lead to gas savings by skipping repeated checks for\r\n     * {IERC165} support.\r\n     *\r\n     * See {IERC165-supportsInterface}.\r\n     */\r\n    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\r\n        // query support of ERC165 itself\r\n        if (!supportsERC165(account)) {\r\n            return false;\r\n        }\r\n\r\n        // query support of each interface in interfaceIds\r\n        for (uint256 i = 0; i < interfaceIds.length; i++) {\r\n            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\r\n                return false;\r\n            }\r\n        }\r\n\r\n        // all interfaces supported\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @notice Query if a contract implements an interface, does not check ERC165 support\r\n     * @param account The address of the contract to query for support of an interface\r\n     * @param interfaceId The interface identifier, as specified in ERC-165\r\n     * @return true if the contract at account indicates support of the interface with\r\n     * identifier interfaceId, false otherwise\r\n     * @dev Assumes that account contains a contract that supports ERC165, otherwise\r\n     * the behavior of this method is undefined. This precondition can be checked\r\n     * with {supportsERC165}.\r\n     *\r\n     * Some precompiled contracts will falsely indicate support for a given interface, so caution\r\n     * should be exercised when using this function.\r\n     *\r\n     * Interface identification is specified in ERC-165.\r\n     */\r\n    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\r\n        // prepare call\r\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\r\n\r\n        // perform static call\r\n        bool success;\r\n        uint256 returnSize;\r\n        uint256 returnValue;\r\n        assembly {\r\n            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\r\n            returnSize := returndatasize()\r\n            returnValue := mload(0x00)\r\n        }\r\n\r\n        return success && returnSize >= 0x20 && returnValue > 0;\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/dependencies/openzeppelin/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Standard math utilities missing in the Solidity language.\r\n */\r\nlibrary Math {\r\n    enum Rounding {\r\n        Down, // Toward negative infinity\r\n        Up, // Toward infinity\r\n        Zero // Toward zero\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the largest of two numbers.\r\n     */\r\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a > b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the smallest of two numbers.\r\n     */\r\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the average of two numbers. The result is rounded towards\r\n     * zero.\r\n     */\r\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b) / 2 can overflow.\r\n        return (a & b) + (a ^ b) / 2;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the ceiling of the division of two numbers.\r\n     *\r\n     * This differs from standard division with `/` in that it rounds up instead\r\n     * of rounding down.\r\n     */\r\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // (a + b - 1) / b can overflow on addition, so we distribute.\r\n        return a == 0 ? 0 : (a - 1) / b + 1;\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\r\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\r\n     * with further edits by Uniswap Labs also under MIT license.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\r\n        unchecked {\r\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\r\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\r\n            // variables such that product = prod1 * 2^256 + prod0.\r\n            uint256 prod0; // Least significant 256 bits of the product\r\n            uint256 prod1; // Most significant 256 bits of the product\r\n            assembly {\r\n                let mm := mulmod(x, y, not(0))\r\n                prod0 := mul(x, y)\r\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\r\n            }\r\n\r\n            // Handle non-overflow cases, 256 by 256 division.\r\n            if (prod1 == 0) {\r\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\r\n                // The surrounding unchecked block does not change this fact.\r\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\r\n                return prod0 / denominator;\r\n            }\r\n\r\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\r\n            require(denominator > prod1, \"Math: mulDiv overflow\");\r\n\r\n            ///////////////////////////////////////////////\r\n            // 512 by 256 division.\r\n            ///////////////////////////////////////////////\r\n\r\n            // Make division exact by subtracting the remainder from [prod1 prod0].\r\n            uint256 remainder;\r\n            assembly {\r\n                // Compute remainder using mulmod.\r\n                remainder := mulmod(x, y, denominator)\r\n\r\n                // Subtract 256 bit number from 512 bit number.\r\n                prod1 := sub(prod1, gt(remainder, prod0))\r\n                prod0 := sub(prod0, remainder)\r\n            }\r\n\r\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\r\n            // See https://cs.stackexchange.com/q/138556/92363.\r\n\r\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\r\n            uint256 twos = denominator & (~denominator + 1);\r\n            assembly {\r\n                // Divide denominator by twos.\r\n                denominator := div(denominator, twos)\r\n\r\n                // Divide [prod1 prod0] by twos.\r\n                prod0 := div(prod0, twos)\r\n\r\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\r\n                twos := add(div(sub(0, twos), twos), 1)\r\n            }\r\n\r\n            // Shift in bits from prod1 into prod0.\r\n            prod0 |= prod1 * twos;\r\n\r\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\r\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\r\n            // four bits. That is, denominator * inv = 1 mod 2^4.\r\n            uint256 inverse = (3 * denominator) ^ 2;\r\n\r\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\r\n            // in modular arithmetic, doubling the correct bits in each step.\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\r\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\r\n\r\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\r\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\r\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\r\n            // is no longer required.\r\n            result = prod0 * inverse;\r\n            return result;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\r\n     */\r\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\r\n        uint256 result = mulDiv(x, y, denominator);\r\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\r\n            result += 1;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\r\n     *\r\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\r\n     */\r\n    function sqrt(uint256 a) internal pure returns (uint256) {\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\r\n        //\r\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\r\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\r\n        //\r\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\r\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\r\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\r\n        //\r\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\r\n        uint256 result = 1 << (log2(a) >> 1);\r\n\r\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\r\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\r\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\r\n        // into the expected uint128 result.\r\n        unchecked {\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            result = (result + a / result) >> 1;\r\n            return min(result, a / result);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates sqrt(a), following the selected rounding direction.\r\n     */\r\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = sqrt(a);\r\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 128;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 64;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 32;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 16;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                value >>= 8;\r\n                result += 8;\r\n            }\r\n            if (value >> 4 > 0) {\r\n                value >>= 4;\r\n                result += 4;\r\n            }\r\n            if (value >> 2 > 0) {\r\n                value >>= 2;\r\n                result += 2;\r\n            }\r\n            if (value >> 1 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log2(value);\r\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >= 10 ** 64) {\r\n                value /= 10 ** 64;\r\n                result += 64;\r\n            }\r\n            if (value >= 10 ** 32) {\r\n                value /= 10 ** 32;\r\n                result += 32;\r\n            }\r\n            if (value >= 10 ** 16) {\r\n                value /= 10 ** 16;\r\n                result += 16;\r\n            }\r\n            if (value >= 10 ** 8) {\r\n                value /= 10 ** 8;\r\n                result += 8;\r\n            }\r\n            if (value >= 10 ** 4) {\r\n                value /= 10 ** 4;\r\n                result += 4;\r\n            }\r\n            if (value >= 10 ** 2) {\r\n                value /= 10 ** 2;\r\n                result += 2;\r\n            }\r\n            if (value >= 10 ** 1) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log10(value);\r\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, rounded down, of a positive value.\r\n     * Returns 0 if given 0.\r\n     *\r\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\r\n     */\r\n    function log256(uint256 value) internal pure returns (uint256) {\r\n        uint256 result = 0;\r\n        unchecked {\r\n            if (value >> 128 > 0) {\r\n                value >>= 128;\r\n                result += 16;\r\n            }\r\n            if (value >> 64 > 0) {\r\n                value >>= 64;\r\n                result += 8;\r\n            }\r\n            if (value >> 32 > 0) {\r\n                value >>= 32;\r\n                result += 4;\r\n            }\r\n            if (value >> 16 > 0) {\r\n                value >>= 16;\r\n                result += 2;\r\n            }\r\n            if (value >> 8 > 0) {\r\n                result += 1;\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\r\n     * Returns 0 if given 0.\r\n     */\r\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\r\n        unchecked {\r\n            uint256 result = log256(value);\r\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\r\n        }\r\n    }\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/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.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 allows children to implement an emergency stop\r\n * mechanism that can be triggered by an authorized account.\r\n *\r\n * This module is used through inheritance. It will make available the\r\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\r\n * the functions of your contract. Note that they will not be pausable by\r\n * simply including this module, only once the modifiers are put in place.\r\n */\r\nabstract contract Pausable is Context {\r\n    /**\r\n     * @dev Emitted when the pause is triggered by `account`.\r\n     */\r\n    event Paused(address account);\r\n\r\n    /**\r\n     * @dev Emitted when the pause is lifted by `account`.\r\n     */\r\n    event Unpaused(address account);\r\n\r\n    bool private _paused;\r\n\r\n    /**\r\n     * @dev Initializes the contract in unpaused state.\r\n     */\r\n    constructor() {\r\n        _paused = false;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is not paused.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must not be paused.\r\n     */\r\n    modifier whenNotPaused() {\r\n        _requireNotPaused();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is paused.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must be paused.\r\n     */\r\n    modifier whenPaused() {\r\n        _requirePaused();\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the contract is paused, and false otherwise.\r\n     */\r\n    function paused() public view virtual returns (bool) {\r\n        return _paused;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the contract is paused.\r\n     */\r\n    function _requireNotPaused() internal view virtual {\r\n        require(!paused(), \"Pausable: paused\");\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if the contract is not paused.\r\n     */\r\n    function _requirePaused() internal view virtual {\r\n        require(paused(), \"Pausable: not paused\");\r\n    }\r\n\r\n    /**\r\n     * @dev Triggers stopped state.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must not be paused.\r\n     */\r\n    function _pause() internal virtual whenNotPaused {\r\n        _paused = true;\r\n        emit Paused(_msgSender());\r\n    }\r\n\r\n    /**\r\n     * @dev Returns to normal state.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - The contract must be paused.\r\n     */\r\n    function _unpause() internal virtual whenPaused {\r\n        _paused = false;\r\n        emit Unpaused(_msgSender());\r\n    }\r\n}\r\n"
      },
      "src/v2/dependencies/openzeppelin/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\r\n\r\npragma solidity ^0.8.0;\r\n\r\n/**\r\n * @dev Contract module that helps prevent reentrant calls to a function.\r\n *\r\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\r\n * available, which can be applied to functions to make sure there are no nested\r\n * (reentrant) calls to them.\r\n *\r\n * Note that because there is a single `nonReentrant` guard, functions marked as\r\n * `nonReentrant` may not call one another. This can be worked around by making\r\n * those functions `private`, and then adding `external` `nonReentrant` entry\r\n * points to them.\r\n *\r\n * TIP: If you would like to learn more about reentrancy and alternative ways\r\n * to protect against it, check out our blog post\r\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\r\n */\r\nabstract contract ReentrancyGuard {\r\n    // Booleans are more expensive than uint256 or any type that takes up a full\r\n    // word because each write operation emits an extra SLOAD to first read the\r\n    // slot's contents, replace the bits taken up by the boolean, and then write\r\n    // back. This is the compiler's defense against contract upgrades and\r\n    // pointer aliasing, and it cannot be disabled.\r\n\r\n    // The values being non-zero value makes deployment a bit more expensive,\r\n    // but in exchange the refund on every call to nonReentrant will be lower in\r\n    // amount. Since refunds are capped to a percentage of the total\r\n    // transaction's gas, it is best to keep them low in cases like this one, to\r\n    // increase the likelihood of the full refund coming into effect.\r\n    uint256 private constant _NOT_ENTERED = 1;\r\n    uint256 private constant _ENTERED = 2;\r\n\r\n    uint256 private _status;\r\n\r\n    constructor() {\r\n        _status = _NOT_ENTERED;\r\n    }\r\n\r\n    /**\r\n     * @dev Prevents a contract from calling itself, directly or indirectly.\r\n     * Calling a `nonReentrant` function from another `nonReentrant`\r\n     * function is not supported. It is possible to prevent this from happening\r\n     * by making the `nonReentrant` function external, and making it call a\r\n     * `private` function that does the actual work.\r\n     */\r\n    modifier nonReentrant() {\r\n        _nonReentrantBefore();\r\n        _;\r\n        _nonReentrantAfter();\r\n    }\r\n\r\n    function _nonReentrantBefore() private {\r\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\r\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\r\n\r\n        // Any calls to nonReentrant after this point will fail\r\n        _status = _ENTERED;\r\n    }\r\n\r\n    function _nonReentrantAfter() private {\r\n        // By storing the original value once again, a refund is triggered (see\r\n        // https://eips.ethereum.org/EIPS/eip-2200)\r\n        _status = _NOT_ENTERED;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\r\n     * `nonReentrant` function in the call stack.\r\n     */\r\n    function _reentrancyGuardEntered() internal view returns (bool) {\r\n        return _status == _ENTERED;\r\n    }\r\n}\r\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/IAeraV2Factory.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport {\n    AssetRegistryParameters,\n    HooksParameters,\n    VaultParameters\n} from \"../Types.sol\";\n\n/// @title IAeraV2Factory\n/// @notice Interface for the V2 vault factory.\ninterface IAeraV2Factory {\n    /// @notice Create V2 vault.\n    /// @param saltInput The salt input value to generate salt.\n    /// @param description Vault description.\n    /// @param vaultParameters Struct details for vault deployment.\n    /// @param assetRegistryParameters Struct details for asset registry deployment.\n    /// @param hooksParameters Struct details for hooks deployment.\n    /// @return deployedVault The address of deployed vault.\n    /// @return deployedAssetRegistry The address of deployed asset registry.\n    /// @return deployedHooks The address of deployed hooks.\n    function create(\n        bytes32 saltInput,\n        string calldata description,\n        VaultParameters calldata vaultParameters,\n        AssetRegistryParameters memory assetRegistryParameters,\n        HooksParameters memory hooksParameters\n    )\n        external\n        returns (\n            address deployedVault,\n            address deployedAssetRegistry,\n            address deployedHooks\n        );\n\n    /// @notice Calculate deployment address of V2 vault.\n    /// @param saltInput The salt input value to generate salt.\n    /// @param description Vault description.\n    /// @param vaultParameters Struct details for vault deployment.\n    function computeVaultAddress(\n        bytes32 saltInput,\n        string calldata description,\n        VaultParameters calldata vaultParameters\n    ) external view returns (address);\n\n    /// @notice Returns the address of wrapped native token.\n    function wrappedNativeToken() external view returns (address);\n\n    /// @notice Returns vault parameters for vault deployment.\n    /// @return owner Initial owner address.\n    /// @return assetRegistry Asset registry address.\n    /// @return hooks Hooks address.\n    /// @return guardian Guardian address.\n    /// @return feeRecipient Fee recipient address.\n    /// @return fee Fees accrued per second, denoted in 18 decimal fixed point format.\n    function parameters()\n        external\n        view\n        returns (\n            address owner,\n            address assetRegistry,\n            address hooks,\n            address guardian,\n            address feeRecipient,\n            uint256 fee\n        );\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/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/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/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"
      },
      "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/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/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/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/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/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}"
      }
    },
    "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": {}
    }
  }}