AllocateModule

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/module/AllocateModule.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {IERC20, IERC4626} from "@openzeppelin-contracts/interfaces/IERC4626.sol";
import {IAllocateModule} from "../interface/IAllocateModule.sol";
import {IStrategyTemplate} from "../interface/IStrategyTemplate.sol";
import {IConcreteStandardVaultImpl} from "../interface/IConcreteStandardVaultImpl.sol";
import {ConcreteStandardVaultImplStorageLib} from "../lib/storage/ConcreteStandardVaultImplStorageLib.sol";
import {SafeCast} from "@openzeppelin-contracts/utils/math/SafeCast.sol";
import {SafeERC20} from "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

contract AllocateModule is IAllocateModule {
    using SafeCast for uint256;
    using SafeERC20 for IERC20;

    /// @inheritdoc IAllocateModule
    function allocateFunds(bytes calldata data) external {
        AllocateParams[] memory params = abi.decode(data, (AllocateParams[]));

        ConcreteStandardVaultImplStorageLib.ConcreteStandardVaultImplStorage storage $ =
            ConcreteStandardVaultImplStorageLib.fetch();

        for (uint256 i; i < params.length; ++i) {
            // Only allocate to Active strategies
            if ($.strategyData[params[i].strategy].status != IConcreteStandardVaultImpl.StrategyStatus.Active) {
                continue;
            }

            uint256 amount;
            if (params[i].isDeposit) {
                IERC20(IERC4626(address(this)).asset()).forceApprove(params[i].strategy, type(uint256).max);

                amount = IStrategyTemplate(params[i].strategy).allocateFunds(params[i].extraData);

                IERC20(IERC4626(address(this)).asset()).forceApprove(params[i].strategy, 0);

                $.strategyData[params[i].strategy].allocated += amount.toUint120();
            } else {
                amount = IStrategyTemplate(params[i].strategy).deallocateFunds(params[i].extraData);
                $.strategyData[params[i].strategy].allocated -= amount.toUint120();
            }

            emit AllocatedFunds(params[i].strategy, params[i].isDeposit, amount, params[i].extraData);
        }
    }
}
"
    },
    "node_modules/@openzeppelin/contracts/interfaces/IERC4626.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
"
    },
    "src/interface/IAllocateModule.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/**
 * @title IAllocateModule
 * @dev Interface for the AllocateModule contract that handles fund allocation and deallocation across multiple strategies.
 * @dev This module enables the vault to efficiently manage funds across different yield-generating strategies
 *      by batching multiple allocation/deallocation operations in a single transaction.
 *
 * @notice The AllocateModule serves as a coordinator for strategy operations, allowing the vault to:
 * - Allocate funds to multiple strategies in a single call
 * - Deallocate funds from multiple strategies in a single call
 * - Maintain accurate accounting of allocated amounts per strategy
 *
 * @notice This module is typically used during rebalancing operations where the vault needs to
 *         adjust allocations across multiple strategies based on current market conditions,
 *         strategy performance, or allocation targets.
 */
interface IAllocateModule {
    /**
     * @dev Emitted when funds are allocated or deallocated from a strategy.
     *
     * @param strategy The address of the strategy contract.
     * @param isDeposit True if this is an allocation (deposit) operation, false if it's a deallocation (withdrawal).
     * @param amount The amount of funds allocated or deallocated.
     * @param extraData Arbitrary calldata passed to the strategy's allocateFunds or deallocateFunds function.
     */
    event AllocatedFunds(address indexed strategy, bool indexed isDeposit, uint256 amount, bytes extraData);

    /**
     * @dev Structure containing parameters for a single allocation or deallocation operation.
     *
     * @param isDeposit True if this is an allocation (deposit) operation, false if it's a deallocation (withdrawal).
     * @param strategy The address of the strategy contract to interact with.
     * @param extraData Arbitrary calldata to pass to the strategy's allocateFunds or deallocateFunds function.
     *                  This allows for strategy-specific parameters like slippage tolerance, routing info, etc.
     */
    struct AllocateParams {
        bool isDeposit;
        address strategy;
        bytes extraData;
    }

