# Create an Allocation Strategy \[Deploy a MultiVehicle, its access control and fee manager, then authorize yield sources]

:::info
In Railnet smart contracts, an Allocation Strategy is implemented as a **MultiVehicle**.
:::

This guide covers every MultiVehicle deployment, whether you own the strategy as a platform or deploy it as an asset manager.

You need the deposit asset and ETH for gas, the `FACTORY_SPAWN` role on the MultiVehicle factory, and the deposit asset registered in the [AssetRegistry](/developers/contracts/asset-registry). The factory pulls an initial deposit at spawn time using the amount configured there, and burns the shares it mints so the strategy cannot be inflation-attacked. Railnet runs `spawn` today, so send us the parameters below.

:::steps
### Deploy External Access Control

One EAC contract holds the roles for the strategy and everything attached to it. Use a multisig as `initialDefaultAdmin`, and a non-zero `initialDelay` if you want admin changes to be visible before they take effect.

```solidity [Solidity]
AccessControlFactory.SpawnParams memory params = AccessControlFactory.SpawnParams({
    initialDelay: 0,
    initialDefaultAdmin: msg.sender,
    initialRoles: new IExternalAccessControl.RoleAttribution[](0),
    deploymentSalt: keccak256("my-eac-v1")
});

ExternalAccessControl eac = eacFactory.spawn(params);
```

### Deploy a Fee Manager

The Fee Manager holds performance, management, deposit and redeem fees for the strategy itself, separate from the Fee Manager on any Conduit above it. `initialMaxFees` is immutable: you can always lower a rate, never exceed its cap. Deploy one even at zero rates, because passing the zero address locks you out of fees forever.

```solidity [Solidity]
FeeManagerFactory.SpawnParams memory params = FeeManagerFactory.SpawnParams({
    accessControl: externalAccessControl,
    initialFees: FeeManager.Fees({
        performanceFeeBps: 1000,  // 10%
        managementFeeBps: 200,    // 2% annual
        depositFeeBps: 0,
        redeemFeeBps: 0
    }),
    initialMaxFees: FeeManager.Fees({
        performanceFeeBps: 2000,
        managementFeeBps: 500,
        depositFeeBps: 100,
        redeemFeeBps: 100
    }),
    initialRecipients: recipients,  // shares in bps, must sum to 10,000
    deploymentSalt: keccak256("my-fee-manager-v1")
});

FeeManager feeManager = feeManagerFactory.spawn(params);
```

See [Fee Manager](/developers/contracts/fee-manager) for the formulas and the recipient API.

### Approve the initial deposit

```solidity [Solidity]
uint256 initialDepositAmount = assetRegistry.getInitialDepositAmount(usdc);
IERC20(usdc).approve(address(multiVehicleFactory), initialDepositAmount);
```

### Spawn the MultiVehicle

One call deploys the MultiVehicle, Vehicle Manager, Sector Accounting Engine, Queue Strategy Engine, Sub Query Engine and Query Redeem Queue, wired and initialized. The initial deposit amount is read from the AssetRegistry, not passed here.

```solidity [Solidity]
MultiVehicleFactory.SpawnParams memory params = MultiVehicleFactory.SpawnParams({
    asset: IERC20(usdc),
    name: "Diversified USDC",
    symbol: "dUSDC",
    initialInterceptions: new Interceptor.Interception[](0),
    accessControl: externalAccessControl,
    feeManager: feeManager,
    modulesManager: modulesManager,
    salts: MultiVehicleFactory.Salts({
        multiVehicle: keccak256("mv"),
        queryRedeemQueue: keccak256("qrq"),
        queueStrategyEngine: keccak256("qse"),
        sectorAccountingEngine: keccak256("sae"),
        subQueryEngine: keccak256("sqe"),
        vehicleManager: keccak256("vm"),
        initialDepositQuery: keccak256("idq")
    }),
    forbiddenAddresses: new address[](0),
    queryRegistry: queryRegistry
});

MultiVehicleFactory.Contracts memory contracts = factory.spawn(params);
```

### Authorize yield sources

A MultiVehicle can only send assets to sources you have explicitly authorized. This is the guardrail that matters most, and it stays with the owner — never grant `MULTI_VEHICLE_SET_VEHICLE_AUTHORIZATION` to an asset manager.

The Vehicle Manager checks that each source uses the strategy's base asset, is a contract, and reports `ready()`. Use `authorizeAndConfigure` to set a mode and cap in the same transaction, `configure` to change them later, and `unauthorize` to remove a source once you have redeemed everything out of it.

```solidity [Solidity]
IVehicleManager manager = MultiVehicle(contracts.multiVehicle).manager();

eac.grantScopedRole(
    keccak256("MULTI_VEHICLE_SET_VEHICLE_AUTHORIZATION"),
    address(manager),
    platformAdmin
);

manager.authorize(IVehicle(aaveVehicle));

manager.authorizeAndConfigure(
    IVehicle(morphoVehicle),
    VehicleManagerStore.VehicleConfig({
        mode: VehicleMode.Automatic,
        cap: Target({value: 250_000e6, threshold: 0})
    })
);
```

Pick sources from the [catalog](/yield-sources); addresses are on [Deployed contracts](/developers/contracts/deployments). You can add or remove sources at any time without redeploying.
:::

## What you deployed

| Contract | Purpose |
|---|---|
| **External Access Control** | Roles for the whole set, with you as admin |
| **Fee Manager** | Fee rates, immutable caps, recipient splits |
| **MultiVehicle** | Share token and depositor entry points |
| **Vehicle Manager** | The authorized source list, caps, redeem queue operations |
| **Sector Accounting Engine** | Balances per sector, `move` and `dispatch` |
| **Queue Strategy Engine** | Deposit and redeem priority queues |
| **Sub Query Engine** | Sub-queries on each yield source |
| **Query Redeem Queue** | Asynchronous redemption matching |

Check the deployment with the [Railnet API](/developers/api):

```graphql [GraphQL]
query VerifyDeployment($address: String!) {
  Vehicle(where: { address: { _ilike: $address } }) {
    address
    name
    symbol
    vehicleType
    supply
  }
}
```

## Next steps

<Cards>
  <Card title="Operate an Allocation Strategy" description="Configure queues, move and dispatch capital, rebalance." icon="sliders" to="/strategies/allocation/operate" />

  <Card title="Guardrails and mandates" description="Delegate operations to an asset manager inside enforced boundaries." icon="shield" to="/strategies/allocation/guardrails" />

  <Card title="Quick start" description="Deploy the Conduit that wraps this strategy." icon="rocket" to="/conduits/quick-start" />
</Cards>
