Conversation
File
|
| title: On-Chain Registry for ERC-7730 Clear Signing Descriptors | ||
| description: An open on-chain protocol-agnostic registry for ERC-7730 descriptors with EAS-backed attestations | ||
| author: Alex Forshtat (@forshtat) | ||
| discussions-to: https://ethereum-magicians.org/ |
There was a problem hiding this comment.
Please create a discussions topic on Eth Magicians linking to this PR
Co-authored-by: Andrew B Coathup <28278242+abcoathup@users.noreply.github.com> Co-authored-by: Alex Forshtat <forshtat1@gmail.com>
|
Have you seen my proposal here? ethereum/clear-signing-erc7730-registry#2577 If the schema updates, it's a lot of work to update these contracts too. |
Hello @PatrickAlphaC ! Yes, I have looked at this proposal briefly, and as far as I understand the release process outlined in it I would say these two proposals are complimentary. Will be happy to discuss these proposals in more detail! |
…cleanup, ERC-8176 alignment Specification and reference implementation fixes: * Require an EIP-712 registration signature binding contextIds and mirrorListId to the attester when a registration is relayed by a third party. Prevents front-running an attester's EAS delegated attestation to register it under attacker-chosen context IDs or mirror lists. Replay protection comes from binding the signed struct to the single-use EAS attestation signature, with no extra nonce state. Verified via ECDSA for EOAs and ERC-1271 for contract attesters; skipped when the attester submits the transaction directly. * Add permissionless clearRevokedEndorsements(attesters[], contextIds[][]) to remove slots whose backing attestation was revoked or expired directly on EAS. Skips still-valid and empty slots instead of reverting so a multi-attester watchdog sweep cannot be blocked by a slot changing state in flight; returns the number of cleared slots. * Require the active attestation to be revocable; an irrevocable one would permanently freeze its slots since replacement demands revocation. Require the attested data to be exactly 32 bytes. * Enforce the displaced-UID revocation check even when the revocations batch is empty; previously an active slot could be silently replaced without revoking the prior attestation. * Rename descriptorId to descriptorHash and define it by reference to the ERC-8176 hash computation (includes-resolved, RFC 8785/JCS canonicalized), replacing the contradictory raw-file-bytes wording. Wallets verify retrieved descriptors by recomputing this hash. * Fix the EIP-712 domain-separator context tag string diverging between the spec (domainseparator) and the implementation (domain-separator), which would have produced disjoint context IDs. * Align spec text with implementation behavior (revoke-then-attest order), remove stale updateMirrorList reference, add normative wallet requirements to verify attestation revocation and expiry per ERC-8176, and add 1271 to required EIPs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add resolveDescriptors(attesters[], contextIds[]) as the primary wallet-facing entry point. For every non-empty (attester, contextId) slot it returns the descriptor hash, the backing attestation UID with its expiration and revocation times read from EAS in the same call, and the attester's MirrorList contents. A wallet derives its candidate context IDs locally (contract key for calldata transactions, deployment and domain-separator keys for EIP-712 messages, factory keys for factories it supports) and completes the entire on-chain lookup in a single eth_call instead of three to five sequential ones. Remove getMirrorList(attester, descriptorHash): wallets get mirror data from resolveDescriptors, and indexers get it from MirrorListUpdated events combined with getMirrorListById. getDescriptors stays as the lightweight raw-slot primitive for on-chain callers, and getMirrorListById stays as the only standalone reader of published MirrorList contents, since MirrorListPublished only emits the ID. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document the approximate cost structure of populating the registry: ~400-450k gas per descriptor (dominated by the EAS attestation and the one-time MirrorList storage) plus ~50k per context ID, with a round reference point of 10,000 descriptors at two deployments each costing on the order of 5 billion gas (~50 ETH at 10 gwei). Notes the three properties that keep the cost manageable: one-time bootstrap with incremental re-attestation, idempotent MirrorList sharing saving subsequent attesters roughly a third, and linear scaling. Explicitly framed as order-of-magnitude estimates without enshrining current registry sizes or market prices. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The markdown-no-backticks rule rejects EIP/ERC number patterns inside backticks, which the full asset paths in link texts triggered. Use the bare file names as link text instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ual-flow MirrorLists Reduce per-descriptor registration gas by roughly 20% and improve attester operations: * Store only the EAS attestation UID per (attester, contextId) slot. The endorsed descriptor hash is already carried in the attestation's data, verified at registration time, and is read from EAS when queried, so it is never duplicated in registry storage. Saves one storage slot per context ID and removes a consistency invariant. The AttesterEndorsementUpdated event now carries the previous attestation UID, linking the supersession chain for indexers. * Replace the single-descriptor write function with a batched createDescriptorAttestations(DescriptorRegistration[], ...) call: attestations[0].data[i] is the active attestation for registrations[i], one merged EAS call covers the whole batch, and a single EIP-712 registration signature (nested ClearSigningRegistrationBatch struct) authorizes the entire release, reducing a multisig attester's signing ceremonies to one per release. Replay protection is unchanged: the batch is bound to the single-use EAS delegated attestation signatures. * Support two MirrorList flows per registration. Reference flow: a non-zero mirrorListId points to a list published by anyone via the batched publishMirrorLists, keeping mirror operation a separate role from attestation. Inline flow: mirrorListUris are published idempotently within the registration with mirrorListId required to be zero, making a first registration a single transaction. The registration signature always covers the effective MirrorList ID, which is safe because published lists are immutable and content-addressed. * Update the Rationale gas estimates to the new cost structure (~350-400k gas per descriptor plus ~25k per context ID; the 10,000 descriptor reference point drops to ~4 billion gas, about 40 ETH at 10 gwei). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The motivation entry now states the interoperability problem instead of describing the set mechanics. The expiration rationale no longer claims revocation is freshness-independent: a stale state view hides a recent revocation like any other registry update; the honest argument is that revocation adds no trust input beyond the state view wallets need anyway, while expiration needs a clock the target devices do not have. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop sentences duplicated in the Specification or the interface file: error-name revert bookkeeping, restated MirrorList properties, gas complexity analysis, and rhetorical summaries. Also remove a dangling cross-reference to a nonexistent ENS recommendation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop restatements of the data model comments, duplicate wallet verification requirements, event and nonce bookkeeping visible in the reference implementation, and cross-reference navigation notes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds deriveFactoryContextKeyId, deriveEip712DeploymentContextKeyId, and deriveDomainSeparatorContextKeyId plus a worked register/resolve example, since the walkthrough previously only covered contract.deployments even though the registry supports all four ERC-7730 context binding types. Also fixes leftover chainId/vaultContractAddress references left over from the contextId -> contextKeyId rename. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1. The 'schemaMajor' and 'formatId' names are confusing. Renamed to "descriptorSchemaMajor" and "attestationFormatId". 2. The 'attestationFormatId' but only EAS is declared. Provied an example ML-DSA based signature (artificial example). 3. There is no need to create atomic flows inside the registry. Removed 'revocations' and 'MirrorListRefs' from the registration flow. Atomicity can be achieved with externally batching the transactions. 4. Improve the README.md, provide examples for factory-based contexts.
… repo Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The external GitHub link and its erc7730-containing link text tripped markdown-rel-links and markdown-re-erc-dash. Switched to a plain, non-linked mention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
The commit 6ed9f3b (as a parent of 75a4342) contains errors. |
The descriptors for ERC-7730 "Clear Signing" are too big to be stored on-chain, but it does not mean we can't do anything about it and fall back to using Github as a registry.
The "registry" contract can store IPFS identifiers and EAS attestations for the descriptor files.
This approach closes the loop:
These four standards together create a full clear signing ecosystem that can actually address the security of signing Ethereum transactions of any non-trivial complexity.