> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metalntwx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Unshield Circuit

> How the unshield proof spends notes and releases MIP20 value to a public destination

Every unshield transaction carries an unshield proof. Unshielding spends notes
and releases their MIP20 value to an authorized public destination. The key
holder authorizes the spend. With custodial keys, the customer's virtual asset service
provider (VASP) can prepare and sign the action. With
[self-custodied keys](https://docs.metalntwx.com/learn/mip410/roles-and-authorization.md#custodian), the customer's
wallet must sign. The proof establishes this statement:

> I am unshielding `amount` units of `asset` from the pool to `destination`,
> the public destination I authorize. The input notes sit in the commitment
> tree, and I authorize their spend with the spending key behind
> them. The value leaving the pool plus my change note equals the value of
> the inputs, and I am not sanctioned.

## What unshielding checks

The circuit binds `destination` to the key holder's authorization and proves
that the spender's `affilID` is absent from the sanctioned set. There is no
pool-side destination registration or proof that the spender owns the public
destination. The outgoing MIP20 transfer remains subject to the token's policy.

Because an unshield spends notes, the proof also checks input ownership,
commitment-tree membership, nullifier and input lock ID derivation, and value
conservation into an optional change note. The pool separately checks the
spent set and input lock set.

The unshield destination, asset, and amount are public. Which note commitments
were spent, and the earlier activity that produced them, remain private. The
[unshielding](https://docs.metalntwx.com/learn/mip410/shielded-payments.md#unshielding) page describes the lifecycle, and
[Privacy](https://docs.metalntwx.com/start/privacy) describes what each party sees.

## Spending notes during unshielding

An unshield uses the same note identifiers as a shielded payment on a different
schedule. A payment keeps its nullifiers
[sealed in the payment effect hash](https://docs.metalntwx.com/reference/privacy/transfer-circuit.md#payment-identifiers)
from initiation until an `Accept` resolution. An unshield publishes its
nullifiers in one transaction. The pool requires each nullifier to be absent
from the spent set and records it during the same execution. Both actions use
`Poseidon2(nk, leafIndex, DOMAIN_NULLIFIER)` for each input note.

The proof also derives each input lock ID as
`Poseidon2(nk, leafIndex, DOMAIN_LOCK)`. The pool checks that no active hold has
reserved an input and unshield does not modify the input lock set. The circuit
derives the input lock IDs and nullifiers from the same `(nk, leafIndex)` pairs,
binding the lock check to the notes being spent.

Any remaining value returns as a change note. The change note's address must
satisfy `pk_d = ivk · g_d`, so change returns to the same identity. Wallets
should choose a fresh diversifier; the circuit does not enforce its freshness.
Its `shieldTimestamp` is the minimum of the inputs' values,
so it retains the age of the oldest input. The input amounts must equal the
public `amount` plus the change amount, with every amount range-checked to 128
bits. One or two notes can fund one unshield. An unused second input slot
publishes zero for its nullifier and input lock ID. If no value remains, the change note
commitment takes the canonical empty value and the pool appends nothing.

## The spender screen

From the incoming viewing key, the circuit derives the identity's stable
[`affilID`](https://docs.metalntwx.com/reference/privacy/key-derivation#derived-identifiers) and proves
it absent from the sanctioned set. Unshielding does not require a VASP
policy-wrapper proof. Custody and key protection must account for the spending
key's ability to authorize a public destination.

## Witness

| Witness | Role |
| - | - |
| Input note openings, base-point roots, Merkle paths, and real-input flags | Up to two [note openings](https://docs.metalntwx.com/reference/privacy/shielded-note.md#the-commitment), their address derivations and membership in the commitment tree; the first slot must be real |
| Ownership pair `(ak, nk)` and the authorization signature | Prove the notes belong to one identity and that this exact unshield was [authorized](https://docs.metalntwx.com/reference/privacy/key-derivation.md#spend-authorization) |
| Change note opening | The note returning the remainder, bound to the same identity |
| Sanctions path | Non-membership of `affilID` in the sanctioned set |

The witness remains with the prover. Its preparation can be delegated through
[outsourced proving](https://docs.metalntwx.com/reference/privacy/key-derivation.md#outsourced-proving), but
the key holder must authorize the unshield with a Schnorr signature under `ak`.

## Public inputs

| Public input | How the pool constrains it |
| - | - |
| `chain_id`, `pool_address` | Supplied by the pool to bind the proof to this deployment |
| `asset`, `amount` | The MIP20 value the pool transfers out |
| `destination` | The unshield destination that receives the transfer |
| Commitment tree root | Must be a root the pool knows |
| `nullifiers[2]` | Each real input's nullifier must be unspent; the pool records it permanently and skips zero dummy slots |
| `lock_ids[2]` | Each real input's input lock ID must be absent from the input lock set |
| Change note commitment | Appended to the tree, unless it is the canonical empty value |
| `sanctions_root` | Must be the current sanctions root |

The table follows the circuit's twelve public inputs in order, with each array
flattened in place. Its nullifiers prevent successful
resubmission after they enter the spent set.

The pool verifies the proof at `0xF2`, records the nullifiers, appends any
nonzero change note commitment, and transfers the MIP20 amount to
`destination`. If the MIP20 transfer fails, atomic rollback reverses the
complete operation, including the nullifiers and change note commitment.

## Illustration

![The unshield circuit combines input note openings, ownership data, authorization, and public inputs into an unshield proof. The pool checks the input lock IDs, nullifiers, and accepted roots before transferring MIP20 value to the destination.](https://mintcdn.com/nexus-ed339086/CdWwGT0bcT9zD-Uw/images/mip410/unshield-circuit.svg?fit=max\&auto=format\&n=CdWwGT0bcT9zD-Uw\&q=85\&s=bd2b30d97724ac15920224caa612cfbb)

## Unshield transaction submission

Any public account may submit the prepared unshield transaction and pay gas.
The customer, a relayer, or the customer VASP may act as submitter. The unshield
proof fixes the destination, amount, inputs, change note, and private checks.
The submitter cannot alter those values or authorize another spend.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.