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

Generic Types

Parameterized types for collections, optionals, and typed entity addresses.

Vec<T>

Dynamic ordered sequence:

m_participants: Vec<address> {
    in register(addr) => m_participants.push(addr)
}
MethodDescription
v.len()Length (use v.len() == 0 to test for emptiness)
v.push(elem)Append (as the tail of a Vec member transform on EVM)
v[index]Element at index

array(...) builds a vector value, e.g. as a member default:

m_empty: Vec<u64> = array() {}
m_nums: Vec<u64> = array(1, 2, 3) {}

HashMap<K, V>

Key-value map (keys are hashable primitives / address):

m_balances: HashMap<address, U256> {
    in transfer(src, dst, amount) => m_balances
        .insert(src, m_balances[src] - amount)
        .insert(dst, m_balances[dst] + amount)
}
MethodDescription
m[key]Read; returns the type’s default (e.g. 0) when the key is absent
m.insert(k, v) / m.update(k, v)Write (in a member transform; chainable)
m.remove(key)Delete (in a member transform)
m.exists(key) / m.contains(key)Presence

Option<T>

some(value) / none. Unwrap an option with match:

let result = match m_limit {
    some(val) => val * 2,
    none => 0
};

There are no .unwrap() / .unwrap_or() / .is_some() methods — always match on the two cases.

Address<Entity>

Typed wrapper around address that carries the target entity at compile time. Named messages should use a typed destination. Plain value transfers (~> dest with { value }) may use untyped address.

m_root: Address<RootToken> {}     // named sends
m_backup: address {}              // value transfers

A named send to a plain address is rejected (V23): type the destination as Address<Entity> so the message is checked against the target’s routes. For a foreign contract, declare it with extern entity and use Address<ThatExternEntity>.

Predicting addresses (EVM)

On the EVM target, compute a destination without a manual factory:

macro pairAddr(token0: address, token1: address) -> Address<UniswapV2Pair> = {
    UniswapV2Pair.address(token0, token1)
}

routes {
    notify(token0: address, token1: address) => [
        Ping() ~> UniswapV2Pair.address(token0, token1)
    ]
}

Entity.address(args) and the addressOf(...) spelling lower to the same CREATE2 expression on EVM. Singletons use Entity.address() with no arguments. See Deterministic Addresses and Deploy.

FeatureAddress<Entity>address
Named sendChecked against the target’s routesRejected (V23)
Plain value transferAllowedAllowed
Compile-time route checksYesNo