Skip to main content
In user-facing documentation, a MultiVehicle is referred to as a Strategy. See Glossary.
A Multi-Vehicle is a sophisticated vault system built on the STEAM protocol. It manages multiple sub-vehicles (yield strategies) with advanced allocation and redemption capabilities, providing a single entry point for diversified DeFi strategies.

Architecture overview

A Multi-Vehicle is composed of 6 interconnected components:

The 6 components

1. MultiVehicle (main contract)

The STEAM-compliant entry point that users interact with directly. User operations:
  • Deposit assets — receive Multi-Vehicle shares
  • Redeem shares — receive base assets back
Key responsibilities:
  • User-facing STEAM operations (create, resume, unlock, recover)
  • Share minting and burning using ERC-4626-style exchange rates
  • Integration with QueryRedeemQueue for asynchronous redemptions

2. SectorAccountingEngine

The central accounting system implementing double-entry bookkeeping principles. Every asset movement is recorded as a transfer between sectors, ensuring the total supply of accounted assets remains constant.
SectorTypeDescription
ENTRYVirtualAssets entering the system (accounting only)
DEPOSITPhysicalIdle base assets awaiting allocation
ALLOCATIONPhysicalSub-vehicle shares (deployed capital)
REDEEMPhysicalBase assets ready for withdrawal
EXITVirtualAssets leaving the system (accounting only)
Vehicle sectorsStagingPer-vehicle staging areas
Pending sectorsEphemeralAssets in active queries (in-flight)
For a deep dive into how sectors work and how funds flow between them, see Accounting and flow of funds.

3. QueueStrategyEngine

Defines the allocation strategy through configurable priority queues. The asset manager sets up deposit and redeem queues that control how capital is distributed.

Deposit queue

A prioritized list of {vehicle, target} pairs:
  1. Processes in order (index 0 = highest priority)
  2. target = maximum shares to allocate to a vehicle before moving to the next entry
  3. Stops when the vehicle reaches its target, hits maxDepositable, or assets are exhausted
// Initial state
depositQueue = [{aave, 60k}, {morpho, 30k}]
currentHoldings = {aave: 50k, morpho: 20k}
newDeposit = 20k shares

// Algorithm execution:
// 1. Check aave: 50k < 60k target
//    -> allocate min(20k available, 10k to reach target) = 10k to aave
//    -> aave now has 60k

// 2. Remaining: 10k shares

// 3. Check morpho: 20k < 30k target
//    -> allocate min(10k available, 10k to reach target) = 10k to morpho
//    -> morpho now has 30k

// 4. Done: aave=60k, morpho=30k
The deposit queue does not enforce ongoing ratios. If a vehicle grows past its target from yield alone, new deposits skip it and go to the next queue entry.

Redeem queue

A prioritized list of {vehicle, target} pairs where target represents a floor (minimum shares to maintain):
  1. Processes in order (index 0 = highest priority)
  2. Redeems from a vehicle down to its floor
  3. Moves to the next entry if more assets are needed
// Initial state
redeemQueue = [{aave, 20k}, {morpho, 10k}]
currentHoldings = {aave: 60k, morpho: 30k}
redeemRequest = 50k shares

// Algorithm execution:
// 1. Check aave: 60k holdings, 20k floor
//    -> redeem min(50k requested, 60k - 20k available) = 40k from aave
//    -> aave now has 20k (at floor)

// 2. Remaining: 10k shares

// 3. Check morpho: 30k holdings, 10k floor
//    -> redeem min(10k requested, 30k - 10k available) = 10k from morpho
//    -> morpho now has 20k

// 4. Done: redeemed 50k total

4. SubQueryEngine

Manages the STEAM query lifecycle for operations dispatched to sub-vehicles. It tracks ephemeral accounting to prevent share price distortion during asynchronous operations. Ephemeral accounting ensures that totalAssets() remains accurate even when assets are in-flight:
  • When a sub-query enters PROCESSING, the system uses the vehicle’s estimate() function to record expected outputs
  • As actual shares are received on settlement, the ephemeral estimate is replaced with real values
  • This prevents spikes or drops in the Multi-Vehicle’s share price during async settlements

5. QueryRedeemQueue

Handles asynchronous redemptions when immediate liquidity is insufficient:
  • Demands — user redemption requests, created during redeem commit. Each demand records the shares owed and is assigned a sequential index.
  • Fulfillments — liquidity provisions created by a keeper or operator calling feedQueryRedeemQueue. Each fulfillment covers one or more demands using FIFO matching.
  • Partial fills — a single demand can be fulfilled across multiple rounds. The queue tracks cumulative fulfillment progress using binary search for efficient matching.
  • Claiming — once fulfilled (partially or fully), users call claimRedeemQueue to receive their base assets. No manual monitoring is needed — the queue tracks what’s owed.

