Skip to main content
This page covers the smart contract implementation details. See Glossary.
WrapperVehicle wraps an existing ERC20 token into a STEAM-compatible Vehicle without adding yield logic. Deposits mint shares and redeems burn them at an ERC-4626-style rate (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 forbiddenAddresses list fixed at deployment, and gate the Vehicle’s admin surface through an ExternalAccessControl. 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 via WrapperVehicleFactory.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 FeeManager for deposit, redeem, management, and performance fees, a ModulesManager for delegatecall modules, and an ExternalAccessControl for role gating