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

Where Clause

The where clause lists preconditions that must hold before a route runs. Each condition pairs with a throw that fires if the condition is false.

Syntax

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

Prefer named errors (throw ErrorName(args)) so EVM codegen emits typed custom errors. See Custom Errors.

Multiple conditions

Chain conditions with &&. Each has its own throw:

transfer(to: address, amount: U256)
    where m_balances[msg::sender] >= amount : throw InsufficientBalance(m_balances[msg::sender], amount)
    && to != msg::sender : throw SelfTransfer()
    && m_status == Status::Active : throw Paused()
=> []

Conditions evaluate in order. On failure the transaction reverts immediately; no later actions or member transforms run.

Condition expressions

Any boolean expression is valid: comparisons, equality, macro calls (@is_owner()), map lookups, and compounds:

where msg::value > 0 : throw ZeroValue()
where msg::sender == m_owner : throw Unauthorized()
where @is_owner() : throw Unauthorized()
where m_whitelist.exists(msg::sender) : throw NotWhitelisted()
where (m_deadline == 0 || sys::now < m_deadline) : throw Expired()

Where with from

Sender checks run before where:

process(data: bytes)
    from Oracle(m_oracle_id) : throw BadSender()
    where m_status == Status::Active : throw Paused()
    && data.len() > 0 : throw EmptyData()
=> []

Per-phase where

On phased routes, a later phase may attach its own guard that can read var captures from earlier phases:

withdraw(who: address) => [
    fetch: [
        var bal = balanceOf(who) ~> m_token;
    ]
    act where bal > 0 : throw EmptyBalance(): [
        // …
    ]
]

Route-level where runs before any phase and must not reference var bindings (V27). Per-phase where may only see vars from strictly earlier phases (V28). Prefer unphased routes unless you need a synchronous capture or interleaved effects.

Init routes

init setup(owner: address, limit: U256)
    where limit > 0 : throw BadLimit()
=> []