Skip to main content
Metal uses EIP-712 for the 0x7f transaction envelope and MIP20 ERC-3009 authorizations. MIP410 verifies Schnorr wallet authorization inside its shield, initiation, and unshield proofs. The signing digest is:

MIP20 0x7f transaction

The authorization-list hash binds every EIP-7702 authorization carried by the transaction. Use the Metal SDK codec to compute it.

MIP20 ERC-3009

The EIP-712 domain uses the token’s name, version "1", the chain ID, and the MIP20 token address.
Authorization is valid only when block.timestamp > validAfter and block.timestamp < validBefore; when both values set bit 47, they are block numbers instead. A (from, nonce) pair is single-use, and cancelling it uses it up. Read the domain with eip712Domain() (ERC-5267). The signature is from’s own 65-byte ECDSA signature over the digest. When it is not and from has code (a contract, or an EOA delegated by EIP-7702), MIP20 asks the account through ERC-1271 isValidSignature(digest, signature) and accepts the authorization when the account does. The owner’s key stays valid on a delegated account.

MIP410 wallet authorization

The key holder signs a Poseidon2 digest with the spending key. The circuit verifies the Grumpkin Schnorr signature under the spend-verification key ak. The proof witness contains the signature, ak, the nullifier key nk, and the note material. The circuit witness does not contain the spending key. Each wallet digest hashes an operation-specific domain tag followed by every public input in the circuit’s declared order:
Tags are their ASCII bytes interpreted as big-endian field elements. Dummy input slots contribute zero. The initiation signature binds the nullifiers and output note commitments through the payment effect hash. The circuit verifies that the inputs and change belong to the signing identity. The pool enforces the hold deadline and prevents reuse of a payment effect hash. Shielding also requires the depositor’s MIP20 ERC-3009 ReceiveWithAuthorization signature, with the pool as payee and the note commitment as nonce. Its EIP-712 digest is separate from the wallet’s Schnorr authorization. Resolution requires the recipient VASP’s authorization and no new signature under the customer’s spending key. Reclaim needs no proof or signature beyond the outer transaction signature.

VASP signatures

The VASP messaging key signs three payment artifacts with separate domains: The policy-wrapper phases are 0 for initiation, 1 for acceptance, and 2 for rejection. At resolution, the wrapper also checks that the registered VASP matches the hold’s recipient VASP binding commitment. The payload signature and payment-request signature are verified offchain; they are separate from the policy-wrapper signature. Registry updates use mip410/fi-update-auth, signed under the current messaging key and verified by the pool. See VASP controls for the digest and updateFi arguments. See MIP410 Key Derivation for key derivation and spend authorization, and Sending a shielded payment for the payment proof flow.

Digest coverage

TypeScript SDK

Use the canonical 0x7f typed-data builder and codec.

MIP410 API

Look up policy structs, proof calls, and state.

Settlement

Understand application settlement and chain finality.

Transactions

Review the outer envelope and admission rules.