Conditional Actions
Conditional actions allow a route to execute different sets of actions based on
runtime conditions. They use an if/else syntax within the action list.
Syntax
if condition => [
// actions when true
] else [
// actions when false
]
The else branch is optional:
if condition => [
// actions when true
]
Basic Usage
Execute an action only when a condition is met:
routes {
forward() => [
if msg::value > 0 => [
~> m_recipient with { value: msg::value }
]
]
}
If/Else
Choose between two action sequences:
routes {
forward() => [
if msg::value >= m_threshold => [
emit LargeTransfer(msg::sender, msg::value);
~> m_cold_wallet with { value: msg::value }
] else [
~> m_hot_wallet with { value: msg::value }
]
]
}
Conditions
The condition can be any boolean expression:
Comparisons
if m_balance >= amount => [
~> recipient with { value: amount }
]
Macro Calls
if @is_owner() => [
~> m_treasury with { value: m_balance }
]
Member State
if m_status == Status::Active => [
process(data) ~> m_processor
] else [
enqueue(data) ~> m_queue
]
Compound Conditions
if amount > 0 && m_balance >= amount => [
~> msg::sender with { value: amount }
]
Nested Conditionals
Conditional actions can be nested for multi-branch logic:
routes {
categorize(score: u64) => [
if score >= 90 => [
award("gold") ~> m_rewards
] else [
if score >= 70 => [
award("silver") ~> m_rewards
] else [
award("bronze") ~> m_rewards
]
]
]
}
Conditional Sends
A common pattern is conditionally sending a refund. An if condition reads
the members after the route’s transforms, so the previous bid and bidder are
bound in an earlier phase, before the
transforms overwrite them:
entity Auction {
routes {
bid()
where msg::value > m_highest_bid : throw 100
=> [
snap: [
let prev_bid = m_highest_bid;
let prev_bidder = m_highest_bidder;
]
refund: [
if prev_bid > 0 => [
~> prev_bidder with { value: prev_bid }
]
]
]
}
m_highest_bid: U256 {
in bid() => refund: msg::value
}
m_highest_bidder: address {
in bid() => refund: msg::sender
}
}
This refunds the previous highest bidder only if there was a previous bid.
Conditional Deploy
Deploy an entity only under certain conditions:
routes {
ensure_vault(user: address) => [
if !m_vaults.exists(user) => [
deploy UserVault(user) with { value: 1_000_000 }
]
]
}
Conditionals with Let Bindings
Let bindings can precede conditional actions:
routes {
distribute() => [
let fee = msg::value * 3 / 100;
let net = msg::value - fee;
if fee > 0 => [
~> m_treasury with { value: fee }
]
~> m_recipient with { value: net }
]
}
Complete Example
entity Escrow {
event Resolved(indexed deal_id: u64, approved: bool);
routes {
#[factory_only]
init setup(deal_id: u64, buyer: address, seller: address, arbiter: address) => []
deposit()
where msg::sender == m_buyer : throw 201
=> []
resolve(approved: bool)
where msg::sender == m_arbiter : throw 200
&& !m_resolved : throw 202
=> [
if approved => [
~> m_seller with { value: m_amount }
emit Resolved(m_deal_id, true);
] else [
~> m_buyer with { value: m_amount }
emit Resolved(m_deal_id, false);
]
]
}
m_deal_id: u64 {
in setup(deal_id, _, _, _) => deal_id
}
m_buyer: address {
in setup(_, buyer, _, _) => buyer
}
m_seller: address {
in setup(_, _, seller, _) => seller
}
m_arbiter: address {
in setup(_, _, _, arbiter) => arbiter
}
m_amount: U256 {
in deposit() => m_amount + msg::value
}
m_resolved: bool {
in resolve(approved) => true
}
}