Skip to main content
Version: 0.13

Account Operations

The #[component] macro automatically provides methods on self for interacting with the current account during a transaction. Read-only queries are available on &self, and mutations (add/remove assets, increment nonce) require &mut self.

Read-only queries (&self)

#[component]
impl MyAccount {
pub fn check_state(&self) {
// Account identity
let id: AccountId = self.get_id();
let nonce: Felt = self.get_nonce();

// Vault queries
let balance: Felt = self.get_balance(faucet_id);
let initial: Felt = self.get_initial_balance(faucet_id);
let has_nft: bool = self.has_non_fungible_asset(asset);
let root: Word = self.get_vault_root();
let initial_root: Word = self.get_initial_vault_root();

// Commitment queries
let commitment: Word = self.compute_commitment();
let initial_commit: Word = self.get_initial_commitment();
let storage: Word = self.compute_storage_commitment();
let initial_storage: Word = self.get_initial_storage_commitment();
let code: Word = self.get_code_commitment();

// Procedure queries
let count: Felt = self.get_num_procedures();
let proc_root: Word = self.get_procedure_root(0);
let exists: bool = self.has_procedure(proc_root);
}
}

Mutations (&mut self)

#[component]
impl MyAccount {
pub fn receive_asset(&mut self, asset: Asset) {
// Add an asset to the vault — returns the asset as stored
let stored: Asset = self.add_asset(asset);
}

pub fn send_asset(&mut self, asset: Asset, note_idx: NoteIdx) {
// Remove an asset from the vault — returns the removed asset
// Proof generation fails if the asset doesn't exist or insufficient balance
let removed: Asset = self.remove_asset(asset);
output_note::add_asset(removed, note_idx);
}

pub fn auth(&mut self) {
// Increment the account nonce (replay protection)
let new_nonce: Felt = self.incr_nonce();

// Compute commitment of all state changes in this transaction
let delta: Word = self.compute_delta_commitment();

// Check if a specific procedure was called during this transaction
let called: bool = self.was_procedure_called(proc_root);
}
}

The nonce must be incremented for any transaction that modifies account state. Without it, the same transaction could be replayed.

When proof generation fails

Several operations cause proof generation to fail if preconditions aren't met:

OperationFails when
remove_asset(asset)Asset not in vault or insufficient balance
get_balance(faucet_id)Referenced asset is non-fungible
get_procedure_root(index)Index out of bounds
Any assert!()Condition is false

When proof generation fails:

  1. The ZK circuit cannot produce a valid proof
  2. The transaction is rejected before reaching the network
  3. No state changes occur
  4. The client receives an error describing the failure

Example: ManagedWallet

#![no_std]
#![feature(alloc_error_handler)]

use miden::{component, output_note, Asset, AccountId, NoteIdx, Felt};

#[component]
struct ManagedWallet;

#[component]
impl ManagedWallet {
/// Receive an asset into the vault.
pub fn receive_asset(&mut self, asset: Asset) {
self.add_asset(asset);
}

/// Send an asset to an output note, with balance check.
pub fn send_asset(&mut self, asset: Asset, note_idx: NoteIdx) {
let removed = self.remove_asset(asset);
output_note::add_asset(removed, note_idx);
}

/// Query the balance of a fungible asset.
pub fn balance_of(&self, faucet_id: AccountId) -> Felt {
self.get_balance(faucet_id)
}
}

To move assets out of an account, create output notes with output_note::add_asset. For signature verification and nonce management, see Authentication.

Full API docs on docs.rs: miden