Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Init Routes

Init routes run once when an entity instance is created. They supply the arguments that member transforms use for initial state. An entity may have at most one init route.

Syntax

Init routes are declared with the init keyword:

#[factory_only]
init setup(owner: address, name: String) => [
    // initialization actions (optional)
]

A route literally named constructor (without the init keyword) is also treated as the init route.

On EVM, entities are always deployed via CREATE2 through the generated CambrianFactory, so the init route carries the #[factory_only] attribute: the generated initialize() accepts only calls from the factory. Leaving it out is an error in EVM project builds and a warning in single-file EVM builds.

Purpose

The init route is invoked exactly once at instance creation. Its primary role is to provide initial values for members through their transforms:

entity Token {
    routes {
        #[factory_only]
        init setup(
            name: String,
            symbol: String,
            decimals: u8,
            owner: address
        ) => []
    }

    m_name: String {
        in setup(name, _, _, _) => name
    }

    m_symbol: String {
        in setup(_, symbol, _, _) => symbol
    }

    m_decimals: u8 {
        in setup(_, _, decimals, _) => decimals
    }

    m_owner: address {
        in setup(_, _, _, owner) => owner
    }

    m_total_supply: U256 {
        in setup(_, _, _, _) => 0
    }
}

Parameter Passing

Init route parameters are passed at deployment time. The deploying entity (or off-chain client) provides these values as part of the deployment transaction — identity values first, then the init arguments:

// In another entity's route body, deploying the Token above:
deploy Token("MyToken", "MTK", 18, msg::sender)

Do not read msg::sender inside the init route itself: on EVM the caller of initialize() is the factory, not the account that requested the deployment. Pass the owner (or mint recipient) as an explicit parameter, as owner is above. Reading msg::sender there is diagnosed like a missing #[factory_only]: an error in EVM project builds, a warning in single-file EVM builds.

Init Actions

While the init route’s action list is often empty ([]), it can contain actions that should execute at deployment:

#[factory_only]
init setup(owner: address, treasury: address) => [
    emit Initialized(owner, treasury);
]

Member Initialization

Every member that needs an initial value must include a transform referencing the init route. Members without an init transform start at their type’s default value (typically zero or empty).

The parameter pattern in a member transform for an init route uses positional matching with _ for unused parameters:

m_owner: address {
    in setup(_, _, _, owner) => owner
}

m_paused: bool {
    in setup(_, _, _, _) => false
}

Complete Example

A vault entity with an init route:

entity Vault {
    const MIN_DEPOSIT: U256 = 100

    routes {
        #[factory_only]
        init create(
            owner: address,
            guardian: address,
            daily_limit: U256
        ) => []

        deposit()
            where msg::value >= MIN_DEPOSIT : throw 100
        => []

        withdraw(amount: U256)
            where msg::sender == m_owner : throw 101
            && m_balance >= amount : throw 102
        => [
            ~> msg::sender with { value: amount }
        ]
    }

    m_owner: address {
        in create(owner, _, _) => owner
    }

    m_guardian: address {
        in create(_, guardian, _) => guardian
    }

    m_daily_limit: U256 {
        in create(_, _, daily_limit) => daily_limit
    }

    m_balance: U256 {
        in create(_, _, _) => 0
        in deposit() => m_balance + msg::value
        in withdraw(amount) => m_balance - amount
    }
}

Constraints

  • An entity can have at most one init route.
  • Init routes cannot be called after deployment — they execute exactly once.
  • Init routes can include where clauses to validate constructor arguments.
  • On EVM, construction is split into a factory-guarded initialize(); see Deterministic Addresses.