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

Return Values

The return action produces a value from a route. It is required in view and pure routes and provides the mechanism for returning computation results to callers.

Syntax

return(expression)

The parentheses are required. The expression inside is evaluated and returned to the caller.

In View Routes

Every view route must include a return action:

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

view get_owner() -> address => [
    return(m_owner)
]

In Pure Routes

Every pure route must include a return action:

pure add(a: u64, b: u64) -> u64 => [
    return(a + b)
]

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

Computed Returns

The return expression can be any expression, including blocks, conditionals, and function calls:

view get_status_label() -> String => [
    return(match m_status {
        Status::Active => "active",
        Status::Paused => "paused",
        _ => "unknown"
    })
]
view get_effective_balance(account: address) -> U256 => [
    return({
        let raw = m_balances.get(account).unwrap_or(0);
        let locked = m_locked.get(account).unwrap_or(0);
        raw - locked
    })
]

Return with Let Bindings

Let bindings can compute intermediate values before the return:

view get_share(account: address) -> U256 => [
    let balance = m_balances.get(account).unwrap_or(0);
    let total = m_total_supply;
    return(if total > 0 {
        balance * 10000 / total
    } else {
        0
    })
]

Return Type Agreement

The type of the return expression must match the declared return type of the route. The compiler enforces this:

// Correct: returns U256 as declared
view total() -> U256 => [
    return(m_supply)
]

// Error: return type mismatch
// view total() -> U256 => [
//     return("not a number")
// ]

Return in Regular Routes

Regular routes typically do not use return – their purpose is to cause side effects (state changes, message sends) rather than produce values. If a regular route does not need to return a value, the action list contains only sends, deploys, conditionals, and let bindings.

Complete Example

An entity exposing several computed views:

entity Pool {
    routes {
        view total_liquidity() -> U256 => [
            return(m_reserve_a + m_reserve_b)
        ]

        view price(token: address) -> U256 => [
            return(if token == m_token_a {
                m_reserve_b * 1_000_000 / m_reserve_a
            } else {
                m_reserve_a * 1_000_000 / m_reserve_b
            })
        ]

        view share_of(provider: address) -> U256 => [
            let lp = m_lp_balances.get(provider).unwrap_or(0);
            let total_lp = m_total_lp;
            return(if total_lp > 0 {
                lp * (m_reserve_a + m_reserve_b) / total_lp
            } else {
                0
            })
        ]

        pure estimate_output(amount_in: U256, reserve_in: U256, reserve_out: U256) -> U256 => [
            return(amount_in * reserve_out / (reserve_in + amount_in))
        ]
    }
}