Works best when
- A standing ruleset governs many actors who never individually signed it.
- Publishing the ruleset would teach an adversary how to evade it.
- Enforcement must happen before execution rather than as an after-the-fact attestation.
Avoid when
- The principal can pre-authorise each action, where a signed mandate is simpler.
- The policy is public anyway, where an ordinary on-chain allowlist suffices.
- The action itself needs hiding, which this pattern does not provide.
Post-quantum exposure
Risk · high- Vector
- UltraHonk verification is pairing-based over BN254 with KZG commitments, which a CRQC breaks. Forged proofs would let an attacker manufacture allow verdicts against any registered domain. Policy commitments themselves are hash-based and hold up better than the proof system that opens them.
- Mitigation
- Move the proving program to a hash-based system with no trusted setup. The reference implementation already carries an SP1 program alongside the Noir circuit, which is the practical migration route. See Post-Quantum Threats.
Visibility
| Actor | Sees |
|---|---|
| Counterparty | — |
| Chain |
|
| Regulator |
|
| Public |
|
Components
- Policy Domain: an operator that maintains a private ruleset and runs an off-chain policy engine.
- Policy Commitment: a hash of the ruleset, registered as a statement in an ERC-7812 Evidence Registry.
- Policy Root: the sparse Merkle tree root containing the current commitment, which the proof is evaluated against.
- Verdict envelope: agent identity, domain, policy root, action commitment, executor, expiry, nullifier, and decision. Every field is a public input.
- Guard: the on-chain contract that verifies a verdict and gates execution on it.
- Agent identity: an ERC-8004 Identity Registry token, which supplies the subject the verdict binds to.
Protocol
- operator Register a domain, commit the ruleset hash to the ERC-7812 registry, and publish the verifier address and program key.
- agent Propose an action and request a verdict from the domain's policy engine.
- prover Evaluate the action against the private ruleset and produce a proof binding the decision to the agent, the policy root, a commitment to the action, the permitted executor, an expiry, and a single-use nullifier.
- contract Recompute
actionCommitmentfrom the call about to execute, and reject any commitment supplied by the caller. - contract Check that the domain is active, the decision is allow, the executor is the caller, the verdict has not expired, the nullifier is unburned, and the policy root is acceptable.
- contract Verify the proof against the domain's program key, burn the nullifier, emit
VerdictConsumed, and execute. - operator Rotate the root as rules change, accepting superseded roots for a bounded window, with revocation taking effect immediately.
Guarantees & threat model
- Hides the ruleset from the chain, from relying parties, and from the agent being governed.
- Binds one verdict to one call through
actionCommitment, so a verdict cannot be replayed against a different action. - The executor check stops a third party observing a pending verdict and consuming it ahead of the intended executor.
- Threat model: the operator is trusted to author honest rules. A proof shows the ruleset was evaluated correctly, never that the ruleset is reasonable. A hostile operator can deny arbitrarily, or commit to a policy that permits everything, and no verifier can tell.
- Root rotation leaves a window in which a superseded policy still authorises actions.
- Out of scope: hiding the action, hiding which domain gated it, and hiding that a verdict was consumed.
Trade-offs
- Proving happens off-chain per action and adds latency to every gated call.
- On-chain cost is one proof verification plus a nullifier write.
- Denied actions never reach the chain, so a watcher who knows an agent was about to act can infer denial from silence.
- The
interfaceIdis a placeholder until the ERC leaves Draft, so ERC-165 detection is not yet stable. - Two hash functions coexist, keccak256 for on-chain digests and Poseidon in-circuit, which is a recurring source of commitment mismatch bugs.
Example
- A corporate card issuer maintains fraud rules that are deliberately unpublished, because a published rule is an evasion guide.
- A procurement agent proposes a payment. The issuer's engine evaluates it against the committed ruleset and returns an allow verdict with a proof.
- The Guard recomputes the action commitment, checks the envelope, verifies the proof, and releases the payment.
- Merchant, agent, and chain observers see that a payment was permitted under domain
Xat rootR. None of them learn a single rule. - Implementation status: a Noir allowlist circuit and generated UltraHonk verifier verify a real proof through
consumein an EVM test harness, across 23 passing Foundry tests. Nothing is deployed to a public network, and the contracts are unaudited.