AIP-4: Proof-Carrying Wash-Trading Enforcement
Defines ZK-proven wash-trading findings that reduce recognized-usage rewards in proportion to proven fabrication, anchored to a public permissionless block-hash store.
| Authors | Shahaf Antwarg (@kotevcode), Alexander Ludwig (@alexanderludwig) |
|---|---|
| Discussion | https://github.com/AntSeed/loop-proof/pull/1 |
| Created | Tue Aug 18 2026 00:00:00 GMT+0000 (Coordinated Universal Time) |
| Requires | AIP-2 |
Table of Contents
- Abstract
- Motivation
- Specification
- Rationale
- Backwards Compatibility
- Test Cases
- Reference Implementation
- Security Considerations
- Copyright
Abstract #
This AIP specifies how wash-trading findings become enforceable on-chain. A
finding is a proof-carrying claim: a zkVM guest program re-verifies raw
Base evidence (receipts and transactions, authenticated by Merkle-Patricia
inclusion proofs against block headers) and checks a fixed mechanical
predicate over it. The guest’s verification key is the rule; its public
journal contains the subject, the proven fabricated volume, the subject’s own
settled volume for comparison, a claim identifier, and the
(blockNumber, blockHash) pairs the evidence came from. An immutable,
ownerless registry contract on Base verifies the proof, authenticates every
journal block reference against the existing public Chainlink BlockhashStore
(0x78b69899C8cD252126cBB1A50171ec37286C3877), and permanently records the
proven volume. Policies installed through AIP-2’s hooks then reduce
recognized-usage points and withhold locked rewards in proportion to the
share of the subject’s own volume that was proven fabricated, making
wash-traded volume emission-ineligible.
Enforcement is deliberately keyed to a ratio rather than an absolute amount: a volume threshold in a public immutable rule would simply tell an operator how finely to split its activity across seller identities to stay beneath it, while a ratio makes such splitting counterproductive.
Because submission is permissionless and the record is permanent, the predicates specified here prove a conserved value loop — capital injected, volume settled, and capital returned, bound together at comparable scale and attributed to one funder through the protocol’s own cumulative accounting — rather than the existence of transfers between related wallets. The companion wash-trading detection AIP calibrates the predicate parameters against real network traffic before a registry is deployed.
There is no committee, no attestation, no optimistic challenge window, and no AntSeed-operated block-hash infrastructure: anyone can produce a claim for any covered period at any time, and nothing in the system requires scheduled maintenance. Historical block hashes outside EIP-2935’s 8,191-block window are obtained from the BlockhashStore, whose entries are correct by construction regardless of who writes them, and which anyone can extend permissionlessly.
Motivation #
AIP-2 makes recognized usage feed on-chain trust scores and ANTS emissions. That creates a direct incentive to fabricate volume: a seller funds sock-puppet buyers, routes deposits through hop wallets, settles channels against itself, and cycles the funds back. Off-chain detection of these patterns is straightforward; the hard problem is acting on a detection without introducing a trusted party. A finding that zeroes a seller’s rewards is an adversarial, high-stakes claim — if it rests on a multisig, committee vote, or company API, the whole trust system inherits that weakness.
The standing requirement is therefore: any finding that affects seller scoring MUST be proven, never attested. Two obstacles make this non-trivial:
- Evidence is historical. An enforcement period spans months of Base
blocks, while the EVM exposes block hashes only through the
BLOCKHASHopcode (256 blocks) and the EIP-2935 ring buffer (8,191 blocks, a few hours on a two-second chain). No predeploy, scheduled hardfork, or OP Stack mechanism reaches deeper history, and none is on the visible roadmap. - Enforcement must be permissionless and perpetual. Anyone MUST be able to construct and submit a claim at any future time without AntSeed’s cooperation, without a keeper cron staying alive, and without any party having pre-provisioned data for them.
A survey of existing infrastructure (see Rationale) found no live third-party service that meets both constraints. This AIP composes two things that do: custom zkVM predicates for the evidence, and an existing, unowned, widely-fed public contract for the historical block hashes.
Specification #
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Architecture overview #
off-chain | on Base
|
detector (indexers, heuristics) |
│ candidate claims |
▼ |
planner ── selects evidence blocks | Chainlink BlockhashStore
│ | (existing, unowned)
▼ | ▲ │
backfill script ── storeVerifyHeader ─────┼────────┘ │ getBlockhash(n)
│ | ▼
▼ | AntseedWashTradingRegistry
witness materializer ── MPT proofs | - zkVM verifier + pinned vkey
│ | - journal block-ref check
▼ | - permanent proven-volume record
zkVM guest ── predicate + journal ────────┼──────────────────►│
(proof via any prover / open market) | ▼
| AIP-2 policies (setPointsPolicy)
| points scaled by f(washRatio)
Only the registry and the points/claim policies are new deployments. The BlockhashStore already exists; the detector, planner, and prover are off-chain tooling with no trust role — a wrong or malicious off-chain component can only produce claims that fail verification.
Evidence authentication (common to all predicates) #
A guest receives, per referenced block: the RLP block header, and for each
referenced receipt or transaction an MPT inclusion proof against that header’s
receiptsRoot or transactionsRoot. The guest MUST:
- Verify every inclusion proof.
- Reject duplicate block, receipt, transaction, or log references.
- Reject evidence from reverted receipts.
- Reject evidence outside the fixed enforcement period.
- Commit
(header.number, keccak256(rlp(header)))for every referenced block to the journal.
Where a predicate attributes an action to an address (e.g. “the funder funded this buyer”), attribution MUST come from recovering the transaction signer, not from log topics alone.
Predicates that read protocol accounting state (the LEDGER witness below)
additionally receive, per referenced block, an MPT account proof against the
header’s stateRoot and a storage proof against the resulting account root.
The guest MUST verify both, and MUST bind the storage slot to the deployed
contract address it commits to. Because the header is already authenticated by
its hash, the same block reference covers receipts, transactions, and state
uniformly. Fetching these witnesses requires an archive-capable Base RPC;
this is an off-chain materialization concern with no trust role.
Predicates #
The guest program’s verification key is the authoritative definition of each predicate. Changing any constant produces a different vkey and therefore a different rule requiring a new registry. The parameters below are named with the constraints they must satisfy; their calibration against observed network traffic is produced by the companion wash-trading detection AIP.
Every predicate in this family proves the same thing: a conserved value loop. Fabricated volume is volume settled with capital that the same party put in and got back. The predicate therefore measures three magnitudes — capital injected, volume settled, capital returned — and flags only when all three are bound together in one circuit at comparable scale. Transfers between related wallets, by themselves, are never sufficient.
P0_CLOSED_LOOP — flags one seller S.
Roles: a funder F, the seller S, and a buyer cohort B of distinct buyer
addresses, bounded above by a witness-sizing limit. Evidence sets, all authenticated per Evidence
authentication:
FUND— transfers fromFcrediting each buyerb ∈ B, in any of three forms: a direct USDC transfer tob; aDeposits.deposit(b, …)call whose same-receipt USDC transfer fromFmatches the deposited amount; or a native transfer tob. Every funding transaction MUST be signed byF.SETTLE— successfulChannelSettled(channelId, buyer, seller = S, …)events on the deployed AntseedChannels contract withbuyer ∈ B.RETURN— a USDC path carrying value fromSback toF, either directly or through at mostH_maxintermediate hops, each hop authenticated and time-ordered.LEDGER— for eachb ∈ B, a proof of the protocol’s own cumulative deposit accounting forbat the period bounds (see Attribution below).
The predicate MUST hold:
- Measurement.
Σ SETTLEis the fabricated volume the claim establishes. The guest MUST commit this magnitude to the journal; it is the input to the proportional effect defined in Policy binding. The predicate defines no volume floor and no minimum cohort size beyond what conservation itself requires — a single funded buyer forming a conserved circuit is already a proven loop. Thresholds of this kind would only tell an operator how small to slice its activity. - Funding coverage.
Σ FUND ≥ α_fund · Σ SETTLE. The funder’s capital MUST account for the volume it is alleged to have fabricated. - Attribution. For each
b ∈ B, the capitalbsettled with MUST beF’s. This is established fromLEDGER: the increase inb’s cumulative protocol deposits over the period MUST be matched, withinε_ledger, by theFUNDevidence namingFas payer. Using the protocol’s own on-chain cumulative accounting as the completeness witness makes this anO(1)check per buyer against an authenticated state root, rather than a search over the buyer’s entire transaction history. - Ordering. Each counted settlement MUST occur strictly after the funding
that covers its buyer, and every
RETURNelement MUST occur after the earliest settlement it is claimed to close. - Return.
Σ RETURN ≥ α_return · Σ SETTLE, arriving atF. Where the return travels through intermediaries, each hop MUST forward at leastρ_hopof what it received and the path MUST complete withinT_path. Path length is bounded byH_maxonly so the guest can size its witness statically;H_maxMUST be set well above observed laundering topologies so that it is never the binding constraint. What qualifies a path is the per-hop retention and the end-to-end total reachingF— a conduit is a conduit whether it runs through two wallets or ten, and a rule that stops at a small fixed length is evaded by adding one more address. - Circularity.
F,S, andBMUST form one circuit: the same capital accounted in (2) is the capital returned in (5). WhereS == Fthe return leg is satisfied by identity, and requirements (1)–(4) still apply in full.
Parameters and their constraints: α_fund and α_return are coverage
fractions that MUST be near unity, since a loop that fabricates volume must
supply and recover substantially all of it; ρ_hop is per-hop retention,
likewise near unity; T_path bounds the end-to-end return; ε_ledger is the
tolerance on the ledger reconciliation in requirement (3); H_max is discussed
below. Every parameter is a ratio or a bound on evidence shape, never a
magnitude of volume, so no parameter tells an operator a size to stay under.
Values are fixed by the detection AIP.
P0_RECIPROCAL — flags both wallets A, B of one normalized pair, and
proves the same conservation in its circular form: a pair recycling one pool
of capital between them. Evidence: successful settlements in both directions,
plus LEDGER proofs for both wallets. The predicate MUST hold:
- Measurement. The combined settled volume between the pair is the fabricated magnitude and MUST be committed to the journal, per wallet.
- Directional volume reciprocity
≥ β— neither side is a net seller at scale. - Self-financing. Net external capital entering the pair over the period
MUST be at most
(1 − α_self)of the combined settled volume, established fromLEDGER. The pair MUST be shown to have settled its volume out of receipts from each other rather than out of capital raised elsewhere.
Parameters: β is the reciprocity fraction, high enough that ordinary two-way
trade does not reach it; α_self is the self-financing fraction and MUST be
near unity. Both are ratios; as above, the predicate sets no volume or count
floor. Values are fixed by the detection AIP.
Requirement (3) is what separates recycled capital from genuine two-way trade: two providers who buy from each other with independently earned funds inject external capital proportional to their volume and are therefore outside the predicate.
Journals #
Journals MUST be minimal: the subject(s); per subject, the proven fabricated
volume and the subject’s period-end settled volume read from AgentStats; a
claim identifier binding the claim to its subjects and evidence set; and the
sorted (uint64 blockNumber, bytes32 blockHash)[] array of referenced blocks,
ABI-encoded. Both volumes are on-chain because the effect is proportional to
their ratio and that ratio must be fixed at proving time (see Policy
binding); the claim identifier is on-chain so repeated submission of the same
claim is idempotent. Cohort membership,
intermediate arithmetic, and the evidence manifest stay off-chain; the chain
never duplicates predicate logic.
Block-hash anchoring: the Chainlink BlockhashStore #
The registry MUST authenticate every journal block reference by calling
getBlockhash(blockNumber) on the BlockhashStore at
0x78b69899C8cD252126cBB1A50171ec37286C3877 (Base mainnet) and requiring
equality with the journal’s hash. This contract is chosen for the following
properties, each independently verifiable against the deployed bytecode and
live chain state:
- Immutable and unowned. Its ABI is exactly four functions (
store,storeEarliest,storeVerifyHeader,getBlockhash); the verified source contains no owner, roles, proxy,delegatecall, orselfdestruct; both EIP-1967 proxy slots are zero. - Correct by construction, independent of the writer.
store(n)reads the hash from theBLOCKHASHopcode (Base consensus).storeVerifyHeader(n, header)accepts only a header whose keccak equals the already-stored hash of blockn+1, then stores that header’sparentHash— only the true header satisfies the check, so only the true hash can be stored. No caller, including a malicious one, can store a wrong hash. - Provenanced. The Base VRF v2.5 Coordinator listed in Chainlink’s
official documentation (
0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) returns this address fromBLOCKHASH_STORE(). The contract has shipped with Chainlink VRF since v1 and is fed continuously by VRF node feeders as a side effect of normal VRF operation. - Densely populated. Because the feeders run continuously, stored blocks recur throughout Base history at intervals measured in seconds of chain time, so an arbitrary evidence block is typically a short walk from an existing entry. Implementations MUST measure actual coverage for their period rather than assuming it; density affects backfill cost only, never correctness.
Backfill. Evidence blocks not yet stored MUST be backfilled before claim
submission by anyone (permissionlessly): walk storeVerifyHeader downward
from the nearest stored block above the target, supplying each intermediate
RLP header. Every walked block is stored permanently, so backfills accumulate
as shared public infrastructure. Density is a cost optimization, not a
dependency: in the degenerate case where no nearby block is stored, a
submitter calls store(n) on any block within the current 256-block window
and walks from there.
The registry MUST NOT depend on any AntSeed-operated block-hash
infrastructure. This AIP explicitly supersedes the previously planned
AntseedBlockhashKeeper (checkpoint cron) and any bespoke historical
checkpoint oracle: neither SHALL be deployed.
Registry contract #
AntseedWashTradingRegistry MUST be immutable and ownerless, constructed
with: the zkVM verifier address, the pinned guest verification key(s), the
BlockhashStore address, and the enforcement-period constants. It exposes:
function submitClaim(bytes calldata proof, bytes calldata journalData) external;
function washRatioBps(address subject) external view returns (uint16);
event SubjectProven(
address indexed subject,
bytes32 indexed claimId,
uint256 washVolume,
uint256 settledVolume,
address indexed submitter
);
submitClaim MUST: verify proof against the pinned vkey over journalData;
decode the journal; check every block reference against the BlockhashStore; and
record, per subject, the proven fabricated volume together with the
period-end settled volume the journal commits, clamping their ratio to at most
one. Records are permanent.
Because two claims against one subject may reference overlapping settlements, the registry MUST NOT sum their volumes — that would double-count evidence and overstate the penalty. It MUST instead retain the greatest proven ratio recorded for a subject. This never overstates what was proven, at the cost of understating when genuinely disjoint loops are proven separately, which is the correct direction of error under this AIP’s false-positive-first priority. A claim already recorded is idempotent.
Submission is permissionless; msg.sender is recorded for future bounty
attribution (out of scope here). A new rule, period, or predicate version is a
new guest and a new registry, switched in via AIP-2’s policy hooks — the
registry itself never upgrades.
Policy binding #
Enforcement is proportional to proven fabrication, measured as a share of the subject’s own volume — never keyed to an absolute amount. Define
washRatio(subject) = provenWashVolume(subject) / settledVolume(subject)
Both quantities MUST be measured from the same source in the same unit, so
that the numerator is by construction a subset of the denominator. The
deployed AntseedChannels contract already provides this: settle()
accumulates each settlement’s delta into AgentStats.totalVolumeUsdc,
readable via getAgentStats(agentId) — the identical quantity the predicate
counts from ChannelSettled. No new accounting contract is required for the
denominator.
AgentStats.totalVolumeUsdc is lifetime-cumulative and monotonic, so it MUST
NOT be read live at policy-evaluation time: doing so would make the penalty
depend on when it is evaluated and would let a subject dilute a proven ratio
by accumulating volume afterwards. The guest MUST instead read that storage
slot at the enforcement period’s end block through the same state-proof
machinery used for the LEDGER witness, and commit the value to the journal
alongside the proven volume. The ratio is then fixed at proving time,
deterministic, and permanent.
Two edge cases MUST be handled explicitly. AgentStats accrues only when the
seller has a non-zero staked agentId, so a subject may have a zero or
partial denominator; and a subject whose settlements predate its identity may
yield a numerator exceeding the denominator. In both cases the ratio MUST
clamp to 1 rather than revert or divide by zero — a subject with no recognized
volume has no points to scale in any event.
The ratio is the quantity the policies act on:
- Points policy: recognized-usage points are scaled by
f(washRatio), wherefis monotonically decreasing withf(0) = 1, reaches zero at a ratioθabove which the subject is treated as a wash operation outright, and is superlinear belowθ— the loss MUST exceed the fabricated amount itself, or fabricating is a free roll whose expected value stays positive whenever detection is uncertain. - Seller claim policy: locked reward pools are withheld on the same
schedule, and fully frozen at or above
θ. The wash check takes precedence over any inner vesting policy.
f and θ are fixed by the detection AIP alongside the predicate parameters.
This construction has no threshold to structure beneath. Splitting a fabricated
volume across many seller identities does not reduce exposure — it raises it,
because each identity then carries a high washRatio against its own small
recognized volume, while the same fabrication concentrated in one high-volume
identity would dilute. Conversely a large, mostly honest seller is not
destroyed by a small proven loop, which keeps the permanent penalty
proportionate to what was actually proven.
Proving #
The predicate guests MAY be built for any zkVM that has an immutable verifier deployed on Base (both the RISC Zero verifier router and the SP1 verifier gateway qualify); the choice is pinned per registry at deployment. Proof generation is permissionless in practice via open proving markets (e.g. Boundless, Succinct Prover Network) or local CPU proving; nothing in this specification depends on who proves. Guest builds MUST be reproducible so any party can independently derive the pinned vkey from source.
Rationale #
Why proofs and not attestation. A committee or multisig attestation was explicitly rejected: it reintroduces exactly the trusted party the trust system is meant to remove, and a permanent, seller-poisoning flag is the worst possible place for one.
Why the predicate proves conservation. Submission is permissionless and a flag is permanent, so the design assumes the claimant is adversarial and chooses the funder, the cohort, and the evidence. Under that assumption the only durable defense is to require the claim to exhibit a property that honest activity cannot accidentally satisfy. Value conservation is that property: an honest seller’s volume is settled with capital its buyers raised independently, so no single party can show funding coverage, attribution, and proportional return at the scale of that volume. A fabricated loop must show all three by construction, because that is what it is. Anchoring the predicate to conserved magnitudes rather than to the existence of transfers is what makes the flag safe to make permanent.
Why the effect is a ratio and the predicate has no volume floor. Any
absolute threshold in a public, immutable rule is an instruction: it tells an
operator exactly how small each unit of its activity must be to escape. A floor
on fabricated volume is escaped by splitting one operation across several
seller identities, each sized beneath it — and identities are cheap relative to
the emissions at stake. Ratios have no such edge to sit under. Measuring
proven fabrication against the subject’s own recognized volume inverts the
incentive: fragmenting an operation raises each fragment’s ratio, because the
fabricated volume is being divided by a correspondingly smaller honest base,
so the fragments are penalized harder than the whole would have been. The same
measure keeps the penalty proportionate in the other direction, so that a
mostly honest seller is not permanently destroyed by one small proven loop —
which matters because the record is permanent and submission is open to
anyone. Superlinearity below θ is what stops proportionality from becoming a
free roll: if the penalty merely cancelled the fabricated amount, the expected
value of fabricating would remain positive under any detection probability
below one.
Why return-path length is not a threshold. The rule is public and
immutable, so any constraint an adversary can satisfy by adding one more
wallet is not a constraint at all — it is a published evasion recipe with a
gas-fee price. Path length is such a constraint; per-hop retention and
end-to-end conservation are not, because they bound the value that must
survive the trip rather than the number of addresses it visits. The only
genuine reason to bound length is that a longer permitted path gives more
opportunity for an unrelated sequence of honest payments to coincidentally
form a value-preserving chain ending at an address the claimant nominates as
the funder. That risk is already suppressed by requiring each hop to preserve
ρ_hop of the amount within one bounded window: chains of independent
economic activity do not hold value to a near-unity fraction step after step,
while conduits do. H_max is therefore set by witness sizing and coincidence
margin, generously, and calibrated with the other parameters.
Why protocol accounting supplies completeness. Attribution (requirement 3)
is a statement about all of a buyer’s funding, which a search over evidence
can never establish — absence of evidence is not evidence of absence. Rather
than proving completeness by walking every block in the period, the predicate
reads the protocol’s own cumulative per-buyer deposit accounting at the period
bounds through authenticated state proofs. The contract’s counter is already a
complete summary of what entered, so one storage proof per buyer replaces an
exhaustive history search: O(1) witnesses instead of O(blocks), with the
same guarantee. This is the reason state proofs are in scope alongside receipt
proofs, and why the enforcement period is bounded — the bounds are where the
ledger is read.
Why the Chainlink BlockhashStore and not bespoke infrastructure. The obvious alternative is to prove the block hashes ourselves: walk the parent-hash chain from an EIP-2935-reachable anchor back across the period in zkVM epochs, aggregate the epoch proofs recursively, and commit the result to a purpose-built accumulator oracle. An earlier iteration did exactly that. It was correct, and it dominated both the code size and the proving cost of the whole system — for a fixed range it could never extend, and requiring maintenance that would outlive whoever set it up.
The alternatives fall into classes, each disqualified structurally rather than incidentally. This survey is point-in-time and SHOULD be repeated before deployment, but the structural reasons are durable:
- Native chain mechanisms. Neither the OP Stack nor announced hardforks expose block hashes beyond the EIP-2935 window; cross-chain message primitives carry short expiry windows unsuited to historical evidence.
- ZK coprocessors. The projects that marketed historical receipt/event proving have largely shut down, pivoted away, or do not serve Base; those still operating route proving through their own infrastructure, and their low-cost modes interpose a staked committee.
- Third-party block-hash accumulators. The architecture is right, but deployed instances on Base carry no accumulated data and gate their off-chain proof path behind an admin-settable registry.
- Managed event-proving services. Each substitutes an operator signature, validator set, or hosted API for a proof — placing a trusted party exactly where this AIP requires math — and several cannot prove logs at all.
- Deploy-time pinned root (compute the period’s block hashes off-chain, pin a Merkle root in the constructor). Cheap and publicly re-derivable, but establishing the root is a one-time privileged act by the deployer, which violates the anyone-at-any-time requirement.
The BlockhashStore is the remaining option and dominates: it already exists, carries no owner or writer trust, has long-standing audit exposure as VRF infrastructure, is fed continuously by economically unrelated actors, and any gap can be closed permissionlessly by whoever needs it. Adopting it removes the accumulator, the checkpoint oracle, the keeper cron, and the recurring proving cost, and replaces them with a one-time backfill whose cost is ordinary Base gas proportional to the walk length.
Why the walk-based fallback still matters. The store’s density is an
empirical observation, not a guarantee. The specification therefore defines
correctness in terms of store + storeVerifyHeader semantics only, which
hold even if VRF activity on Base ceased permanently.
Parameter calibration. The α, β, and ρ parameters set where honest activity ends and a proven loop begins, so they are calibrated empirically rather than chosen here: the detection AIP measures funding-coverage and reciprocity distributions across real network traffic and fixes values that leave observed honest behavior outside the predicate with margin. Because the values compile into the guest and thus into the vkey, calibration MUST complete before a registry is deployed and bound to a live policy.
Fixed-period constants. Baking the period into the guest makes each registry a closed, auditable, one-shot rule (“vkey = rule”) at the cost of redeploying per period. This is intentional: an open-ended rule would need upgradable thresholds, which reintroduces governance over findings.
Backwards Compatibility #
Purely additive on the protocol side; no wire-format or metadata changes.
Contract-side, enforcement activates through AIP-2’s existing
setPointsPolicy / seller-claim-policy hooks — recognized-usage aggregates
already on-chain are unaffected, and sellers with no proven volume see no behavioral
change. The previously planned keeper/checkpoint-oracle components are
superseded before ever being deployed, so nothing is deprecated on-chain.
Test Cases #
The reference predicate library carries native (non-zkVM) tests that MUST
pass for any implementation: tampered receiptsRoot/transactionsRoot
rejection, duplicate evidence rejection, reverted-receipt rejection,
funding-before-settlement ordering, exact threshold boundaries for every
parameter, signer-recovery attribution, state-proof binding to the committed
contract and slot, and period-window enforcement.
Predicate tests MUST include vectors that the predicate REJECTS, covering the
honest shapes nearest the boundary: funding present but below α_fund of the
settled volume; funding covering the volume but with no proportional return;
a buyer whose ledger delta exceeds the funder-attributed amount by more than
ε_ledger; a seller that pays rebates to buyers it also serves without a
conserved circuit; and a reciprocal pair whose settled volume is matched by
external capital entering the pair. Registry tests MUST cover: valid proof with
correct block refs accepted; valid proof with one journal hash absent from the
BlockhashStore rejected; valid proof with a mismatching stored hash rejected;
replayed claims idempotent; records irrevocable; a second claim against the
same subject retaining the greater proven volume rather than summing.
Policy tests MUST cover the ratio semantics: that f(washRatio) is applied
against the subject’s own settled volume rather than an absolute amount; that a
fabricated volume split across several seller identities yields at least as
much total penalty as the same volume concentrated in one; that a subject at or
above θ receives zero points and a full pool freeze; that settlement activity
occurring after the enforcement period does not change an already-recorded
ratio; and that a subject with a zero or partial AgentStats denominator
clamps to a ratio of one instead of reverting.
Reference Implementation #
- Evidence-authentication and proving tooling:
AntSeed/loop-proof#1. Its
MPT inclusion, signer-recovery, journal-encoding, and planner machinery are
adopted as-is and extended with the state/storage-proof verification the
LEDGERwitness requires. Itscheckpoint/accumulator workspace and oracle are superseded by the BlockhashStore anchoring specified here. Its predicate constants are superseded by the conserved-loop requirements above, with final values from the detection AIP. - Registry and policies: the
AntseedWashTradingRegistry/ points-policy / seller-claim-policy line of AntSeed/antseed#895, withblockhashSourcebound to the BlockhashStore.
Security Considerations #
Framing resistance. A record permanently reduces a seller’s rewards and
withholds locked pools in proportion to the volume proven against it, and
anyone may submit a claim, so the security goal is that no party can satisfy
the predicate against a seller that did not wash-trade. Proportionality also
bounds the damage of any residual framing: an attacker who could establish a
loop over a small slice of a large honest seller’s volume moves that seller’s
ratio slightly, rather than destroying it outright. The conserved-loop requirements are what deliver this: an attacker
targeting an honest seller would have to supply capital covering α_fund of
that seller’s real settled volume, show through the seller’s buyers’ protocol
ledgers that this capital — and not the buyers’ own — financed that volume,
and then demonstrate α_return of it coming back. The cost of framing
therefore scales with the victim’s genuine volume and cannot be met at all
while the buyers’ ledgers show independent funding, which is the honest case.
Small transfers to a seller’s buyers, rebates paid to one’s own customers, and
mutual trade between two providers are all outside the predicate by
construction.
An unproven loop (false negative) is the milder failure: fabricated volume keeps earning until a later predicate version catches it. The design accordingly prioritizes false-positive resistance over coverage, and parameter calibration (Rationale) resolves the remaining margin empirically.
zkVM soundness. The system’s integrity reduces to the soundness of the chosen proof system and the correctness of the pinned verifier contract on Base. Reproducible guest builds are REQUIRED so the vkey is independently derivable; the registry pins both verifier and vkey immutably.
BlockhashStore assumptions. (1) Header format: storeVerifyHeader
hard-codes the RLP layout of headers (parentHash at a fixed offset of an
0xf9-prefixed list). A future Base hardfork changing header serialization
would break new backward walks until a successor store exists; hashes already
stored, including any period fully backfilled beforehand, are unaffected. (2) Reorged entries: store(n) reads the sequencer chain; a
hash stored in the instant before an unsafe-head reorg could persist as an
orphan entry, and an attacker holding the orphan header could extend fake
lineage below it via storeVerifyHeader. Mitigations: any wrong entry is
correctable by anyone (re-walking from a canonical stored block overwrites,
and writes converge to the canonical value); claim submitters SHOULD
cross-check referenced entries against independent RPCs before submission;
evidence in practice is weeks-to-months old and L1-finalized, where orphan
headers for the referenced heights do not exist. The registry only ever
reads the store, so a bad entry can at worst make a specific claim
submittable/unsubmittable until corrected — it cannot corrupt an honest
proof’s meaning, because the proof binds the true header contents.
Liveness. No component requires scheduled operation. If Chainlink VRF
activity on Base stopped, walk gaps grow but self-service store() within
the 256-block window keeps the system usable by any submitter, forever.
Sybil / griefing. Claim submission is permissionless; invalid proofs revert and cost only the submitter. Duplicate valid claims are idempotent. Backfill griefing is impossible (writes cannot store wrong values) — at worst an attacker wastes their own gas storing blocks nobody needs.
Detector compromise. The off-chain detector, planner, and prover are untrusted by construction: they can withhold claims (censorship is bounded by permissionless submission from anyone else) but cannot cause a false record.
Copyright #
Copyright and related rights waived via CC0.