Token shortlist
On this page, we explain how to update Version 0.10 circuits – supporting only the native AZERO token – to handle more tokens. Due to note structure limitations, in this update we choose around 5-30 tokens to support, and we call the list of chosen tokens the token shortlist. Full ERC20 support is expected in future releases.
We only discuss the Withdraw
circuit, as the remaining circuits should be easy to implement if the design of Withdraw
is known.
We represent the account balances as a 6-tuple. We assume that there are 2 destination addresses (for the recipient and for the fee), and we do not differentiate between them. The circuit receives 2 indexes of modified balances as public inputs, and performs range checks just on the 2 new balances.
In the future, we will be able to extend the length of the tuple with small changes to the circuits and no note migration. We describe such an extension in the last section.
Alternative designs
We considered storing the shortlisted balances as a tree of height 2, but abandoned this idea because it visibly increases circuit complexity without significant performance gains for the expected number of shortlisted tokens.
Note representation
We represent the account balances of all tokens, including AZERO, as the following tuple:
We do not need to decide in advance, which tokens occupy all NUM_SLOTS
slots. We may define the slot mapping in the contract just for a subset of slots, and make the contract reject attempts to use the unused slots. In any case, the NewAccount
circuit should properly initialize all slots.
Our note struct is given by:
For an account tuple acc
, we define its hash as:
Withdraw
relation
Withdraw
relationWe are ready to define the Withdraw
relation:
The definition above does not immediately translate to a circuit description because of the way constraint groups (C1) and (C2) are defined. These constraint groups may be implemented in a circuit as follows:
Implementing constraint group (C1) in a circuit
First, we introduce auxiliary private witnesses idx_i_j ∈ {0, 1}
such that:
Then, for every j ∈ {0, ..., NUM_SLOTS - 1}
, we add the following constraint:
We create the above constraints using a custom gate.
Implementing constraint group (C2) – the range check – in a circuit
We just add the following constraint, for i ∈ {1, 2}
:
Increasing balance tuple size
We may increase NUM_SLOTS
. We always require NUM_SLOTS
to be a multiple of 6.
For NUM_SLOTS = 6k > 6
, we define h_acc = h(acc, 0)
, where h(acc, i)
is recursively defined as:
For example:
The hash of
(1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0)
isposeidon2(1, 2, 3, 4, 5, 6, 0).
The hash of
(1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 1)
isposeidon2(1, 2, 3, 4, 5, 6, poseidon2(0, 0, 0, 0, 0, 1, 0))
.
Note that we do not allow (1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0)
to be hashed as poseidon2(1, 2, 3, 4, 5, 6, poseidon2(0, 0, 0, 0, 0, 0, 0))
. This way, every balance tuple has a deterministic hash value.
This change requires updating NUM_SLOTS
and the hashing logic in the circuits, but no note migration.
Last updated