In user-facing documentation, a Vehicle is referred to as a Yield Source. See Glossary.
The core distinction
The difference between sync and async Vehicles lies in the Query lifecycle.Synchronous Vehicles
Sync Vehicles complete their primary operation within a single transaction. A Query transitions directly from EMPTY to UNLOCKING viacreate() and then to SETTLED via unlock(). There is no waiting period or external dependency.
- Aave V3 Vehicle — Supplies and withdraws assets from Aave V3 lending pools
- Morpho Blue Vehicle — Supplies to and withdraws from a Morpho Blue market
- ERC-4626 Vehicle — Wraps any standard ERC-4626 vault into a STEAM-compliant interface
- Wrapper Vehicle — 1:1 wrap of any ERC-20 for STEAM compatibility (utility, no yield)
Asynchronous Vehicles
Async Vehicles handle operations that cannot complete immediately due to protocol-level constraints. A Query enters PROCESSING after creation and remains there until external conditions are met.- ERC-7540 Vehicle — Wraps any ERC-7540 async vault, driving its request queues through the STEAM lifecycle
- Lagoon Vehicle — An
ERC7540Vehiclesubclass for Lagoon’s hybrid vaults. It picks the sync or async path per call and adds the closed-vault recovery leg. - Ethena Vehicle — Handles sUSDe cooldown periods when active. Operates synchronously when cooldown is disabled.
Why some operations must be async
Asynchronicity is rarely a choice. It is a requirement imposed by the underlying protocol’s design.Protocol cooldowns (Ethena)
Protocol cooldowns (Ethena)
Ethena’s sUSDe protocol implements a
cooldownDuration. When you want to unstake USDe, you must first initiate a cooldown. The assets are only available for withdrawal after this period elapses.The Ethena Vehicle tracks this period, keeping the Query in PROCESSING until the cooldown ends.When Ethena’s
cooldownDuration is set to zero, the Ethena Vehicle operates synchronously — no PROCESSING state, no Account Clone needed.Request queues (ERC-7540 and Lagoon)
Request queues (ERC-7540 and Lagoon)
An ERC-7540 vault does not settle a deposit or redemption on request.
requestDeposit and requestRedeem only register a request; a curator settles it later, in batches, and only then can the result be claimed.The ERC-7540 Vehicle keeps its own demand queue, registering one demand per Query and batching them into a single vault request under the Vehicle’s own address. Each Query holds a demand ID, and state() reports UNLOCKING once that demand becomes claimable.Lagoon vaults are hybrid. The Lagoon Vehicle reads syncMode() and isTotalAssetsValid() on every call and takes the synchronous syncDeposit or syncRedeem path when both allow it, falling back to the async request path when they do not — or when the vault’s runtime gates reject the sync attempt.Multi-step strategies
Multi-step strategies
Complex yield strategies might involve multiple swaps, bridge operations, or liquidity provisioning steps that cannot safely be compressed into a single atomic transaction.
The PROCESSING state
The PROCESSING state is the hallmark of an asynchronous operation.- In sync Vehicles,
create()moves the Query directly to UNLOCKING because assets are immediately deposited and ready to claim - In async Vehicles,
create()moves the Query to PROCESSING, signaling that the operation is underway but not yet ready for settlement
state() view function, which checks the underlying protocol’s status. If conditions are met (e.g., block.timestamp >= cooldownEnd), state() reports UNLOCKING. A Keeper or caller then calls unlock() to finalize, and the Query Registry commits the pending leg at that point — see State resolution and the storedState lag.
If an external condition must be met before processing can continue, the Query may enter PAUSED. Once the condition is satisfied, resume() moves it back to PROCESSING.
Error handling: sync vs async
How errors surface depends on the Vehicle type:- Sync Vehicles — if
create()fails, the entire transaction reverts. No query is created, no assets are transferred. There is nothing to recover. - Async Vehicles — if the underlying protocol operation fails after entering PROCESSING, the Query transitions to RECOVERING. The owner calls
recover()to reclaim input assets, and the Query terminates in REJECTED.
Account Clones: isolating async operations
Some protocols restrict operations to the address that initiated them. Ethena’scooldownShares is address-specific: a new cooldown started from the same address overrides the previous one, so concurrent redemptions driven from a single Vehicle address would clobber each other.
Railnet solves this with the Account Clone pattern, built on the minimal Account contract:
1
Deploy clone
The Vehicle clones
Account through the CoreFactory, using the query ID as the salt, and calls initialize(owner) with itself as owner.2
Transfer assets
The position (for Ethena, the sUSDe being cooled down) is transferred to that Account, and the Vehicle’s accounting is decreased accordingly.
3
Initiate protocol interaction
The Vehicle drives the protocol through
performCall(target, value, data), which only the owner may call — for Ethena, cooldownShares on entry and unstake at settlement.4
Track in query
The Vehicle records the Account’s address in its own per-query storage. The Query Registry record holds no such field.
Account Clones are one tool among several, used where a protocol binds operations to an address. Today only the Ethena Vehicle needs them, on its async redeem leg. The ERC-7540 and Lagoon Vehicles instead batch per-Query demands through their own request queue under the Vehicle’s own address.
Impact on callers
When interacting with async Vehicles, you follow a multi-step process:1
Create the query
Call
create(). The Query enters the PROCESSING state. Assets are transferred to the Vehicle (or its Account Clone).2
Monitor readiness
Poll
state(query) to check the current state. The Vehicle evaluates underlying protocol conditions on each call.3
Finalize the operation
- On success (state is UNLOCKING): call
unlock()to claim output assets. The Query transitions to SETTLED. - On failure (state is RECOVERING): call
recover()to reclaim input assets. The Query transitions to REJECTED.
Multi-Vehicle handling of async sub-vehicles
When a Multi-Vehicle dispatches operations to async sub-vehicles, the SubQueryEngine manages the nested STEAM lifecycle. If a sub-vehicle enters PROCESSING, the Multi-Vehicle’s own Query may remain open until settlement completes. Ephemeral accounting tracks expected outputs during in-flight operations to prevent share price distortion. See Accounting and flow of funds for how this works. The Keeper system automates monitoring and advancing nested sub-queries. See Multi-Vehicle architecture for the full operational picture.Choosing between sync and async
When integrating a new protocol into Railnet, the choice is dictated by the protocol’s deposit and withdrawal mechanics:Async is not a limitation — it is what allows Railnet to provide institutional-grade access to the full spectrum of DeFi yield sources, regardless of their underlying complexity.