> ## 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.

# Event Catalog

> Events emitted by Metal tokens, registries, shielded payments, and interoperability contracts

Index logs from finalized blocks. Logs produced during successful execution
appear in transaction receipts. Reverted transactions contain none.

## MIP20 and factory

| Event | Indexed fields | Emitted when |
| - | - | - |
| `Transfer(from, to, value)` | `from`, `to` | A transfer, mint, burn or transfer into or out of a MIP20 hold succeeds |
| `Approval(owner, spender, value)` | `owner`, `spender` | An explicit approval sets the allowance. Spending a finite allowance does not emit another Approval |
| `AuthorizationUsed(authorizer, nonce)` | `authorizer`, `nonce` | An ERC-3009 authorization is consumed |
| `AuthorizationCanceled(authorizer, nonce)` | `authorizer`, `nonce` | A signed cancellation consumes the authorization |
| `HoldPlaced(owner, spender, amount)` | `owner`, `spender` | A spender holds part of an owner's balance. Follows `Transfer(owner, token, amount)` into the token's escrow |
| `HoldReleased(owner, spender, amount)` | `owner`, `spender` | A hold is released or captured. Follows `Transfer(token, owner, amount)`, and a capture then emits the transfer events from `owner` |
| `MIP20Deployed(token, deployer)` | `token`, `deployer` | A factory deployment creates a token and adds it to the MIP20 allowlist |
| `OwnershipTransferred(previousOwner, newOwner)` | `previousOwner`, `newOwner` | A factory-deployed `MetalToken` is created or its owner transfers ownership |

MIP20 minting emits `Transfer(address(0), to, amount)`. The destination is the
intended holder for an accepted mint, or ReceivePolicy for a refused mint.

