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

Libraries and Using

Cambrian offers two complementary ways to reuse pure helpers: named library blocks and using … for T method-call sugar.

library Name { … }

A library is a named scope of pure fn, const, and type items only. Bodies may not touch entity state, msg::*, or temporal references — the same purity envelope as a free pure fn. Like any pure fn, library functions have no where clause; put preconditions on the calling route.

library FeeMath {
    const BPS: U256 = 10000

    pure fn fee(amount: U256, rate_bps: U256) -> U256 {
        amount * rate_bps / BPS
    }

    pure fn net(amount: U256, rate_bps: U256) -> U256 {
        amount - fee(amount, rate_bps)
    }
}

using FeeMath for U256;

entity Vault {
    routes {
        deposit(amount: U256) => []
    }

    m_balance: U256 {
        in deposit(amount) => m_balance + amount.net(30)
    }

    m_fees: U256 {
        in deposit(amount) => m_fees + FeeMath.fee(amount, 30)
    }
}

Call library functions with a qualifier (FeeMath.fee(amount, 30)), or as methods attached via using (amount.net(30), below).

using Lib for T

using FeeMath for U256; in the example above attaches every suitable function from the library as a method on U256, so amount.net(30) means FeeMath.net(amount, 30).

recv.fn(args) rewrites to Lib.fn(recv, args) (or the free pure fn form) before codegen. Chained receiver calls such as amount.net(30).net(10) work when each step’s return type matches the next receiver, and a chain may also start from a qualified call (FeeMath.fee(a, b).net(10)).

using { fn1, fn2 } for T

Attach selected free pure fns without a library wrapper:

pure fn double(x: U256) -> U256 { x * 2 }
pure fn triple(x: U256) -> U256 { x * 3 }

using { double, triple } for U256;

entity Foo {
    routes {
        bump() => []
    }

    m_n: U256 {
        in bump() => m_n.double().triple()
    }
}

Rules of thumb

  • The first parameter of each attached function must match the for type.
  • When the for type is Vec, HashMap, or Option, method names must not collide with that type’s built-in methods (len, push, insert, exists, …).
  • Libraries and free pure fns may live in imported .cam files. See Program Structure and the Contract Standard Library.

Lowering

On EVM, each Cambrian library becomes a Solidity library with internal pure (or equivalent) functions. Call sites use LibName.fn(args). Free pure fns outside a library remain top-level Solidity helpers.

On Lean, a library is flattened into ordinary pure functions named Lib_fn (a library const becomes a zero-argument function), and every qualified or using call is rewritten to call them.