Skip to main content
A Conduit wraps an existing Vehicle and issues its own ERC20 shares. This lets multiple Multi-Vehicles access the same yield source while the Conduit manages position aggregation, deposits, and redeems through the STEAM lifecycle.
Platforms also deploy Conduits as distribution channels for existing strategies. See Deploy a Conduit as a platform for the platform-focused guide.

When to use a Conduit

Use a Conduit when:
  • Multiple Multi-Vehicles need access to the same underlying yield source
  • You want a single shared position instead of separate per-Multi-Vehicle positions
  • You need ERC20 transferable shares representing a pro-rata claim on the underlying Vehicle
If only one Multi-Vehicle will ever use a yield source, a regular Vehicle is simpler.

Prerequisites

  • A deployed STEAM Vehicle (e.g., an ERC4626Vehicle)
  • A deployed CoreFactory and FreezablePausableBeacon for the Conduit implementation
  • The deposit asset authorized in the AssetRegistry — the factory reads the initial deposit size from there at spawn time
  • Familiarity with the STEAM standard

Deploy a Conduit

1

Deploy the ConduitFactory

The ConduitFactory is responsible for spawning new Conduit instances.
ConduitFactory factory = new ConduitFactory(
    coreFactory,
    conduitBeacon,
    accessControl
);
2

Configure spawn parameters

Define the Conduit’s configuration including the underlying Vehicle and transfer mode. The initial deposit size is read from the AssetRegistry — it is not passed here.
ConduitFactory.SpawnParams memory params = ConduitFactory.SpawnParams({
    name: "My Conduit",
    symbol: "mCON",
    vehicle: IVehicle(VEHICLE_ADDRESS),
    feeManager: IFeeManager(address(0)),       // No fees for now
    accountList: IAccountList(address(0)),       // No access control
    ownerRegistry: IOwnerRegistry(address(0)),   // No external registry
    accessControl: accessControl,
    transferMode: ConduitStructs.TransferMode.ALLOW_TRANSFER,
    initialExpectedSupply: 1e18,
    depositAsset: IERC20(underlyingAsset),
    querySalt: bytes32(0),
    deploymentSalt: keccak256("my-conduit-salt")
});
3

Spawn the Conduit

Look up the initial deposit amount in the AssetRegistry, approve the factory for that amount, then spawn.
// Read the configured initial deposit from the AssetRegistry
uint256 initialDeposit = assetRegistry.getInitialDepositAmount(underlyingAsset);

// Approve the factory to spend it
IERC20(underlyingAsset).approve(address(factory), initialDeposit);

// Spawn the Conduit — factory pulls the initial deposit and burns the minted shares
Conduit conduit = Conduit(
    address(factory.spawn(params, keccak256("deployment-salt")))
);
The initial deposit protects against inflation attacks by bootstrapping the share supply. The initial shares are burned automatically. The registry also dampens cumulative rounding losses from nested vault accounting — see Asset registry for sizing guidance.

Make a deposit

After deployment, deposit into the Conduit. The Conduit handles pulling assets and creating the STEAM query in the underlying Vehicle.
// Approve the Conduit to spend your tokens
IERC20(underlyingAsset).approve(address(conduit), 100e18);

// Define the deposit query
Query memory depositQuery = Query({
    owner: address(conduit),
    receiver: address(conduit),
    mode: Mode.DEPOSIT,
    input: new Asset[](1),
    output: new Asset[](0),
    salt: bytes32(uint256(1)),
    data: ""
});
depositQuery.input[0] = Asset({
    asset: address(underlyingAsset),
    value: 100e18
});

// Create and auto-process the deposit
conduit.create(depositQuery, msg.sender);
After the deposit settles, check your shares:
uint256 shares = conduit.balanceOf(msg.sender);
uint256 assets = conduit.totalAssets();

Redeem from a Conduit

Provide Conduit shares as input, and the Conduit handles the interaction with the underlying Vehicle.
// Approve the Conduit to burn your shares
conduit.approve(address(conduit), shares);

// Define the redeem query
Query memory redeemQuery = Query({
    owner: address(conduit),
    receiver: address(conduit),
    mode: Mode.REDEEM,
    input: new Asset[](1),
    output: new Asset[](0),
    salt: bytes32(uint256(2)),
    data: ""
});
redeemQuery.input[0] = Asset({
    asset: address(conduit),
    value: shares
});

// Create and auto-process the redeem
conduit.create(redeemQuery, msg.sender);

Next steps

Configure fees

Add fee structures to your Conduit.

Learn about Conduits

Understand Conduit architecture in depth.