For the complete documentation index, see llms.txt. This page is also available as Markdown.

Withdrawal Queue Mechanics

Overview

The withdrawal queue system orchestrates asset withdrawals across multiple chains and vaults through two fixed-size queues:

  • Local queue for same-chain vaults

  • Cross-chain queue for vaults on other networks

Queue Structure

    // Fixed size for all queues
    uint256 public constant WITHDRAWAL_QUEUE_SIZE = 30;
    
    // Queue storage
    uint256[WITHDRAWAL_QUEUE_SIZE] public localWithdrawalQueue;
    uint256[WITHDRAWAL_QUEUE_SIZE] public xChainWithdrawalQueue;

Queue Management

Queue Registration

    /// @notice Add a new vault to the portfolio
    /// @param chainId chainId of the vault
    /// @param superformId id of superform in case its crosschain
    /// @param vault vault address
    /// @param vaultDecimals decimals of ERC4626 token
    /// @param oracle vault shares price oracle
   function addVault(
        uint32 chainId,
        uint256 superformId,
        address vault,
        uint8 vaultDecimals,
        ISharePriceOracle oracle
    )
        external
        onlyRoles(MANAGER_ROLE)
    {
        if (superformId == 0) revert();
        // If its already listed revert
        if (isVaultListed(vault)) revert VaultAlreadyListed();

        // Save it into storage
        vaults[superformId].chainId = chainId;
        vaults[superformId].superformId = superformId;
        vaults[superformId].vaultAddress = vault;
        vaults[superformId].decimals = vaultDecimals;
        vaults[superformId].oracle = oracle;
        uint192 lastSharePrice = vaults[superformId].sharePrice(asset()).toUint192();
        if (lastSharePrice == 0) revert();
        _vaultToSuperformId[vault] = superformId;

        if (chainId == THIS_CHAIN_ID) {
            // Push it to the local withdrawal queue
            uint256[WITHDRAWAL_QUEUE_SIZE] memory queue = localWithdrawalQueue;
            for (uint256 i = 0; i != WITHDRAWAL_QUEUE_SIZE; i++) {
                if (queue[i] == 0) {
                    localWithdrawalQueue[i] = superformId;
                    break;
                }
            }
            // If its on the same chain perfom approval to vault
            asset().safeApprove(vault, type(uint256).max);
        } else {
            // Push it to the crosschain withdrawal queue
            uint256[WITHDRAWAL_QUEUE_SIZE] memory queue = xChainWithdrawalQueue;
            for (uint256 i = 0; i != WITHDRAWAL_QUEUE_SIZE; i++) {
                if (queue[i] == 0) {
                    xChainWithdrawalQueue[i] = superformId;
                    break;
                }
            }
        }

        emit AddVault(chainId, vault);
    }

Withdrawal Processing

State Tracking

Withdrawal Route Calculation

Queue Processing Logic

Asset Tracking

Optimization Strategies

Gas Optimizations

  1. Prioritizes idle assets (no withdrawal cost)

  2. Processes local withdrawals before cross-chain

  3. Batches cross-chain operations

  4. Uses unchecked blocks for counters

  5. Caches chain indexes and lengths

Slippage Protection

Asset Validation

Gas Analysis

  1. Estimated Costs

    • Local withdrawals: ~100k-200k gas

    • Cross-chain operations: varies by chain

    • Batch processing savings

  2. Queue Security Implications

    • Maximum queue size impact

    • Reordering attack vectors

    • Front-running mitigations

  3. Slippage Protection Analysis

    • Minimum output validation

    • Cross-chain slippage handling

    • Price impact considerations

Error Types

Last updated