    /**
     * @dev Executes multiple allocation and deallocation operations across different strategies in a single transaction.
     * @dev This function processes an array of allocation parameters, calling the appropriate strategy functions
     *      and updating the vault's internal accounting for each strategy.
     *
     * @param data ABI-encoded array of AllocateParams structures containing the operations to execute.
     *             Each AllocateParams specifies whether to allocate or deallocate funds, which strategy to use,
     *             and any additional data required by the strategy.
     *
     * @notice The function iterates through all provided parameters and:
     * - For deposits (isDeposit = true): Calls strategy.allocateFunds() and increases allocated amount
     * - For withdrawals (isDeposit = false): Calls strategy.deallocateFunds() and decreases allocated amount
     *
     * @notice All operations are executed atomically - if any single operation fails, the entire transaction reverts.
     *
     * @notice The function updates the vault's internal strategy accounting to track the total amount
     *         allocated to each strategy, which is used for yield calculation and strategy limits.
     */
    function allocateFunds(bytes calldata data) external;
}
"
    },
    "src/interface/IStrategyTemplate.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/**
 * @title IStrategyTemplate
 * @dev Interface that all strategy implementations must follow to be compatible with the vault system.
 * @dev Each strategy is bound to a single vault and manages that vault's funds in different protocols or investment opportunities.
 * @dev The Vault uses this interface to deploy, withdraw, and rebalance funds across multiple strategies.
 *
 * @notice This interface defines the core functionality required for strategy contracts:
 * - Asset management (allocation and deallocation of funds)
 * - Withdrawal capabilities for user redemptions
 * - Limit reporting for rebalancing operations
 * - Compatibility with the vault's underlying asset token
 *
 * @notice All strategies must implement proper access controls and ensure only authorized callers
 * (typically the vault) can execute fund management operations.
 *
 * @notice For strategies that accrue rewards from underlying protocols:
 * The vault has an arbitrary call execution function that can call any target with arbitrary data.
 * This is primarily used to claim rewards from external reward systems. Strategies that earn rewards
 * should provide dedicated functions that can be called by the vault through this mechanism to claim
 * rewards and forward them to the rewards distributor system.
 */

/**
 * @dev Enum representing different types of strategies
 */
enum StrategyType {
    ATOMIC, // 0: Strategy that executes operations atomically, provides on-chain accurate accounting of yield
    ASYNC, // 1: Strategy that requires asynchronous operations (multiple transactions), can provide stale (within defined latency) accounting of yield
    CROSSCHAIN // 2: Strategy that operates across different blockchain networks, can provide stale (within defined latency) accounting of yield

}

interface IStrategyTemplate {
    /**
     * @dev Allocates funds from the vault to the underlying protocol.
     * @dev This function will be called when the vault wants to deploy assets into the yield-generating protocol.
     *
     * @param data Arbitrary calldata that can be used to pass strategy-specific parameters for the allocation.
     *             This allows for flexible configuration of the allocation process (e.g., slippage tolerance,
     *             specific protocol parameters, routing information, etc.).
     *
     * - MUST emit the AllocateFunds event.
     * - MUST revert if all of assets cannot be deposited (due to allocation limit being reached, slippage, the protocol
     *   not being able to accept more funds, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
     */
    function allocateFunds(bytes calldata data) external returns (uint256);

    /**
     * @dev Deallocates funds from the underlying protocol back to the vault.
     * @dev This function will be called when the vault wants to withdraw assets from the yield-generating protocol.
     *
     * @param data Arbitrary calldata that can be used to pass strategy-specific parameters for the deallocation.
     *             This allows for flexible configuration of the withdrawal process (e.g., slippage tolerance,
     *             specific protocol parameters, withdrawal routing, etc.).
     *
     * - MUST emit the DeallocateFunds event.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the protocol
     *   not having enough liquidity, etc).
     */
    function deallocateFunds(bytes calldata data) external returns (uint256);

    /**
     * @dev Sends assets of underlying tokens to sender.
     * @dev This function will be called when the vault unwinds its position while depositor withdraws.
     *
     * - MUST emit the Withdraw event.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough assets, etc).
     */
    function onWithdraw(uint256 assets) external returns (uint256);

