Skip to main content
In Railnet smart contracts, an Allocation Strategy is implemented as a MultiVehicle. See Glossary for all terminology.
This guide walks you through creating an Allocation Strategy on Railnet. By the end, you will have a fully deployed ecosystem with its External Access Control, optional Fee Manager, and the Allocation Strategy itself (MultiVehicle).
If you are a Conduit owner deploying a strategy you will own and delegate to an asset manager, see Use a Strategy instead.

Prerequisites

  • A wallet with funds — the deposit asset (e.g. USDC) for the initial deposit and ETH for gas
  • The FACTORY_SPAWN role on the Multi-Vehicle factory (or access to a public factory)
  • The factory must not be deprecated
Every Allocation Strategy deployment requires an initial deposit. This is a security measure to prevent inflation attacks (zero-share vulnerability). The shares minted from this deposit are sent to the burn address and can never be withdrawn.
1

Deploy External Access Control (EAC)

Railnet uses an External Access Control contract to provide Role-Based Access Control (RBAC) across all strategies you operate. You define roles and grant them to different addresses from this single contract.You must deploy at least one EAC before creating any Allocation Strategy.Parameters:
  • initialDelay — delay for admin operations (in seconds), set to 0 for immediate access
  • initialDefaultAdmin — the address granted DEFAULT_ADMIN_ROLE
  • initialRoles — array of initial role attributions (can be empty and configured later)
  • deploymentSalt — salt for deterministic CREATE2 deployment
// Deploy External Access Control via the EAC Factory
ExternalAccessControlFactory.SpawnParams memory params = ExternalAccessControlFactory.SpawnParams({
    initialDelay: 0,
    initialDefaultAdmin: msg.sender,
    initialRoles: new ExternalAccessControlFactory.RoleAttribution[](0),
    deploymentSalt: keccak256("my-eac-v1")
});

ExternalAccessControl eac = eacFactory.spawn(params);
2

Deploy Fee Manager (optional)

The Fee Manager contract handles all fee-related operations for your Allocation Strategy: performance fees, management fees, deposit fees, and redemption fees. You can configure initial fee rates, maximum fee caps, and fee recipients.If you do not need fees, you can pass the zero address (0x0000...0000) when deploying the Allocation Strategy.Parameters:
  • accessControl — your EAC contract address
  • initialFees — fee rates in basis points (1 bps = 0.01%)
  • initialMaxFees — maximum fee caps that can never be exceeded
  • initialRecipients — fee recipients with their share in bps (must sum to 10,000)
  • deploymentSalt — salt for deterministic CREATE2 deployment
FeeManagerFactory.SpawnParams memory params = FeeManagerFactory.SpawnParams({
    accessControl: externalAccessControl,
    initialFees: FeeManager.Fees({
        performanceFeeBps: 1000,  // 10% performance fee
        managementFeeBps: 200,    // 2% annual management fee
        depositFeeBps: 0,         // No deposit fee
        redeemFeeBps: 0           // No redeem fee
    }),
    initialMaxFees: FeeManager.Fees({
        performanceFeeBps: 2000,  // 20% max performance fee
        managementFeeBps: 500,    // 5% max management fee
        depositFeeBps: 100,       // 1% max deposit fee
        redeemFeeBps: 100         // 1% max redeem fee
    }),
    initialRecipients: recipients,  // Array of FeeRecipient structs
    deploymentSalt: keccak256("my-fee-manager-v1")
});

FeeManager feeManager = feeManagerFactory.spawn(params);
Set initialMaxFees carefully. These caps are immutable and define the absolute ceiling for each fee type. You can always lower fees later, but you can never exceed the max.
3

Approve the initial deposit

When creating an Allocation Strategy, you select a single deposit asset (e.g. USDC). You must make an initial deposit (at least 1 unit of the asset) to protect against inflation attacks.Approve the Multi-Vehicle Factory to spend the required amount on the ERC-20 token contract.
// Approve the Multi-Vehicle Factory to spend USDC for the initial deposit
uint256 initialDepositAmount = 1e6; // 1 USDC (6 decimals)
IERC20(usdc).approve(address(multiVehicleFactory), initialDepositAmount);
4

Deploy the Allocation Strategy

Deploy the full Allocation Strategy ecosystem in a single transaction. The factory creates the MultiVehicle, Sector Accounting Engine, Queue Strategy Engine, Sub Query Engine, and Query Redeem Queue — all correctly linked and initialized.Parameters:
  • asset — the underlying deposit asset (e.g. USDC)
  • name — the ERC-20 token name for Allocation Strategy shares
  • symbol — the ERC-20 token symbol for Allocation Strategy shares
  • initialInterceptions — interceptor rules for reward distribution (can be empty)
  • accessControl — your EAC contract address
  • feeManager — Fee Manager address (or zero address for no fees)
  • modulesManager — Modules Manager address (or zero address)
  • salts — collection of deployment salts for all underlying contracts
  • initialDepositSize — amount of the initial deposit (in asset decimals)
  • initialExpectedSupply — minimum expected supply after initial deposit (generally 1e18)
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"),
        vehicleRegistry: keccak256("vr"),
        initialDepositQuery: keccak256("idq")
    }),
    initialDepositSize: 1e6,    // 1 USDC
    initialExpectedSupply: 1e18
});

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

// contracts.multiVehicle      — main Allocation Strategy contract
// contracts.accountingEngine   — Sector Accounting Engine
// contracts.strategyEngine     — Queue Strategy Engine
// contracts.subQueryEngine     — Sub Query Engine
// contracts.redeemQueue        — Query Redeem Queue
5

Verify the deployment

After deployment, verify your Allocation Strategy’s status and configuration by querying the Railnet subgraph or reading the contract state directly.
// Read the deployed MultiVehicle state
address multiVehicle = address(contracts.multiVehicle);

// Verify the asset
address asset = MultiVehicle(multiVehicle).asset();

// Verify the total supply (should reflect initial deposit)
uint256 totalSupply = MultiVehicle(multiVehicle).totalSupply();

// Verify the accounting engine link
ISectorAccountingEngine accounting = MultiVehicle(multiVehicle).accountingEngine();
You can also query the Railnet subgraph using GraphQL:
query VerifyDeployment($address: String!) {
  Vehicle(where: { address: { _ilike: $address } }) {
    address
    id
    name
    vehicleType
    symbol
    supply
  }
}

What you deployed

Your Allocation Strategy ecosystem now consists of five interconnected contracts:
ContractPurpose
MultiVehicleMain Allocation Strategy contract. Users deposit and receive ERC-20 shares.
Sector Accounting EngineTracks all asset allocations across yield sources and idle sectors.
Queue Strategy EngineDefines deposit/redeem priority queues for automated allocation.
Sub Query EngineExecutes deposit and redeem queries on yield sources.
Query Redeem QueueHandles asynchronous redemption processing.

Next steps

Operate an Allocation Strategy

Authorize yield sources, configure allocation queues, and operate your Allocation Strategy.

Configure fees

Set up fee structures for your Allocation Strategy.