Core Operations

MetaVault core operations consist of four main categories:

  • Deposit Operations (atomic via multicall)

  • Withdrawal Operations (4-step process)

  • Investment Operations (same and cross-chain)

  • Divestment Operations (same and cross-chain)

Deposit Operations

Atomic Deposit (via Multicall)

// Example of atomic deposit using multicall
vault.multicall([
    // Step 1: Request Deposit
    abi.encodeWithSelector(
        vault.requestDeposit.selector,
        1000e6,      // 1000 USDC
        msg.sender,  // Controller
        msg.sender   // Owner
    ),
    // Step 2: Execute Deposit
    abi.encodeWithSelector(
        vault.deposit.selector,
        1000e6,      // Amount
        recipient,   // Share recipient
        msg.sender   // Controller
    )
]);

requestDeposit

function requestDeposit(
    uint256 assets,
    address controller,
    address owner
) public override noEmergencyShutdown returns (uint256 requestId)

First step of atomic deposit process.

Requirements:

  • Vault not in emergency shutdown

  • Assets approved for transfer

  • Asset amount non-zero

deposit

function deposit(
    uint256 assets,
    address to,
    address controller
) public override noEmergencyShutdown returns (uint256 shares)

Second step of atomic deposit process.

Events:

  • Deposit(controller, to, assets, shares)

Withdrawal Operations

Step 1: Request Redemption

function requestRedeem(
    uint256 shares,
    address controller,
    address owner
) public override returns (uint256 requestId)

Process:

  1. Verify share lock status

  2. Create pendingRedeemRequest

  3. Transfer shares to vault

  4. Set redeemLocked[controller] = true

Step 2: Process Request (via Relayer)

function processRedeemRequest(
    address controller,
    SingleXChainSingleVaultWithdraw calldata sXsV,
    SingleXChainMultiVaultWithdraw calldata sXmV,
    MultiXChainSingleVaultWithdraw calldata mXsV,
    MultiXChainMultiVaultWithdraw calldata mXmV
) external

Process:

  1. Check totalIdle() first

  2. If insufficient idle assets, calculate divest route

  3. Process withdrawals through ERC7540Engine

  4. Update pending to claimable state

Step 3: Settlement

function settleLiquidation(
    address controller,
    uint256[] calldata superformIds
) external

OR

function settleDivest(
    uint256[] calldata superformIds
) external

Process:

  1. Receive assets from cross-chain operations

  2. Move from pendingRedeemRequest to claimableRedeemRequest

  3. Update vault accounting

Step 4: Final Redemption

function redeem(
    uint256 shares,
    address receiver,
    address controller
) public override nonReentrant returns (uint256 assets)

Process:

  1. Verify redeemLocked[controller] = false

  2. Check claimableRedeemRequest

  3. Process redemption

  4. Clear claimable state

Investment Operations

Direct Investment (Same Chain)

investSingleDirectSingleVault

function investSingleDirectSingleVault(
    address vaultAddress,
    uint256 assets,
    uint256 minSharesOut
) public onlyRoles(MANAGER_ROLE) returns (uint256 shares)

Process Flow:

  1. Validate vault in approved list

  2. Record initial balance for share calculation

  3. Deposit assets into target vault

  4. Verify received shares meet minimum

  5. Update accounting:

    • Decrease _totalIdle

    • Increase _totalDebt

    • Update vault's totalDebt

  6. Emit Invest event

Example:

// Invest with 1% max slippage
uint256 shares = vault.investSingleDirectSingleVault(
    targetVault,
    1000e6,     // 1000 USDC
    990e6       // Min shares (1% slippage)
);

Cross-Chain Investments

investSingleXChainSingleVault

function investSingleXChainSingleVault(
    SingleXChainSingleVaultStateReq calldata req
) external payable onlyRoles(MANAGER_ROLE)

Process Flow:

  1. Gateway validation

  2. Asset transfer to gateway

  3. Initiate cross-chain deposit

  4. Track pending investments

  5. Update vault accounting

Example:

vault.investSingleXChainSingleVault{value: 0.1 ether}(
    SingleXChainSingleVaultStateReq({
        ambIds: [1],                // LayerZero
        dstChainId: 137,           // Polygon
        superformData: {
            superformId: vaultId,
            amount: 1000e6,
            minOutAmount: 990e6,    // 1% slippage
            hasDstSwap: false,
            retain4626: false
        }
    })
);

investMultiXChainMultiVault

function investMultiXChainMultiVault(
    MultiDstMultiVaultStateReq calldata req
) external payable onlyRoles(MANAGER_ROLE)

Process Flow:

  1. Multi-chain validation

  2. Calculate total investment

  3. Asset transfer to gateway

  4. Track individual vault investments

  5. Update global debt tracking

Example:

vault.investMultiXChainMultiVault{value: 0.5 ether}(
    MultiDstMultiVaultStateReq({
        ambIds: [
            [1],    // Polygon AMB
            [1]     // Arbitrum AMB
        ],
        dstChainIds: [137, 42161],
        superformsData: [
            {   // Polygon investments
                superformIds: [vault1, vault2],
                amounts: [1000e6, 2000e6],
                minOutAmounts: [990e6, 1980e6]
            },
            {   // Arbitrum investments
                superformIds: [vault3, vault4],
                amounts: [1500e6, 2500e6],
                minOutAmounts: [1485e6, 2475e6]
            }
        ]
    })
);

Divestment Operations

Direct Divestment

divestSingleDirectSingleVault

function divestSingleDirectSingleVault(
    address vaultAddress,
    uint256 shares,
    uint256 minAssetsOut
) public onlyRoles(MANAGER_ROLE) returns (uint256 assets)

Process Flow:

  1. Calculate share value

  2. Check if full withdrawal

  3. Redeem from target vault

  4. Verify minimum assets received

  5. Update accounting:

    • Increase _totalIdle

    • Decrease _totalDebt

    • Update vault's totalDebt

  6. Emit Divest event

Example:

uint256 assets = vault.divestSingleDirectSingleVault(
    vaultAddress,
    1000e18,    // 1000 shares
    990e6       // Min assets (1% slippage)
);

Cross-Chain Divestments

divestSingleXChainSingleVault

function divestSingleXChainSingleVault(
    SingleXChainSingleVaultStateReq calldata req
) external payable onlyRoles(MANAGER_ROLE)

Process Flow:

  1. Transfer NFTs to gateway

  2. Update debt tracking

  3. Initiate cross-chain withdrawal

  4. Track pending divest

  5. Wait for settlement

Example:

vault.divestSingleXChainSingleVault{value: 0.1 ether}(
    SingleXChainSingleVaultStateReq({
        ambIds: [1],
        dstChainId: 137,
        superformData: {
            superformId: vaultId,
            amount: 1000e18,
            minOutAmount: 990e6,
            hasDstSwap: false
        }
    })
);

divestMultiXChainMultiVault

function divestMultiXChainMultiVault(
    MultiDstMultiVaultStateReq calldata req
) external payable onlyRoles(MANAGER_ROLE)

Process Flow:

  1. Process multiple vaults per chain

  2. Batch NFT transfers

  3. Update debt per vault

  4. Track cross-chain operations

  5. Emit events per chain

Important Considerations:

  • Gas estimation per chain

  • Bridge timeouts

  • Slippage protection

  • Settlement verification

Example:

vault.divestMultiXChainMultiVault{value: 0.5 ether}(
    MultiDstMultiVaultStateReq({
        ambIds: [[1], [1]],
        dstChainIds: [137, 42161],
        superformsData: [
            {   // Polygon divests
                superformIds: [vault1, vault2],
                amounts: [1000e18, 2000e18],
                minOutAmounts: [990e6, 1980e6]
            },
            {   // Arbitrum divests
                superformIds: [vault3, vault4],
                amounts: [1500e18, 2500e18],
                minOutAmounts: [1485e6, 2475e6]
            }
        ]
    })
);

Last updated