    /**
     * @dev Rescue function to withdraw tokens that may have been accidentally sent to the strategy.
     * @dev This function allows authorized users to rescue tokens that are not part of the strategy's normal operations.
     *
     * @param token The address of the token to rescue.
     * @param amount The amount of tokens to rescue. Use 0 to rescue all available tokens.
     *
     * - MUST only allow rescue of tokens that are not the strategy's primary asset (asset()).
     * - MUST emit appropriate events for the rescue operation.
     * - MUST revert if the caller is not authorized to perform token rescue.
     * - MUST revert if attempting to rescue the strategy's primary asset token.
     */
    function rescueToken(address token, uint256 amount) external;

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address);

    /**
     * @dev Returns the address of the vault that this strategy is bound to.
     *
     * - MUST return the vault address that was set during strategy initialization.
     * - MUST NOT revert.
     */
    function getVault() external view returns (address);

    /**
     * @dev Returns the type of strategy implementation.
     * @dev This function indicates the operational characteristics of the strategy.
     *
     * @return The strategy type as defined in the StrategyType enum.
     *
     * - MUST return one of the defined StrategyType values.
     * - MUST NOT revert.
     * - ATOMIC: Strategy executes operations atomically in the same transaction, yield MUST be always atomicly updated in strategy allocated amount.
     * - ASYNC: Strategy requires asynchronous operations across multiple transactions, yield Can be updated asynchronously within documented latency.
     * - CROSSCHAIN: Strategy operates across different blockchain networks, yield Can be updated asynchronously within documented latency.
     */
    function strategyType() external view returns (StrategyType);

    /**
     * @dev Returns the total value of assets that the bound vault has allocated in the strategy.
     * @dev This function is mainly used during yield accrual operations to account for strategy yield or losses.
     *
     * @return The total value of allocated assets denominated in the asset() token.
     *
     * - MUST return the total value of assets that the bound vault has allocated to this strategy.
     * - MUST account for any losses or depreciation in the underlying protocol.
     * - MUST NOT revert.
     * - MUST return 0 if the vault has no funds allocated to this strategy.
     */
    function totalAllocatedValue() external view returns (uint256);

    /**
     * @dev Returns the maximum amount of assets that can be allocated to the underlying protocol.
     * @dev This function is primarily used by the Allocator to determine allocation limits when rebalancing funds.
     *
     * - MUST return the maximum amount of underlying assets that can be allocated in a single call to allocateFunds.
     * - MUST NOT revert.
     * - MAY return 0 if the protocol cannot accept any more funds.
     * - MAY return type(uint256).max if there is no practical limit.
     */
    function maxAllocation() external view returns (uint256);

    /**
     * @dev Returns the maximum amount of assets that can be withdrawn from the strategy by the vault.
     * @dev This function is primarily used by the vault to determine withdrawal limits when covering user redemptions.
     *
     * - MUST return the maximum amount of underlying assets that can be withdrawn in a single call to onWithdraw.
     * - MUST NOT revert.
     * - MAY return 0 if no funds are available for withdrawal.
     * - SHOULD reflect current liquidity constraints and strategy-specific withdrawal limits.
     */
    function maxWithdraw() external view returns (uint256);
}
"
    },
    "src/interface/IConcreteStandardVaultImpl.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {IUpgradeableVault} from "./IUpgradeableVault.sol";
import {Hooks} from "./IHook.sol";
import {IERC4626} from "@openzeppelin-contracts/interfaces/IERC4626.sol";
import {IAccessControlEnumerable} from "@openzeppelin-contracts/access/extensions/IAccessControlEnumerable.sol";

/**
 * @title IConcreteStandardVaultImpl
 * @dev Interface for the standard vault implementation that manages multiple investment strategies.
 * @dev This interface extends the base tokenized vault functionality with strategy management capabilities.
 * @dev Strategies are external contracts that implement the IStrategyTemplate interface and handle
 * fund allocation to different yield-generating protocols or investment opportunities.
 */
interface IConcreteStandardVaultImpl is IUpgradeableVault, IERC4626, IAccessControlEnumerable {
    /**
     * @dev Thrown when attempting to withdraw to the zero address.
     */
    error InvalidReceiver();

