Skip to main content

Using Value Notes in Aztec.nr

ValueNotes hold one main property - a value - and have utils useful for manipulating this value, such as incrementing and decrementing it similarly to an integer.

ValueNote

This is the ValueNote struct:

value-note-def
// ValueNote is used as fn parameter in the Claim contract, so it has to implement the Serialize trait.
// It is important that the order of these annotations is preserved so that derive(Serialize) runs AFTER the note macro, which injects the note header.
#[note]
#[derive(Serialize)]
pub struct ValueNote {
value: Field,
owner: AztecAddress,
randomness: Field,
}
Source code: noir-projects/aztec-nr/value-note/src/value_note.nr#L18-L28

Importing ValueNote

In Nargo.toml

value_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="aztec-packages-v0.66.0", directory="noir-projects/aztec-nr/value-note" }

In your contract

import_valuenote
use dep::value_note::value_note::ValueNote;
Source code: noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr#L23-L25

Working with ValueNote

Creating a new note

Creating a new ValueNote takes the following args:

  • value (Field): the value of the ValueNote
  • npk_m_hash (Field): the master nullifier public key hash of the user
valuenote_new
let mut note = ValueNote::new(amount as Field, donor);

let donor_ovpk_m = get_public_keys(donor).ovpk_m;
Source code: noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr#L85-L89

In this example, amount is the value and the npk_m_hash of the donor was computed earlier.

Getting a balance

A user may have multiple notes in a set that all refer to the same content (e.g. a set of notes representing a single token balance). By using the ValueNote type to represent token balances, you do not have to manually add each of these notes and can instead use a helper function get_balance().

It takes one argument - the set of notes.

get_balance
// Return the sum of all notes in the set.
balance_utils::get_balance(owner_balance)
Source code: noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr#L101-L104

This can only be used in an unconstrained function.

Incrementing and decrementing

Both increment and decrement functions take the same args:

increment_args
balance: PrivateSet<ValueNote, &mut PrivateContext>,
amount: Field,
recipient: AztecAddress,
Source code: noir-projects/aztec-nr/value-note/src/utils.nr#L21-L25

Note that this will create a new note in the set of notes passed as the first argument. For example:

increment_valuenote
increment(
storage.notes.at(owner),
value,
owner,
outgoing_viewer,
outgoing_viewer,
);
Source code: noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr#L24-L32

The decrement function works similarly except the amount is the number that the value will be decremented by, and it will fail if the sum of the selected notes is less than the amount.

Learn more