6. VehicleRegistry

Manages authorization and configuration for sub-vehicles. Every vehicle must be registered here before it can receive capital from the Multi-Vehicle. Key responsibilities:
  • Validate vehicle compatibility (STEAM standard, SingleAsset, matching base asset)
  • Store per-vehicle configuration (mode and cap)
  • Enforce role-based access for authorization changes

The role of the asset manager

The asset manager configures and operates the Multi-Vehicle. Beyond setting initial parameters, they have four active levers.

Rebalance capital

Move assets directly between sub-vehicles using rebalance:
// Redeem from source, deposit into destination
accountingEngine.rebalance(fromVehicle, toVehicle, shareAmount);
If the source vehicle is asynchronous, the redemption settles first and the deposit is staged in the destination vehicle’s sector until settlement completes.

Manage sub-vehicles

Add or remove yield sources at any time:
// Authorize a new sub-vehicle
vehicleRegistry.authorize(newVehicle);

// Or authorize with initial mode and cap
vehicleRegistry.authorizeAndConfigure(newVehicle, config);

// Remove a sub-vehicle (redeem all positions first)
vehicleRegistry.unauthorize(vehicleToRemove);
Removing a sub-vehicle prevents new allocations but does not automatically redeem existing positions — unallocate first.

Reconfigure queues

Update allocation priorities without moving capital:
// Set new deposit and redeem queues
strategyEngine.setQueues(newDepositQueue, newRedeemQueue);
New deposits and redemptions follow the updated order immediately. Existing positions are unaffected.

Feed redemption liquidity

When async redemptions are pending in the QueryRedeemQueue, feed liquidity to fulfill demands:
multiVehicle.feedQueryRedeemQueue();
Keepers typically automate this, but operators can trigger it manually if redemptions stall.

Authorization and guardrails

Every sub-vehicle must be explicitly authorized in the VehicleRegistry before it can receive capital. Authorization validates that the vehicle implements the STEAM standard, is a SingleAsset vehicle, and uses the same base asset as the Multi-Vehicle.

Vehicle configuration

Each authorized vehicle has a configuration with two parameters:
ParameterValuesDescription
ModeAutomatic (default), ManualAutomatic vehicles participate in queue-based allocation. Manual vehicles only receive capital through explicit rebalancing.
CapShare target (default: unlimited)Maximum allocation target for this vehicle. Limits exposure to a single yield source.
// Authorize with Automatic mode and a 100k share cap
vehicleRegistry.authorizeAndConfigure(vehicle, VehicleConfig({
    mode: VehicleMode.Automatic,
    cap: Target(100_000e18)
}));

On-chain guardrails

Authorization and caps create enforceable boundaries:
  • Queue configuration cannot route capital to unauthorized vehicles
  • Allocation caps limit exposure regardless of queue targets or active rebalancing
  • Role-based access (via EAC) controls who can authorize vehicles, set caps, and reconfigure queues — allowing platforms commissioning a strategy to set guardrails that asset managers cannot override
This means strategies can run hands-off through queue automation while enforcing risk boundaries that neither automation nor operators can exceed.

Sync and async sub-vehicles

Multi-Vehicle orchestrates both synchronous and asynchronous sub-vehicles. Synchronous sub-vehicles (Aave, Compound, ERC-4626) complete in a single transaction:
// Sync flow: single transaction
// EMPTY -> UNLOCKING -> SETTLED
Asynchronous sub-vehicles (Ethena, Syrup) require multiple transactions:
// Async flow: multiple transactions
// EMPTY -> PROCESSING -> (WAITING ->) UNLOCKING -> SETTLED
When interacting with async sub-vehicles:
  • Sub-queries remain in PROCESSING until the underlying protocol is ready
  • Ephemeral accounting tracks expected outputs to prevent share price distortion
  • The Keeper system automates monitoring and advancing nested operations
  • Operators should monitor pending sectors for high balances indicating slow settlement

Design principles

  1. Separation of concerns — Each component has a single, well-defined responsibility
  2. Double-entry accounting — All asset movements are tracked through sector transfers
  3. Asynchronous by design — STEAM handles both sync and async operations gracefully
  4. Queue-based strategy — Flexible, operator-controlled allocation and redemption logic
  5. Accurate pricing — Ephemeral accounting ensures share price accuracy during in-flight operations
Trade-offs to consider:
  • Gas costs — More automation means higher gas costs. Queue-based strategies execute more transactions.
  • Complexity — More vehicles mean more monitoring and management overhead. Start simple and scale up.
  • Async operations — Sub-vehicle operations may not settle immediately. Design your flows with async handling in mind.