    /**
     * @dev Thrown when attempting to add a strategy that uses a different asset than the vault.
     */
    error InvalidStrategyAsset();

    /**
     * @dev Thrown when attempting to add a strategy that has already been added to the vault.
     */
    error StrategyAlreadyAdded();

    /**
     * @dev Thrown when attempting to operate on a strategy that doesn't exist in the vault.
     */
    error StrategyDoesNotExist();

    /**
     * @dev Thrown when attempting to interact with a strategy that is halted.
     */
    error StrategyIsHalted();

    /**
     * @dev Thrown when attempting to halt a strategy that is already halted.
     */
    error StrategyAlreadyHalted();

    /**
     * @dev Thrown when attempting to toggle the status of an inactive strategy.
     */
    error CannotToggleInactiveStrategy();

    /**
     * @dev Thrown when attempting to set a management fee without setting a recipient first.
     */
    error FeeRecipientNotSet();

    /**
     * @dev Thrown when attempting to set a management fee that exceeds the maximum allowed.
     */
    error ManagementFeeExceedsMaximum();

    /**
     * @dev Thrown when attempting to set a performance fee that exceeds the maximum allowed.
     */
    error PerformanceFeeExceedsMaximum();

    /**
     * @dev Thrown when attempting to set an invalid fee recipient address (address(0)).
     */
    error InvalidFeeRecipient();

    /**
     * @dev Thrown when the allocate module is invalid.
     */
    error InvalidAllocateModule();

    /**
     * @dev Thrown when the asset is invalid.
     */
    error InvalidAsset();

    /**
     * @dev Thrown when the initial vault manager is invalid.
     */
    error InvalidInitialVaultManager();

    /**
     * @dev Thrown when the name is invalid.
     */
    error InvalidName();

    /**
     * @dev Thrown when the symbol is invalid.
     */
    error InvalidSymbol();

    /**
     * @dev Thrown when the deposit limits are invalid.
     */
    error InvalidDepositLimits();

    /**
     * @dev Thrown when the withdraw limits are invalid.
     */
    error InvalidWithdrawLimits();

    /**
     * @dev Thrown when the asset amount is out of bounds.
     */
    error AssetAmountOutOfBounds(address sender, uint256 assets, uint256 minDepositAmount, uint256 maxDepositAmount);

    /**
     * @dev Thrown when attempting to remove a strategy that has allocation or is in the deallocation order.
     */
    error StrategyHasAllocation();

    /**
     * @dev Thrown when the vault has insufficient balance to process the epoch.
     */
    error InsufficientBalance();

    /**
     * @dev Thrown when calculated shares are zero.
     */
    error InsufficientShares();

    /**
     * @dev Thrown when calculated assets are zero.
     */
    error InsufficientAssets();

    /**
     * @dev Emitted when a new strategy is successfully added to the vault.
     * @param strategy The address of the strategy contract that was added.
     */
    event StrategyAdded(address strategy);

    /**
     * @dev Emitted when a strategy is successfully removed from the vault.
     * @param strategy The address of the strategy contract that was removed.
     */
    event StrategyRemoved(address strategy);

    /**
     * @dev Emitted when a strategy is set to Halted status.
     * @param strategy The address of the strategy contract that was halted.
     */
    event StrategyHalted(address strategy);

    /**
     * @dev Emitted when a strategy's status is toggled between Active and Halted.
     * @param strategy The address of the strategy contract whose status was toggled.
     */
    event StrategyStatusToggled(address indexed strategy);

    /**
     * @dev Emitted when the yield accrual operation is completed across all strategies.
     *
     * @param totalPositiveYield The total amount of positive yield generated across all strategies.
     * @param totalNegativeYield The total amount of losses incurred across all strategies.
     */
    event YieldAccrued(uint256 totalPositiveYield, uint256 totalNegativeYield);

    /**
     * @dev Emitted when management fee is accrued.
     * @param recipient The address that received the management fee shares.
     * @param shares The number of shares minted as management fee.
     * @param feeAmount The asset value of the management fee.
     */
    event ManagementFeeAccrued(address indexed recipient, uint256 shares, uint256 feeAmount);

