chainId 143 and your contract address, then add it to the public registry.
What is clear signing?
ERC-7730 is a JSON format for describing how a wallet should render contract calldata and EIP-712 messages. The descriptor lives outside your contract. It maps functions, message types, and fields to labels and formatters a wallet can show before a user signs. The lookup key ischainId plus contract address, so Monad contracts do not need a Monad-specific version of the standard.
Without a descriptor, a wallet may only have raw calldata:
Why it matters for Monad
Users should not have to trust the site that assembled a transaction. A spoofed frontend can ask for one action while submitting another, and raw calldata gives most users nothing useful to inspect. Clear signing moves the important details into the wallet prompt: the action, recipient, amount, token, deadline, or any other field that matters for the call. Adding a descriptor does not require a contract change. You publish a JSON file, validate it, and submit it to the registry used by wallets that support ERC-7730.Monad mainnetchainIdis143(testnet10143). See Network Information.
Quickstart
Installuv first. The uvx command runs the erc7730 tool without a separate global install.
- Generate a starting descriptor from your ABI:
- Edit the intents and field labels so they read like English (see Editing the descriptor).
- Validate the descriptor:
- Preview how a wallet renders your fields at clear-signing.sourcify.dev.
- Open a PR to the ERC-7730 registry. CI validates it against the schema, a maintainer reviews, and once merged, supporting wallets can use it.
Keep the ABI inline
Thegenerate command embeds your contract ABI under context.contract.abi, which makes the descriptor self-contained. Leave it there: with the ABI in the file, the fields validate locally and nothing has to reach an explorer to make sense of the call.
While linting you may see a warning like this:
erc7730 also tries to fetch the deployed contract’s ABI from Etherscan to cross-check your display fields, and that request needs an ETHERSCAN_API_KEY. Set one (export ETHERSCAN_API_KEY=...) and lint passes clean; without it, that cross-check is skipped. Either way, keep the inline abi.
Editing the descriptor
generate gives you a skeleton with one entry per function. Most of the hand-editing is in two places:
intent: a short action label, such asApprove USDCorWrap MON. Keep it to 30 characters or fewer; some hardware wallet screens truncate longer strings.fields: the parameters you want users to review, each with alabelandformat.
format | Renders | Notes |
|---|---|---|
tokenAmount | 1,000 USDC | Applies decimals and ticker. Set a threshold with a message like Unlimited for max approvals. |
amount | Native MON with ticker | Reads the transaction value. |
addressName | A known name, otherwise a checksummed address | Use types (eoa, contract, token) and sources (local, ens). |
raw | A number, string, or address as-is | |
date | A readable date from a unix timestamp | Set encoding. |
#. for decoded calldata or message fields, $. for this descriptor’s own metadata, and @. for the transaction container, such as @.value.
Monad examples
These Monad descriptors are useful references when writing your own:- Permit2, the EIP-712 approval contract used across many dApps, at , added to the canonical Uniswap descriptor in registry PR #2611.
- The Monad staking precompile (delegate, undelegate, claim rewards) at , in registry PR #2589.
- Wrapped MON (wrap, unwrap, and ERC-20 calls) at .
How a wallet uses the descriptor
At a high level, a supporting wallet does this:- A user starts a transaction or signs an EIP-712 message.
- The wallet computes the 4-byte selector (or the EIP-712 type hash).
- It looks up the descriptor by
chainIdand address. - It checks that the descriptor’s
contextbinding matches the actual target. - It decodes the parameters with the ABI and resolves token and name metadata.
- It applies each field formatter and shows the
intentwith the formatted fields.