A token transfer to `0x0000000000000000000000000000000000000f4d` credits
ReceivePolicy quarantine. Match it with that contract's
`Quarantined(bytes32 indexed receiptId, address indexed receiver, address indexed originator, Receipt receipt, uint8 reason)`.
The [quarantine receipt](https://docs.metalntwx.com/reference/compliance/receive-policy.md#quarantine-and-receipts)
identifies the token, amount and recovery authority.
`Claimed(bytes32 indexed receiptId, address indexed to)` records recovery and
must be paired with the exact token transfer out of quarantine. For an
authorized payment, match `AuthorizationUsed` with its transfer to determine
whether the recipient or quarantine received the funds.

## MIP410

The pool at `0x0000000000000000000000000000000000000410` emits the events below.
The [MIP410 API](https://docs.metalntwx.com/reference/assets-and-payments/mip410.md) lists the calls that emit them.

### Pool and hold lifecycle

| Event | Indexed fields | Emitted when |
| - | - | - |
| `Shielded(asset, depositor, amount, noteCommitment)` | `asset`, `depositor`, `noteCommitment` | A shield executes and MIP20 backing enters the pool |
| `NoteCommitmentAppended(noteCommitment, leafIndex, newRoot)` | `noteCommitment` | Shielding, an `Accept` resolution, or unshield change appends a note commitment |
| `HoldCreated(holdId, paymentEffectHash, deadline, payloadCommitment)` | `holdId`, `paymentEffectHash` | Valid initiation and policy-wrapper proofs create a hold and fix its [payment effect](https://docs.metalntwx.com/reference/assets-and-payments/mip410.md#initiate-a-shielded-payment), deadline, and payload commitment |
| `InputLocked(holdId, inputLockId)` | `holdId`, `inputLockId` | An initiation locks one input against another hold or spend |
| `HoldAccepted(holdId)` | `holdId` | Valid resolution and policy-wrapper proofs accept a hold |
| `HoldRejected(holdId)` | `holdId` | Valid resolution and policy-wrapper proofs reject a hold |
| `HoldReclaimed(holdId)` | `holdId` | An expired hold is reclaimed and its input locks are released |
| `InputLockReleased(holdId, inputLockId)` | `holdId`, `inputLockId` | A `Reject` resolution or reclaim releases one input lock |
| `NullifierSpent(nullifier)` | `nullifier` | An `Accept` resolution or unshielding marks a note as spent |
| `Unshielded(asset, destination, amount)` | `asset`, `destination` | An unshield executes and backing leaves the pool |
| `BridgeMinted(asset, depositId, amount, noteCommitment)` | `asset`, `depositId`, `noteCommitment` | A bridge deposit mints its note and bridge liability grows |
| `BridgeWithdrawn(asset, routeId, withdrawalId, amount, destCommitment)` | `asset`, `routeId`, `withdrawalId` | A bridge exit spends its notes and bridge liability shrinks |

Index each appended note from `NoteCommitmentAppended` and each spent note from
`NullifierSpent`. An `Accept` resolution emits `HoldAccepted`, one
`NullifierSpent` for each real input, one `NoteCommitmentAppended` for the
recipient note, and one for the change note when present. Acceptance keeps the
input locks permanently set. Rejection and reclaim release them without
appending note commitments or recording nullifiers.

Indexers derive `Expired` from a hold's `deadline` and the finalized block
timestamp. The inputs remain locked until `HoldReclaimed` records their release.

### The VASP tree and the sanctioned set

The tree records virtual asset service providers (VASPs). The MIP410 authority
administers admission and revocation.

| Event | Indexed fields | Emitted when |
| - | - | - |
| `FiAdmitted(index, fiId, vkHash, mpkX, mpkY, newRoot)` | `index`, `fiId` | The authority admits an institution at a slot |
| `FiRevoked(index, fiId, newRoot)` | `index`, `fiId` | The authority returns a slot to the empty leaf |
| `FiUpdated(index, fiId, vkHash, mpkX, mpkY, newRoot)` | `index`, `fiId` | A VASP authorizes replacement of its policy verification key hash and messaging key |
| `Sanctioned(affilId, index, newRoot)` | `affilId` | The authority adds an identity to the sanctioned set at position `index` |
| `SanctionsReset(sortedAffilIds, newRoot)` | — | The authority rebuilds the sanctioned set under a fresh generation |

Each event carries the new root of its tree. An admission retains the previous
registration root. Revocations, updates, and sanctions writes retire the old
root according to the [root windows](https://docs.metalntwx.com/reference/assets-and-payments/mip410.md#root-windows). Use
the events to trigger a registry refresh through the pool's getters. The leaf
preimage that `FiAdmitted` or `FiUpdated` publishes lets other VASPs rebuild the
tree.

### Administration

| Event | Indexed fields | Emitted when |
| - | - | - |
| `AuthorityTransferStarted(current, pending)` | `current`, `pending` | The authority names its successor, or cancels by naming zero |
| `AuthorityTransferred(previous, current)` | `previous`, `current` | The pending account accepts and becomes the authority |
| `PoolPaused(by)` | `by` | The authority stops the value paths |
| `PoolUnpaused(by)` | `by` | The authority reopens them |
| `AssetAdmitted(asset)` | `asset` | `shield` accepts the asset from this block on |
| `AssetRevoked(asset)` | `asset` | `shield` refuses the asset. Unshielding remains available |
| `CircuitIdUpdated(circuit, previousId, newId)` | `circuit` | The pool verifies that circuit's proofs against a different registered key |
| `MaxHoldDurationUpdated(previousDuration, newDuration)` | — | The ceiling on hold deadlines moves |
| `BridgeGatewayUpdated(previousGateway, newGateway)` | — | The authority names a different bridge gateway, or disables the bridge with zero |

These events expose public registry and configuration changes. The submitter
account and its gas payment are also public.

## Shared registries

| Event | Contract | Indexed fields | Emitted when |
| - | - | - | - |
| `CircuitRegistered(circuitId, pointer, backend, vkLength)` | `CircuitRegistry` | `circuitId`, `pointer` | A new verification key is registered. Registering the same key again emits no event |

## Interoperability

| Event | Contract | Indexed fields | Emitted when |
| - | - | - | - |
| `MessageSent(nonce, destinationChainId, target, sender, payload)` | Metal outbox or source-chain `Outbox` | `nonce`, `destinationChainId`, `target` | A message commitment is recorded |
| `MessageExecuted(nonce, target, sender)` | `MetalInbox` | `nonce`, `target` | A proved Metal message executes successfully on the destination chain |
| `MessageExecuted(nonce, target, sender)` | `ForeignInbox` | `nonce`, `target` | A proved source-chain message executes successfully on Metal |
| `CheckpointAccepted(blockHash, blockNumber, viewNumber, stateRoot, receiptsRoot, timestampMs)` | Metal and Tempo light clients | `blockHash`, `blockNumber` | A verified checkpoint advances the client |
| `CheckpointAccepted(blockHash, blockNumber, stateRoot, receiptsRoot, timestampMs)` | Arc light client | `blockHash`, `blockNumber` | A verified Arc checkpoint advances the client |

Ethereum checkpoints on Metal are updated during block execution through the
read-only protocol contract, which emits no checkpoint event. Read its
[checkpoint getters](https://docs.metalntwx.com/reference/interop/light-clients.md#ethereum-light-client).
Message events support reconstruction and indexing. Inboxes authenticate
delivery using proofs against accepted checkpoints.

## Finality and indexing

1. Read logs with `eth_getLogs` or transaction receipts.
2. Deduplicate by `(blockHash, transactionIndex, logIndex)`.
3. Advance application state only through the finalized block.
4. Replay from the last finalized cursor after a restart.

> [card] [JSON-RPC](https://docs.metalntwx.com/reference/json-rpc/overview.md)
>
> Look up log and block methods.

> [card] [Verify and reconcile payments](https://docs.metalntwx.com/build/payments/verify-and-reconcile-payments.md)
>
> Build an indexer that advances on finality and replays safely.

> [card] [Finality](https://docs.metalntwx.com/learn/architecture.md)
>
> Determine when a block and its logs are final.


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