    /**
     * @dev Emitted when performance fee is accrued.
     * @param recipient The address that received the performance fee shares.
     * @param shares The number of shares minted as performance fee.
     * @param feeAmount The asset value of the performance fee.
     */
    event PerformanceFeeAccrued(address indexed recipient, uint256 shares, uint256 feeAmount);

    /**
     * @dev Emitted when management fee is updated.
     * @param managementFee The new management fee rate in basis points.
     */
    event ManagementFeeUpdated(uint16 managementFee);

    /**
     * @dev Emitted when management fee recipient is updated.
     * @param managementFeeRecipient The new management fee recipient address.
     */
    event ManagementFeeRecipientUpdated(address managementFeeRecipient);

    /**
     * @dev Emitted when performance fee is updated.
     * @param performanceFee The new performance fee rate in basis points.
     */
    event PerformanceFeeUpdated(uint16 performanceFee);

    /**
     * @dev Emitted when performance fee recipient is updated.
     * @param performanceFeeRecipient The new performance fee recipient address.
     */
    event PerformanceFeeRecipientUpdated(address performanceFeeRecipient);

    /**
     * @dev Emitted when deposit limits are updated.
     * @param maxDepositAmount The new maximum deposit amount.
     * @param minDepositAmount The new minimum deposit amount.
     */
    event DepositLimitsUpdated(uint256 maxDepositAmount, uint256 minDepositAmount);

    /**
     * @dev Emitted when withdraw limits are updated.
     * @param maxWithdrawAmount The new maximum withdraw amount.
     * @param minWithdrawAmount The new minimum withdraw amount.
     */
    event WithdrawLimitsUpdated(uint256 maxWithdrawAmount, uint256 minWithdrawAmount);

    /**
     * @dev Emitted when the deallocation order is updated.
     */
    event DeallocationOrderUpdated();

    /**
     * @dev Emitted when an individual strategy's yield is accrued.
     *
     * @param strategy The address of the strategy contract whose yield was accrued.
     * @param currentTotalAllocatedValue The current total allocated value reported by the strategy.
     * @param yield The amount of positive yield generated by this strategy since last accrual.
     * @param loss The amount of loss incurred by this strategy since last accrual.
     */
    event StrategyYieldAccrued(
        address indexed strategy, uint256 currentTotalAllocatedValue, uint256 yield, uint256 loss
    );

    /**
     * @dev Enumeration of possible strategy statuses within the vault.
     * @dev Inactive: Strategy is inactive and cannot receive new allocations.
     * @dev Active: Strategy is active and can receive allocations and process withdrawals normally.
     * @dev Halted: Strategy is halted, typically due to detected issues or failures.
     * In this state, the strategy can be removed even if it has allocated funds
     */
    enum StrategyStatus {
        Inactive,
        Active,
        Halted
    }

    /**
     * @dev Structure containing metadata and state information for each strategy.
     * @dev status: Current operational status of the strategy.
     * @dev allocated: Total amount of vault assets currently allocated to this strategy, denominated in the vault's underlying asset token.
     */
    struct StrategyData {
        StrategyStatus status;
        uint120 allocated;
    }

    /**
     * @dev Adds a new strategy to the vault.
     * @dev The strategy must implement the IStrategyTemplate interface and use the same underlying asset as the vault.
     * @dev Only callable by accounts with the STRATEGY_MANAGER role.
     *
     * @param strategy The address of the strategy contract to add.
     *
     * Requirements:
     * - The strategy's asset() must match the vault's asset()
     * - The strategy must not already be added to the vault
     * - Caller must have STRATEGY_MANAGER role
     *
     * Emits:
     * - StrategyAdded event
     *
     * Reverts:
     * - InvalidStrategyAsset if strategy uses different asset
     * - StrategyAlreadyAdded if strategy is already in the vault
     */
    function addStrategy(address strategy) external;

