I would like feedback on a draft ERC before I open a PR.
The one-line version. Every delegation standard I have found on the Standards Track is two-party: the party who consents is the party who benefits, and the party at risk is the party who signed. I want to standardize the case where those are different people, because that is the shape of consent to use someone’s data.
Disclosure: I am the founder of GenoBank.io, which builds a decentralized biobanking system in which patients grant researchers access to data about themselves, and this draft comes out of that work. The draft is deliberately domain-neutral: nothing in the normative text mentions health, genomics, or GenoBank.io, because the structure is not specific to any of them.
The problem
The case has three principals, and existing standards collapse the last two:
- a subject, the person whose data the grant concerns and whose assent it records
- a grantee, the party authorized to exercise the grant
- an agent, an optional principal that exercises the grant on the grantee’s behalf
In ERC-4907 and ERC-5006 an owner grants a time-boxed user role over their own token. In ERC-8226 a principal delegates scoped, capped authority to an agent over the principal’s own asset, with the mandate keyed (agent, principal). In every case the consenting party is the beneficiary. The case this standard addresses is structurally different: a subject consents to a grantee’s access to data about the subject, and the harm from an unauthorized act falls on someone who is not a party to the transaction at all.
Three gaps follow, none of which I could express with what exists:
1. The subject is not the beneficiary. ERC-8328 does model a subject, and so does W3C VC 2.0 with credentialSubject. What neither does is make a non-party subject’s withdrawal operative for a relying party at access time. ERC-8328 says this itself: it “does not define compliance policy… transfer restrictions”, and its OUTCOME_REVOKED is a recorded assertion that nothing consults.
2. The agent must be revocable separately from the human. Where an agent is modelled at all, it is modelled as an extension of the principal, so no two-party standard can say “this researcher retains access, but the tool they were using does not,” which is precisely the action an incident response requires when a model provider, an MCP server, or a session key is compromised.
3. Purpose is not enforced anywhere. Every regulatory-compliance ERC to date (3643, 7518, 8106, 8226, 8320) encodes securities vocabulary: accreditation, jurisdiction blocks, AML flags, transfer caps. A fund unit has no purpose limitation, so nobody needed one. Data does.
Why on-chain at all
This is the question I expect to be pressed on, and the answer has two parts.
For the instrument itself, a W3C Verifiable Credential is the better carrier and the draft says so. termsRef and purposeProfileRef are hashes of documents referenced from a credential’s normative termsOfUse. They are not a replacement for it.
The one thing that must not live in an issuer-controlled place is revocation status. A Bitstring Status List is fetched from an endpoint the issuer can rewrite, take offline, or backdate; a consensus-ordered revocation cannot be any of those.
That matters concretely rather than theoretically. The incumbent standard for credentialed access to controlled datasets is GA4GH Passports, and its own AAI profile states that a Visa Issuer “MAY provide tokens of this type without any revocation process”, defines exp as explicitly not a hard cutoff (“access is NOT necessarily removed by the exp timestamp”), and rate-limits the only active check: polling “MUST NOT be done more than once per hour per Passport Clearinghouse.” There is no revocation list and no push channel. Worst-case propagation of a withdrawn consent is bounded by token lifetime and an hourly poll.
So the claim is narrow and I want it judged narrowly: public, non-repudiable, consensus-ordered revocation of a grant whose subject is not its beneficiary. It is not a new identity system, not a new credential format, and not a compliance oracle.
Why not a profile of ERC-8226
ERC-8226 is the closest neighbour and I want to be precise about the difference rather than strawman it.
Its Mandate is keyed (agent, principal) and its caps are denominated in transfer quantity. Three things stand in the way of a profile:
- The principal is the beneficiary. There is no seat for a third person, and adding one changes the key.
- Compliance is checked at grant time only. Its own Security Considerations accept a race between revocation and enforcement, mitigated by an out-of-band freeze relay. For an irreversible disclosure, under regimes whose triggers are knowledge and ease of withdrawal, a grant-time check is not sufficient.
metadata, the only field where an instrument or a purpose could live, is expressly non-normative: implementations “MUST NOT rely on it for enforcement decisions.”
The two compose: an agent may hold an 8226 mandate over a payment asset and a grant under this spec over a data asset. I do not think that makes either a profile of the other.
Status
Draft ERC plus a reference implementation, deployed and verifiable:
| chain | address |
|---|---|
| Avalanche mainnet (43114) | 0xA04d20E6fB15A0939B08eb1cB88673f34051342c |
| Avalanche Fuji (43113) | 0x25d419259d7336a4d883808adc02a5F92520b2C0 |
| Sequentia (15132025, permissioned) | 0x473Cd8D24437c9321e2e0c32C7cC9F777f99d1A5 |
45 tests, mostly negative ones. The interesting assertions are that a sub-grant cannot exceed its parent on scope, ops, expiry, purpose or uses; that a claimed-but-unproven agent identity never satisfies an agent constraint; that revoking the agent leg leaves the human grant alive; and that revocation cost does not grow with the number of delegated children.
Before drafting this post I ran the spec and the implementation through an adversarial review from five independent perspectives: an EIP editor, a security auditor, a data-protection officer, a hostile competing-standards author, and an implementer working from the text alone. It produced 54 findings, 48 of which survived a verification pass. I fixed the 7 it classed as publication blockers. Two of those were cases where my own NatSpec asserted something the code did not do, and one was a live privilege escalation in the deployed contract. I mention this because the remaining items below are not modesty; they are a list I already have.
What I know is still weak
I would rather name these than leave them to be found.
The privacy section contradicts the data model. The Privacy rules say personal data MUST NOT be written on-chain in any form including hashed. The data model mandates address subject. The draft recommends a zero-subject profile where the subject is derived from an asset registry, but the published interface has no subjectOf hook, so that profile is not buildable as specified. Separately, if grants are represented as ERC-1155 tokens, the subject-side mint republishes the address that zeroing the field was meant to remove, and nonces is keyed by the raw address. I have not resolved this and it is the single thing I most want input on.
usesMax is a self-declaration. Only the grantee or agent advances useCount, via commitUsage. A grantee who never calls it holds an effectively uncapped grant. It binds contractually, not cryptographically, and the draft should either say so plainly or split checkAccess into a view and a state-changing consume.
The usage hash chain is under-specified. h_i = H(h_{i-1} || record_i) with no named H, no h_0, and no record_i schema. Two implementations cannot produce comparable chains. The draft still uses the word “completeness”, which is wrong: a hash chain gives tamper-evidence and ordering; it gives no protection at all against a party who simply declines to append.
Merkle leaf construction is unspecified (hash function and pair ordering), and a withdrawn leaf is not inherited by sub-grants, so per-datum withdrawal does not survive one delegation hop.
Four Status values have no setter or transition rule, and SUSPENDED is documented as reversible, which contradicts the no-reinstatement rule.
checkAccess authenticates only an on-chain caller. An off-chain relying party calling it via eth_call supplies from itself and gets no authentication whatsoever. Given that the deployment I describe in the Motivation is exactly an off-chain gateway, this needs either a signed-challenge companion or a much louder warning, and probably both.
RFC 8785 does not sort array elements, so the purpose profile canonicalization I specify does not produce a stable hash for the same semantic profile.
What I am asking
- Is the narrow claim actually unclaimed? I am asking specifically about a non-party subject’s withdrawal being operative at access time, not about three-party modelling in general, which ERC-8328 already does.
- Should the
opsbitmask be ERC-6617, or are fixed values right when a grant minted by one party is evaluated by another? - On the privacy contradiction above: is a
subjectOfresolver hook the right shape, or should the subject leave on-chain state entirely and live only in the off-chain credential? - Is there appetite for this as a standard at all, or is the correct outcome that it should be a VC profile with an on-chain status anchor and nothing more? I would rather hear that now than after a PR.
If the framing itself is wrong, that is the answer I would most like to have.
Links
Deployed reference implementation, byte-identical across all three (15,385 bytes runtime):
- Avalanche mainnet:
0xA04d20E6fB15A0939B08eb1cB88673f34051342c - Avalanche Fuji:
0x25d419259d7336a4d883808adc02a5F92520b2C0 - Sequentia (permissioned, chainId 15132025):
0x473Cd8D24437c9321e2e0c32C7cC9F777f99d1A5, readable athttps://seqrpc.genobank.app
Superseded instances from an earlier deployment remain live on all three chains and carry a
scope-containment bypass that this version fixes. They are not proxies and cannot be
disabled, so I am naming them rather than leaving them to be found:
0xA25543a0eDF4755d7C4f39207F8cF59C23173864 (mainnet),
0xEE53dAAf7AF86E47bc3155b0642c41a30F1A5d06 (Fuji),
0x6D6604eD95A46018a36C730614714f9586049C3D (Sequentia). Do not use them.
Full draft text follows in the next reply, so the thread is self-contained and does not
depend on a link staying alive.
