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

Routes

Routes are the named entry points of an entity — the primary interface callers use to interact with it. Invoking a route runs its preconditions, member transforms, and action list. How a host dispatches to a route (EVM call, test harness, …) is target-specific; the .cam surface stays the same.

Routes block

entity Wallet {
    routes {
        init setup(owner: address) => []

        deposit()
            where msg::value > 0 : throw ZeroDeposit()
        => []

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

        view get_balance() -> U256 => [
            return(m_balance)
        ]

        pure compute_fee(amount: U256, rate: u64) -> U256 => [
            return(amount * (rate as U256) / 10000)
        ]

        accept receive() => []
    }
}

Route kinds

KindKeywordStateSide effectsUse
Regular(none)Read + writeYesMutations
ViewviewRead onlyNoQueries
PurepureNoneNoStateless computation
Init / constructorinit (or constructor-style)WriteYesOne-time setup
PrivateprivateRead + writeYesIn-entity only; use with call
Receiveaccept receive()Read + writeYesPlain ETH receiver
Fallbackfallback()Read + writeYesUnknown selector

Details:

Private routes

A private route is part of the entity’s logic but not an external entry point. Other routes invoke it with the call action:

entity Service {
    routes {
        run() => [
            call finalize_step()
        ]

        private finalize_step() => []
    }

    m_done: bool {
        in finalize_step() => true
    }
}

See Call (Private Routes) for restrictions and per-target lowering.

Anatomy

[modifier] name(parameters) [from clause] [where clause] [-> ReturnType] => [actions]
PartRequiredDescription
ModifierNoview, pure, init, private, or accept on receive
NameYesRoute identifier (receive / fallback are reserved on EVM)
ParametersYesTyped list (empty for receive / fallback)
From clauseNoSender verification — From Clause
Where clauseNoPreconditions — Where Clause
Return typeNo-> T when returning a value (V42 if return(expr) lacks it)
ActionsYes=> [ … ] (may be empty when only transforms apply)

Clauses

From

release()
    from Buyer(m_buyer_id) : throw Unauthorized()
=> []

Where

withdraw(amount: U256)
    where m_balance >= amount : throw InsufficientBalance(m_balance, amount)
=> []

Prefer named errors — Custom Errors.

Actions

Sends, deploys, emits, conditionals, returns, and local bindings:

transfer(to: address, amount: U256) => [
    let fee = compute_fee(amount);
    Transfer(amount - fee) ~> to,
    Transfer(fee) ~> m_treasury
]

See Route Actions.

Members

Members name the routes that update them:

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

Empty action lists

routes {
    increment() => []
}

m_count: u64 {
    in increment() => m_count + 1
}

The [] is still required syntactically.