# Quick start \[Deploy your first Conduit in minutes]

A Conduit wraps one yield source with your own ERC20 share token, fee structure and access control. Deploy it through the ConduitFactory. Every step is identical if you point the Conduit at a MultiVehicle instead.

:::warning
Railnet runs factory `spawn` today: `CONDUIT_SPAWN` and `FACTORY_SPAWN` are gated roles. Send us the parameters below and we deploy your Conduit. To integrate now, use the [test Conduit](/developers/integrate-conduit#test-conduit) on Base.
:::

## Before you begin

| Prerequisite | Required | How to get it |
|---|---|---|
| **Yield source Vehicle** | Yes | [Pick a source from the catalog](/yield-sources). Composing several? [Deploy a MultiVehicle](/strategies/allocation/create) |
| **External Access Control (EAC)** | Yes | [Deploy an EAC](/developers/contracts/access-control), your central permission contract |
| **Fee Manager** | No | [Deploy a Fee Manager](/conduits/configure-fees), or pass `address(0)` for no fees |
| **AccountList** | No | [Set up compliance](/conduits/compliance), or pass `address(0)` for permissionless access |

Three spawn parameters decide how the product behaves:

| Parameter | What it decides |
|---|---|
| `feeManager` | Management, performance, deposit and redeem fees. `address(0)` for none. See [Configure fees](/conduits/configure-fees). |
| `accountList` | Who can deposit, hold and transfer shares. `address(0)` for permissionless. See [Compliance](/conduits/compliance). |
| `transferEnabled` | `false` makes the token mint-and-burn only. Flip it on later with `enableTransfers()`; the latch is one-way. See [Transfer policy](/conduits/compliance#transfer-policy). |

## Deploy the Conduit

:::steps
### Get the ConduitFactory address

Factory addresses per network are in [Deployed contracts](/developers/contracts/deployments). `spawn` is gated on `CONDUIT_SPAWN`, held in the factory's own access control, not the EAC you pass in `params`.

```solidity [Solidity]
ConduitFactory factory = ConduitFactory(CONDUIT_FACTORY_ADDRESS);
```

### Configure spawn parameters

The `vehicle` parameter accepts any STEAM-compliant contract: a Vehicle, or a MultiVehicle composing several. The deposit asset is that Vehicle's `asset()` and the seed amount comes from the [AssetRegistry](/developers/contracts/asset-registry), so neither is passed here.

```solidity [Solidity]
ConduitFactory.SpawnParams memory params = ConduitFactory.SpawnParams({
    name: "Platform USDC Yield",                    // Your token name
    symbol: "pUSDCy",                               // Your token symbol
    vehicle: IVehicle(AAVE_V3_VEHICLE_ADDRESS),     // Vehicle or MultiVehicle
    feeManager: IFeeManager(feeManagerAddress),     // address(0) for no fees
    accountList: IAccountList(accountListAddress),  // address(0) for permissionless
    ownerRegistry: IOwnerRegistry(address(0)),      // address(0) for no wrapped-query NFTs
    accessControl: accessControl,                   // Your EAC contract
    transferEnabled: false,                         // One-way latch, flip with enableTransfers()
    initialInterceptions: new Interceptor.Interception[](0),
    initialExpectedSupply: 0.8e18,                  // cShares have 18 decimals; lower bound for a 1 USDC seed
    querySalt: bytes32(0),
    deploymentSalt: keccak256("platform-conduit-v1")
});
```

### Approve and spawn

Read the seed amount from the AssetRegistry, approve the factory, then spawn; the deployment salt travels inside `params`. The factory is the `msg.sender` of the seed deposit, so allow-list it first if your AccountList is in `REGULAR` or `STRICT` mode.

```solidity [Solidity]
uint256 initialDeposit = assetRegistry.getInitialDepositAmount(USDC_ADDRESS);
IERC20(USDC_ADDRESS).approve(address(factory), initialDeposit);

// Requires CONDUIT_SPAWN
IConduit conduit = factory.spawn(params);
```

### Finalize (async yield sources only)

On a sync source the Conduit is enabled inside `spawn`. On an async source the seed deposit settles later, so wait for it and finalize: that burns the seed shares, checks `totalSupply() >= initialExpectedSupply`, and enables the Conduit.

```solidity [Solidity]
// Reverts NoPendingDeposit if there is nothing pending
factory.finalizeConduitDeposit(conduit);
```
:::

## Verify deployment

```solidity [Solidity]
require(conduit.ready(), "Conduit not enabled");
require(address(conduit.getVehicle()) == AAVE_V3_VEHICLE_ADDRESS, "Wrong vehicle");
require(conduit.asset() == USDC_ADDRESS, "Wrong asset");
```

## Next steps

<Cards>
  <Card title="Integrate a Conduit" description="Deposits, withdrawals and balances." icon="code" to="/developers/integrate-conduit" />

  <Card title="Compliance & access control" description="Allow-lists, transfer policy and the roles you need." icon="lock" to="/conduits/compliance" />

  <Card title="Configure fees" description="Fee structure and recipient splits." icon="percent" to="/conduits/configure-fees" />
</Cards>