    /**
     * @dev Removes a strategy from the vault.
     * @dev The strategy can only be removed if it has no allocated funds, unless it's in Halted status.
     * @dev Only callable by accounts with the STRATEGY_MANAGER role.
     *
     * @param strategy The address of the strategy contract to remove.
     *
     * Requirements:
     * - Strategy must exist in the vault
     * - Strategy must have zero allocated funds OR be in Halted status
     * - Caller must have STRATEGY_MANAGER role
     *
     * Emits:
     * - StrategyRemoved event
     *
     * Reverts:
     * - StrategyDoesNotExist if strategy is not in the vault
     * - Custom revert if strategy has allocated funds and is not in Halted status
     */
    function removeStrategy(address strategy) external;

    /**
     * @dev Toggles a strategy's status between Active and Halted.
     * @dev This is a safety mechanism to isolate problematic strategies or reactivate previously halted ones.
     * @dev Active strategies can receive allocations and participate in yield accrual and withdrawal operations.
     * @dev Halted strategies are skipped during yield accrual and withdrawal operations.
     * @dev Only callable by accounts with the STRATEGY_MANAGER role.
     *
     * @param strategy The address of the strategy contract to toggle.
     *
     * Requirements:
     * - Strategy must exist in the vault
     * - Strategy must be either Active or Halted (cannot toggle Inactive strategies)
     * - Caller must have STRATEGY_MANAGER role
     *
     * Emits:
     * - StrategyStatusToggled event
     *
     * Reverts:
     * - StrategyDoesNotExist if strategy is not in the vault
     */
    function toggleStrategyStatus(address strategy) external;

    /**
     * @notice Executes fund allocation and deallocation operations across multiple strategies.
     * @dev This function performs a yield accrual operation first to update vault accounting,
     *      then executes the allocation operations specified in the data parameter.
     * @dev All operations are performed via delegatecall to the respective modules to maintain
     *      proper storage context and access control.
     * @param data ABI-encoded array of AllocateParams structures containing the allocation
     *             operations to execute. Each param specifies whether to allocate or deallocate
     *             funds, which strategy to use, and any additional data required by the strategy.
     * @dev Only callable by accounts with the ALLOCATOR role.
     * @dev The function automatically triggers yield accrual before allocation to ensure
     *         accurate vault accounting prior to fund movements.
     */
    function allocate(bytes calldata data) external;

    /**
     * @notice Accrues yield and accounts for losses across all active strategies in the vault.
     * @dev This function updates the vault's internal accounting by querying the current
     *      value of all strategy allocations and calculating net yield or losses.
     * @dev This function can be called by anyone to update the vault's accounting.
     * @dev The yield accrual operation does not trigger actual fund movements, it only
     *         updates the vault's internal state to reflect current strategy values.
     */
    function accrueYield() external;

    /**
     * @notice Updates the management fee for the vault.
     * @param managementFee The new management fee in basis points.
     * @dev Only callable by accounts with VAULT_MANAGER role.
     * @dev Fee must be <= MAX_MANAGEMENT_FEE.
     * @dev If fee > 0, recipient must be set.
     */
    function updateManagementFee(uint16 managementFee) external;

    /**
     * @notice Updates the management fee recipient for the vault.
     * @param recipient The new management fee recipient address.
     * @dev Only callable by accounts with VAULT_MANAGER role.
     * @dev Recipient cannot be address(0).
     */
    function updateManagementFeeRecipient(address recipient) external;

    /**
     * @notice Updates the performance fee for the vault.
     * @param performanceFee The new performance fee in basis points.
     * @dev Only callable by accounts with VAULT_MANAGER role.
     * @dev Fee must be <= MAX_PERFORMANCE_FEE.
     * @dev If fee > 0, recipient must be set.
     */
    function updatePerformanceFee(uint16 performanceFee) external;

    /**
     * @notice Updates the performance fee recipient for the vault.
     * @param recipient The new performance fee recipient address.
     * @dev Only callable by accounts with VAULT_MANAGER.
     * @dev Recipient cannot be address(0).
     */
    function updatePerformanceFeeRecipient(address recipient) external;

    /**
     * @notice Returns the current fee configuration for the vault.
     * @return currentManagementFee The current management fee in basis points.
     * @return currentManagementFeeRecipient The current management fee recipient address.
     * @return currentLastManagementFeeAccrual The timestamp of the last management fee accrual.
     * @return currentPerformanceFee The current performance fee in basis points.
     * @return currentPerformanceFeeRecipient The current performance fee recipient address.
     */
    function getFeeConfig()
        external
        view
        returns (
            uint16 currentManagementFee,
            address currentManagementFeeRecipient,
            uint32 currentLastManagementFeeAccrual,
            uint16 currentPerformanceFee,
            address currentPerformanceFeeRecipient
        );

