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

Calling Contracts

Build, simulate, and send contract function calls via aztec-contract.

Runnable Examples

  • examples/simulate_profile_send.rs — simulate → profile → send for a single call.
  • examples/private_token_transfer.rs — private function call end to end.
  • examples/public_storage.rs — public function + public storage read.
  • examples/note_getter.rs — reading owned notes from the PXE.

Typical Flow

use aztec_rs::abi::{AbiValue, ContractArtifact};
use aztec_rs::contract::Contract;

let artifact: ContractArtifact = /* load_artifact(...) */;
let handle = Contract::at(token_address, artifact, wallet.clone());

// Build a call — arity and types are validated against the artifact.
let call = handle.method("transfer", vec![
    AbiValue::Field(sender.into()),
    AbiValue::Field(recipient.into()),
    AbiValue::Integer(amount),
])?;

// Optional: simulate + profile
let sim   = call.simulate(Default::default()).await?;
let prof  = call.profile(Default::default()).await?;

// Submit; SendOptions picks the fee payment method.
let sent  = call.send(SendOptions { from: sender, ..Default::default() }).await?;
println!("tx hash: {}", sent.tx_hash);

Choosing the Right Path

Function kindMethod
Privatehandle.method(...).send(...)
Publichandle.method(...).send(...) (same)
Utility (off-chain)Wallet::execute_utility(call, opts) or handle.method(...).simulate(...)

Wallet::execute_utility does not produce a transaction; it runs the utility inside the PXE and returns the decoded values + logs.

Batch Calls

BatchCall bundles several calls into a single transaction. Use it when multiple calls share authorization or must be atomic.

Attaching Authwits / Capsules

let call = handle.method("spend_on_behalf", args)?
    .with(vec![authwit], vec![capsule]);

ContractFunctionInteraction::with(auth_witnesses, capsules) attaches additional authorization or capsule data before simulation / send.

Full Runnable Example

Source: examples/simulate_profile_send.rs.

//! Compare simulation, profiling, and sending for the same call.

#![allow(clippy::print_stdout, clippy::wildcard_imports)]

mod common;

use common::*;

#[tokio::main]
async fn main() -> Result<(), aztec_rs::Error> {
    let Some((wallet, owner)) = setup_wallet(TEST_ACCOUNT_0).await else {
        return Err(aztec_rs::Error::InvalidData(format!(
            "node not reachable at {}",
            node_url()
        )));
    };

    let (address, artifact, _) = deploy_contract(
        &wallet,
        load_stateful_test_artifact(),
        vec![abi_address(owner), AbiValue::Field(Fr::from(1u64))],
        owner,
    )
    .await?;

    let call = build_call(
        &artifact,
        address,
        "increment_public_value_no_init_check",
        vec![abi_address(owner), AbiValue::Field(Fr::from(5u64))],
    );
    let payload = ExecutionPayload {
        calls: vec![call],
        ..Default::default()
    };

    let sim = wallet
        .simulate_tx(
            payload.clone(),
            SimulateOptions {
                from: owner,
                estimate_gas: true,
                ..Default::default()
            },
        )
        .await?;
    let gas_limits = get_gas_limits(&sim, None);

    let profile = wallet
        .profile_tx(
            payload.clone(),
            ProfileOptions {
                from: owner,
                profile_mode: Some(ProfileMode::Full),
                ..Default::default()
            },
        )
        .await?;

    let tx_hash = wallet
        .send_tx(
            payload,
            SendOptions {
                from: owner,
                gas_settings: Some(GasSettings {
                    gas_limits: Some(gas_limits.gas_limits.clone()),
                    teardown_gas_limits: Some(gas_limits.teardown_gas_limits.clone()),
                    ..Default::default()
                }),
                ..Default::default()
            },
        )
        .await?
        .tx_hash;

    let updated_value =
        read_public_u128(&wallet, address, derive_storage_slot_in_map(2, &owner)).await?;

    println!("Contract address:   {address}");
    println!("Sim return values:  {}", sim.return_values);
    println!(
        "Suggested gas:      da={} l2={}",
        gas_limits.gas_limits.da_gas, gas_limits.gas_limits.l2_gas
    );
    println!("Profile payload:    {}", profile.profile_data);
    println!("Sent tx hash:       {tx_hash}");
    println!("Updated value:      {updated_value}");

    Ok(())
}

References