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

Regular Routes

Regular routes are the default route kind. They can read and modify entity state, send messages, deploy entities, and run other route actions. Most routes in a typical Cambrian entity are regular routes.

Syntax

A regular route has no keyword modifier:

routes {
    deposit(amount: U256) => [
        // actions
    ]
}

Parameters

Route parameters are typed and positional:

transfer(to: address, amount: U256) => [
    // to and amount are available here
]

Parameters are available in the action list and are referenced by name in member transforms. A route with no parameters uses empty parentheses:

increment() => []

State Access

Regular routes have full access to entity state through members. State changes are expressed in member transforms, not in the route body itself:

entity Counter {
    routes {
        add(value: u64) => []
    }

    m_total: u64 {
        in add(value) => m_total + value
    }
}

The route body contains actions (sends, deploys, conditionals); state mutation is handled by the member system.

Actions

The action list can contain any combination of sends, deploys, conditionals, let bindings, emits, and evm:: intrinsics:

routes {
    purchase(item_id: u64)
        where msg::value >= m_prices[item_id] : throw 100
    => [
        let price = m_prices[item_id];
        let change = msg::value - price;
        if change > 0 => [
            ~> msg::sender with { value: change }
        ],
        Sold(item_id, msg::sender) ~> m_ledger
    ]
}

With Preconditions

Regular routes commonly use where clauses to enforce invariants:

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

If any where condition is false, the transaction reverts with the specified error code, and no state changes or actions take effect.

With Sender Verification

The from clause restricts which entity or caller may invoke the route:

credit(account: address, amount: U256)
    from Shop(_)
=> []

See From Clause for details.

Complete Example

A token transfer route combining parameters, preconditions, actions, and member transforms:

entity Token {
    routes {
        transfer(to: address, amount: U256)
            where m_balances[msg::sender] >= amount : throw 100
            && to != msg::sender : throw 101
        => []
    }

    m_balances: HashMap<address, U256> {
        in transfer(to, amount) => {
            let from = msg::sender;
            let from_bal = m_balances[from];
            let to_bal = m_balances.get(to).unwrap_or(0);
            m_balances
                .set(from, from_bal - amount)
                .set(to, to_bal + amount)
        }
    }
}

The route body is [] (empty) because the state change is entirely expressed in the member transform. This is a common and idiomatic pattern.