    /**
     * @notice Sets the hooks for the vault.
     * @dev This function sets the hooks for the vault.
     * @dev Only callable by accounts with the HOOK_MANAGER role.
     * @param hooks The hooks to set.
     */
    function setHooks(Hooks memory hooks) external;

    /**
     * @notice Previews the total assets that would be available after accruing yield from all strategies.
     * @dev This function simulates the yield accrual operation without actually executing it,
     *      providing a view of what the vault's total assets would be after accounting
     *      for yield and losses across all active strategies.
     * @dev The calculation includes the current lastTotalAssets plus any positive
     *      yield minus any losses that would be realized during yield accrual.
     * @dev This is a view function that does not modify state or trigger any actual
     *      fund movements or strategy interactions.
     *
     * @return The total amount of assets that would be available in the vault after yield accrual,
     *         denominated in the vault's underlying asset token.
     * @return The total amount of shares that would be available in the vault after yield accrual,
     *         calculated as current totalSupply + management fee shares.
     */
    function previewAccrueYield() external view returns (uint256, uint256);

    /**
     * @dev Retrieves the current data and status information for a specific strategy.
     * @dev This function provides read-only access to strategy metadata including allocation amounts and status.
     *
     * @param strategy The address of the strategy contract to query.
     * @return The StrategyData struct containing the strategy's current status and allocated amount.
     *
     * Note:
     * - Returns default values (Inactive status, 0 allocated) for non-existent strategies
     * - Does not revert for invalid strategy addresses
     */
    function getStrategyData(address strategy) external view returns (StrategyData memory);

    /**
     * @dev Returns an array of all strategy addresses currently managed by the vault.
     * @dev This function provides a way to enumerate all active strategies for external integrations and monitoring.
     *
     * @return An array containing the addresses of all strategies added to the vault.
     *
     * Note:
     * - The returned array includes strategies in all statuses (Active, Inactive, Emergency)
     * - The order of strategies in the array is not guaranteed
     * - Returns an empty array if no strategies have been added
     */
    function getStrategies() external view returns (address[] memory);

    /**
     * @dev Returns the address of the allocate module.
     *
     * @return The address of the allocate module.
     */
    function allocateModule() external view returns (address);

    /**
     * @dev Returns the management fee configuration.
     * @return managementFeeRecipient The address that receives management fees.
     * @return managementFeeRate The management fee rate in basis points (where 10,000 = 100%).
     * @return lastAccrualTime The timestamp of the last management fee accrual.
     */
    function managementFee()
        external
        view
        returns (address managementFeeRecipient, uint16 managementFeeRate, uint32 lastAccrualTime);

    /**
     * @dev Sets the deposit limits.
     * @param maxDepositAmount The maximum deposit amount.
     * @param minDepositAmount The minimum deposit amount.
     * @dev Only callable by accounts with VAULT_MANAGER role.
     */
    function setDepositLimits(uint256 maxDepositAmount, uint256 minDepositAmount) external;

    /**
     * @dev Sets the withdraw limits.
     * @param maxWithdrawAmount The maximum withdraw amount.
     * @param minWithdrawAmount The minimum withdraw amount.
     * @dev Only callable by accounts with VAULT_MANAGER role.
     */
    function setWithdrawLimits(uint256 maxWithdrawAmount, uint256 minWithdrawAmount) external;

    /**
     * @dev Returns the deposit limits.
     * @return maxDepositAmount The maximum deposit amount.
     * @return minDepositAmount The minimum deposit amount.
     */
    function getDepositLimits() external view returns (uint256 maxDepositAmount, uint256 minDepositAmount);

    /**
     * @dev Returns the withdraw limits.
     * @return maxWithdrawAmount The maximum withdraw amount.
     * @return minWithdrawAmount The minimum withdraw amount.
     */
    function getWithdrawLimits() external view returns (uint256 maxWithdrawAmount, uint256 minWithdrawAmount);

