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

# Signing and Typed Data

> EIP-712 domains, type strings, digest boundaries, and authorization rules on Metal

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:

```text theme={null}
keccak256(0x1901 || domainSeparator || structHash)
```

## MIP20 `0x7f` transaction

| Domain field | Value |
| - | - |
| `name` | `"Metal"` |
| `version` | `"1"` |
| `chainId` | Transaction chain ID |
| `verifyingContract` | `0x0000000000000000000000000000000000000f4C` |
| Primary type | `MIP20Tx` |
| EIP-2718 type byte | `0x7f` |

```text theme={null}
MIP20Tx(
  uint256 chainId,
  uint256 nonce,
  uint256 maxPriorityFeePerGas,
  uint256 maxFeePerGas,
  uint256 gasLimit,
  address to,
  uint256 value,
  bytes data,
  address gasToken,
  bytes32 authorizationListHash
)
```

| Field | Hashing rule |
| - | - |
| `to` | Contract creation hashes `address(0)` |
| `value` | Must be `0` |
| `data` | Struct hash includes `keccak256(data)` |
| `authorizationListHash` | `keccak256(rlp(authorization_list))` |
| `gasToken` | Exact allowlisted MIP20 address |

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.

```text theme={null}
TransferWithAuthorization(
  address from,
  address to,
  uint256 value,
  uint256 validAfter,
  uint256 validBefore,
  bytes32 nonce
)

ReceiveWithAuthorization(
  address from,
  address to,
  uint256 value,
  uint256 validAfter,
  uint256 validBefore,
  bytes32 nonce
)

CancelAuthorization(
  address authorizer,
  bytes32 nonce
)
```

| Function | Relayer rule |
| - | - |
| `transferWithAuthorization` | Any account may submit |
| `receiveWithAuthorization` | `msg.sender` must equal `to` |
| `cancelAuthorization` | Any account may submit |

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:

```text theme={null}
Poseidon2(domain_tag, public_input_0, ..., public_input_n)
```

| Operation | Domain tag | Signed public inputs |
| - | - | - |
| Shield | `mip410/auth/shield` | Chain, pool, note commitment, amount, asset, depositor, shield timestamp, sanctions root |
| Initiation | `mip410/auth/initiation` | Chain, pool, commitment root, two input lock IDs, payment effect hash, recipient VASP binding commitment, nonce, deadline, payload commitment, sanctions root |
| Unshield | `mip410/auth/unshield` | Chain, pool, asset, amount, destination, commitment root, two nullifiers, two input lock IDs, change note commitment, sanctions root |

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:

| Signature | Signed fields after the domain tag | Verified by |
| - | - | - |
| Policy authorization, `mip410/wrapper-auth` | Chain, pool, payment effect hash, phase, payload commitment | Policy-wrapper circuit, under the messaging key in the VASP's registry leaf |
| Payload attestation, `mip410/payload-auth` | Payload commitment | Recipient VASP during offchain intake |
| Payment request, `mip410/request-auth` | Request version, diversified address, VASP identifier, registry index, expiry, and record thresholds | Sender before preparing initiation |

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](https://docs.metalntwx.com/reference/assets-and-payments/mip410.md#the-vasp-tree) for the digest and
`updateFi` arguments.

See [MIP410 Key Derivation](https://docs.metalntwx.com/reference/privacy/key-derivation.md#spend-authorization)
for key derivation and spend authorization, and
[Sending a shielded payment](https://docs.metalntwx.com/learn/mip410/shielded-payments.md) for the payment proof flow.

## Digest coverage

| Authorization | Bound data |
| - | - |
| MIP20 `0x7f` | Transaction fields, calldata, gas token, and authorization list |
| MIP20 ERC-3009 | Sender, recipient, amount, validity window, and nonce |
| MIP410 wallet authorization | Operation domain and every public input of the shield, initiation, or unshield statement |

> [card] [TypeScript SDK](https://docs.metalntwx.com/reference/typescript-sdk.md)
>
> Use the canonical `0x7f` typed-data builder and codec.

> [card] [MIP410 API](https://docs.metalntwx.com/reference/assets-and-payments/mip410.md)
>
> Look up policy structs, proof calls, and state.

> [card] [Settlement](https://docs.metalntwx.com/reference/network-fundamentals/settlement.md)
>
> Understand application settlement and chain finality.

> [card] [Transactions](https://docs.metalntwx.com/reference/network-fundamentals/transactions.md)
>
> Review the outer envelope and admission rules.


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