Recknreckn
SEPOLIA EVIDENCE

ETHGlobal Tokyo 2026  /  ENS + Uniswap Foundation

Pay for work.
Not for a claim.

I want a world where work can be paid before we decide who to trust. Reckn replays a job. If the result matches, settlement gives the buyer one right to write a record. That record becomes a pass to a Uniswap pool.

One settlement. One record. One pass.Live on Sepolia
01 / workReplay the job
02 / settlementResult matches
03 / accessOne record opens one pool
no record refused 0xda60d7df…
settled record 1.0 in → 0.987158034 out 0xa40bb316…
record cleared refused again 0xce00489e…
01 / NO SELF-SCOREThe official registry blocks the agent.

A second address can still write anything. That is the hole.

02 / SETTLEMENT WRITESA replayed result gives the buyer one write.

No judge chooses whether the matching replay settles.

03 / THE RECORD IS USEDThe same Uniswap swap opens, then closes again.

Same sender. Same pool. Only the record changes.

This is not a screenshot. Your browser is calling Sepolia now and reports what comes back — including what is unfinished.

… connecting to Sepolia…

If this stays grey, the public endpoint is refusing us and every check below is unknown rather than false. Everything here can also be read with cast; the commands are in RECEIPTS.md.

1. The official registry refuses the agent's own feedback

… reading ERC-8004…

We registered agent 10518 in the official ERC-8004 reference deployment on Sepolia — not our own copy of it. ReputationRegistry 0x8004B663… guards giveFeedback with require(!isAuthorizedOrOwner(msg.sender, agentId)), so the agent scoring itself reverts Self‑feedback not allowed (that transaction). A second address is accepted.

That is the standard doing its job, and it is also the whole problem. The refusal only moves the question: now the record says whatever that second address says. Nothing made the second address tell the truth.

callerfeedback records for agent 10518
the agent itself 0xfa2582ec……
a second address 0xF81dFf68……

2. So the record is created by a settlement instead

… resolving the record through ENS…

A buyer funds an escrow and names the verifier. Anybody may settle it by handing over a proof that the job was re-executed and reproduced — there is no resolver, no owner, no key that decides. The same settlement grants the buyer, and nobody else, the right to write one ENS text record about that job. Then the right is destroyed.

Read back through UniversalResolverV2, not by calling our resolver directly:

…

The key names the name it belongs to, and that is not decoration. The deployed ENSv2 resolver derives a role's resource from the key alone — we measured agent.reckn.eth and victim.reckn.eth with one key returning one identical resource. A role is therefore never scoped to a name. Naming the name inside the key does not stop bytes being written onto somebody else's name; it stops them being read as that somebody's record.

3. The record is a pass to a Uniswap v4 pool

… asking the hook…

A beforeSwap hook 0x68116b80…0080 on the real Sepolia PoolManager reads the record inside the swap, synchronously, with no CCIP‑Read — a hook cannot go offchain and come back. Its address was mined so that uint160(hook) & ALL_HOOK_MASK == BEFORE_SWAP_FLAG.

Earning happens where the work happened. Spending happens here. The same swap, three times, with liquidity in the pool:

transactionresult
no record 0xda60d7df… refused
the record is written 0xd5610433… —
the same swap 0xa40bb316… 1.0 in, 0.987158034 out
the record is cleared 0x427ee98a… —
the same swap again 0xce00489e… refused

… asking the second pool…

There is a second pool, and you can trade in it. 0x95A466FE…0080 was settled and written by its buyer, the buyer closed its own window, and only then were both root roles destroyed. It has since been traded by an address that was never granted anything. The demo tokens mint to anyone.

It is not that the right is irrevocable. It is that the record a spent right wrote outlives the right, and outlives us.

Both refusals were re-simulated at their own blocks: the PoolManager's ERC‑7751 WrappedError carries target = this hook and reason = 0x43a7f347 NoSettledRecord. A failed transaction on its own only says something went wrong.

4. The last key, read live

… checking who still holds root…

This is the part a demo page normally leaves out. The account that is the agent also deployed this resolver and held root on it, and root overrides the per‑key roles everything above depends on — so while it held them, it could write its own record and open its own pool. The heading above and the three rows below are not written here. They are read from the chain on every load, which is why this section could contradict the rest of the page if it ever stopped being true.

can write the gate's record
the buyer of that job…
a stranger…
the agent itself…

What this page does not prove

The bytes are not proof‑derived. The settlement grants the key, not the value. A buyer can write reproduced under a job whose proof said failed. What a settlement creates is the right to write one record, not the record's contents — the contents are checkable by anyone against the escrow and the proof, and they are not enforced.

The hook does not identify the swapper. It asks whether a record exists and says reproduced. beforeSwap's sender is whoever unlocked the PoolManager, so everyone behind one router looks the same to it, and a second agent could trade behind the first one's record. We asked Uniswap and they answered: keep an allowlist of routers and call msgSender() on them. We are declining that. An allowlist is a party you have to trust, in the last place we had removed one — and our own build check fails on the owner it would need.

A role is scoped to the key, never to the name. Measured, and it is the resolver's behaviour rather than ours. We pin the adapter to one name and put that name inside the key, which makes a write onto a foreign name unattributable — not impossible. We asked ENS and the answer is better than ours: partition names across resolver instances, one per group of writers, because the resolver instance is the trust boundary. This deployment is already that in its smallest form — one resolver, one name.

Nothing here is mainnet, and nothing here is money. Sepolia, test tokens, and an escrow holding a mock USDC.

Check it without this page

Every transaction above is in a record generated from the chain, and a script checks in both directions that every link in the repository names a transaction the record holds and that every transaction the record holds is linked somewhere. The contracts: SettlementRecord.sol · RecordGatedHook.sol · RecknZkEscrow.sol. The one‑command run: bash tokyo-2026/scripts/join-sepolia.sh.

github.com/psyto/reckn · demo runbook · chain receipts