    /**
     * @dev Returns the performance fee configuration.
     * @return performanceFeeRecipient The address that receives performance fees.
     * @return performanceFeeRate The performance fee rate in basis points (where 10,000 = 100%).
     */
    function performanceFee() external view returns (address performanceFeeRecipient, uint16 performanceFeeRate);

    /**
     * @dev Returns the total amount of assets allocated to all strategies.
     *
     * @return The total amount of assets allocated to all strategies.
     */
    function getTotalAllocated() external view returns (uint256);

    /**
     * @dev Returns the cached value of total assets after the last call.
     *
     * @return The cached value of total assets after the last call.
     */
    function cachedTotalAssets() external view returns (uint256);

    /**
     * @dev Returns the deallocation order from strategies.
     *
     * @return order An array of strategy addresses in the order they should be deallocated.
     */
    function getDeallocationOrder() external view returns (address[] memory order);

    /**
     * @dev Sets the deallocation order for strategies.
     * @dev Only callable by accounts with the ALLOCATOR role.
     * @param order An array of strategy addresses in the order they should be deallocated.
     */
    function setDeallocationOrder(address[] calldata order) external;
}
"
    },
    "src/lib/storage/ConcreteStandardVaultImplStorageLib.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/types/Time.sol)
pragma solidity ^0.8.24;

import {IConcreteStandardVaultImpl} from "../../interface/IConcreteStandardVaultImpl.sol";
import {EnumerableSet} from "@openzeppelin-contracts/utils/structs/EnumerableSet.sol";
import {Hooks} from "../Hooks.sol";

library ConcreteStandardVaultImplStorageLib {
    /// @dev keccak256(abi.encode(uint256(keccak256("concrete.storage.ConcreteStandardVaultImplStorage")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant ConcreteStandardVaultImplStorageLocation =
        0xe74d828616eceb28be4a8cf3f9eeee868e1f44ce928ee17a9d7ad296fa52be00;

    /// @custom:storage-location erc7201:concrete.storage.ConcreteStandardVaultImplStorage
    struct ConcreteStandardVaultImplStorage {
        /// @dev max deposit amount
        uint256 maxDepositAmount;
        /// @dev max withdraw amount
        uint256 maxWithdrawAmount;
        /// @dev min deposit amount
        uint256 minDepositAmount;
        /// @dev min withdraw amount
        uint256 minWithdrawAmount;
        /// @dev allocate module's address
        address allocateModule;
        /// 1 slot: 160 + 16 + 32
        /// @dev management fee recipient
        address managementFeeRecipient;
        /// @dev annual management fee rate in basis points
        uint16 managementFee;
        /// @dev timestamp of last management fee accrual
        uint32 lastManagementFeeAccrual;
        /// 1 slot: 160 + 16
        /// @dev performance fee recipient
        address performanceFeeRecipient;
        /// @dev annual performance fee rate in basis points
        uint16 performanceFee;
        /// @dev high water mark
        uint128 performanceFeeHighWaterMark;
        /// Mapping between a strategy address and it's data
        mapping(address => IConcreteStandardVaultImpl.StrategyData) strategyData;
        /// An set of strategy addresses that ConcreteVault allocates to
        EnumerableSet.AddressSet strategies;
        /// Defines the order in which funds are retrieved from strategies to fulfill withdrawals
        address[] deallocationOrder;
        /// @dev hooks
        Hooks hooks;
    }

    /**
     *
     */
    function fetch() internal pure returns (ConcreteStandardVaultImplStorage storage $) {
        assembly {
            $.slot := ConcreteStandardVaultImplStorageLocation
        }
    }
}
"
    },
    "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input m

Tags:
ERC20, ERC165, Proxy, Mintable, Swap, Liquidity, Yield, Upgradeable, Factory|addr:0x14a905158aebcb44451857603006a7dc23b0d014|verified:true|block:23598975|tx:0xfd3b2f0e90b0de0cd68bfc826960035e7d40d4fb4b8426ccefd4645ce12d1a51|first_check:1760726950

Submitted on: 2025-10-17 20:49:10

Comments

Log in to comment.

No comments yet.