This page covers the smart contract implementation details. See Glossary.
shares = assets * totalSupply / totalAssets), which stays 1:1 in value with the underlying token as long as no fees are configured. Shares always carry 18 decimals, so the raw share amount equals the deposited token amount only when the wrapped token is also an 18-decimal token.
How it works
WrapperVehicle is always synchronous. Deposits and withdrawals complete in a single transaction with no cooldown periods or withdrawal queues:create transitions straight to UNLOCKING, and both resume() and recover() revert Unimplemented because a query can never park in PROCESSING.
The contract holds the underlying ERC20 token and issues STEAM-compatible shares against it. asset() returns the wrapped token, and totalAssets() is tracked internally — incremented on deposits, decremented on redeems — rather than read from an external protocol. Because there is no yield source, the share price stays at 1:1 unless a FeeManager is configured: management and performance fees mint fee shares, diluting holders below 1:1.
Use cases
- Access restrictions — bar specific addresses from owning or receiving queries via the immutable
forbiddenAddresseslist fixed at deployment, and gate the Vehicle’s admin surface through anExternalAccessControl. Allow-lists, block-lists, sanctions screening, and share-transfer screening are Conduit-level features — wrap the Vehicle in a Conduit with an AccountList for those. - Fee application — apply deposit, redeem, management, or performance fees to any ERC20 token via a FeeManager
- Integration testing — use WrapperVehicle as a predictable, zero-yield sub-vehicle when testing MultiVehicle or Conduit configurations
- STEAM compatibility — make any ERC20 token composable with Railnet infrastructure (MultiVehicles, Conduits) without building a custom Vehicle adapter
Deployment
WrapperVehicle instances are deployed viaWrapperVehicleFactory.spawn(SpawnParams), which requires the FACTORY_SPAWN role. The factory clones a pre-deployed implementation at a deterministic address, pulls the AssetRegistry-configured initial deposit from the caller, settles it synchronously, then burns the resulting shares as an inflation-attack guard before calling enable() and recording the deployment.
SpawnParams carries the wrapped asset, the optional accessControl, feeManager, and modulesManager modules (each validated against its trusted factory), forbiddenAddresses, the queryRegistry, and the querySalt and deploymentSalt salts.
Composability
Because WrapperVehicle implements the full STEAM interface, it can be:- Registered as a sub-vehicle in a MultiVehicle
- Wrapped by a Conduit for distribution with custom fees and branding
- Combined with the vehicle-level modules: a
FeeManagerfor deposit, redeem, management, and performance fees, aModulesManagerfor delegatecall modules, and anExternalAccessControlfor role gating