Return Values
The return action produces a value from a route. view and pure routes
must include one; it provides the mechanism for returning computation results to
callers.
Syntax
return(expression)
return(expr1, expr2) // multi-value, for `-> (T1, T2)`
The parentheses are required. The expression inside is evaluated and returned to the caller.
In View Routes
A view route should end with a return action:
view get_balance() -> U256 => [
return(m_balance)
]
view get_owner() -> address => [
return(m_owner)
]
In Pure Routes
Likewise for pure routes:
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 ordinary expression (arithmetic, function
calls, member reads). if, match, and { ... } blocks are not allowed
directly inside return(...); bind them with let first:
view get_status_label() -> String => [
let label = match m_status {
Status::Active => "active",
Status::Paused => "paused",
_ => "unknown"
};
return(label)
]
view get_effective_balance(account: address) -> U256 => [
let effective = {
let raw = m_balances[account];
let locked = m_locked[account];
raw - locked
};
return(effective)
]
Return with Let Bindings
Let bindings can compute intermediate values before the return:
view get_share(account: address) -> U256 => [
let balance = m_balances[account];
let total = m_total_supply;
let share = if total > 0 {
balance * 10000 / total
} else {
0
};
return(share)
]
Return Type Agreement
The type of the return expression must match the declared return type of the
route. A route that declares -> T but never returns a value is rejected, and
so is a value of an obviously different kind (a string for a number, say):
// Correct: returns U256 as declared
view total() -> U256 => [
return(m_supply)
]
// Rejected: return type mismatch
// view total() -> U256 => [
// return("not a number")
// ]
Integer widths are not yet diagnosed here, so make them agree yourself: to
return a U256 from a -> u8 route, narrow it with as (which reverts on
overflow) or declare the wider return type.
Multiple return values
Declare a tuple return type and pass several expressions to return:
view stats() -> (U256, bool) => [
return(m_total, m_total > 0)
]
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. A regular route that declares
-> T may still return(...); the returned expression sees member values
after the route’s transforms.
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 => [
let p = if token == m_token_a {
m_reserve_b * 1_000_000 / m_reserve_a
} else {
m_reserve_a * 1_000_000 / m_reserve_b
};
return(p)
]
view share_of(provider: address) -> U256 => [
let lp = m_lp_balances[provider];
let total_lp = m_total_lp;
let share = if total_lp > 0 {
lp * (m_reserve_a + m_reserve_b) / total_lp
} else {
0
};
return(share)
]
pure estimate_output(amount_in: U256, reserve_in: U256, reserve_out: U256) -> U256 => [
return(amount_in * reserve_out / (reserve_in + amount_in))
]
}
// set by the pool's mutating routes (omitted)
m_token_a: address {}
m_reserve_a: U256 {}
m_reserve_b: U256 {}
m_lp_balances: HashMap<address, U256> {}
m_total_lp: U256 {}
}