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.
A second address can still write anything. That is the hole.
No judge chooses whether the matching replay settles.
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.
| caller | feedback 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:
| transaction | result | |
|---|---|---|
| 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.
reckn