Functions
Functions in Lyquid are declared with the lyquid::method! macro and are split into two categories, each mapping naturally to one of the two state categories:
🔹 Network Functions (Lyquid-level Execution)​
- Every node hosting the same Lyquid executes the identical, deterministic sequence of calls to network functions.
- Can only read and write network state.
- Similar to Solidity's
publicorexternalfunctions.
lyquid::method! {
network fn transfer(&mut ctx, to: Address, amount: U256) -> LyquidResult<bool> {
let from = ctx.caller.clone();
transfer(&mut ctx.network, from, to, amount)?;
Ok(true)
}
network fn approve(&mut ctx, spender: Address, value: U256) -> LyquidResult<bool> {
approve(&mut ctx.network, ctx.caller, spender, value, true)?;
Ok(true)
}
}
🔸 Instance Functions (Node-level Execution)​
If you're coming from Solidity, think of instance functions as supercharged view functions with much more power.
- Like
viewfunctions, they can read network state, but not modify it. - Unlike Solidity, they can also read/write instance state and handle events that may differ from node to node, such as network messages.
In Lyquid, instance functions are a first-class concept that unlock entirely new design patterns:
- Resilient API request and response (via UPC)
- Heavy-lifting computation
- Local caching and performance metrics
lyquid::method! {
instance fn balance_of(&ctx, account: Address) -> LyquidResult<U256> {
// Can function like a regular `view` function as in Solidity, &ctx promises not to modify any state.
Ok(get_balance(&ctx.network, &account).clone())
}
instance fn party_sign(&mut ctx, tx: Transaction) -> LyquidResult<Option<Signature>> {
Ok(if validate(tx) {
ctx.multi_sig_key.map(|| key.sign(tx.digest()))
} else {
None
})
}
instance fn record_transaction(&mut ctx, tx: Transaction) -> LyquidResult<()> {
ctx.instance.tx_history.push(tx);
Ok(())
}
instance fn analyze_trading_pattern(&mut ctx, user: Address) -> LyquidResult<Analysis> {
let history = &ctx.instance.tx_history;
let user_txs: Vec<_> = history.iter()
.filter(|tx| tx.user == user)
.collect();
Ok(analyze_transactions(&user_txs))
}
}
💡 Unlike Solidity, instance functions can access node-local state and react to off-chain events. You can even define functions that aggregate results across multiple nodes via UPC, enabling powerful new architectures, like customized oracle and bridging, decentralized order matching, multi-party computation, and so on.
See lyquid::method! for full syntax and advanced UPC forms.