r/CryptoTechnology • u/Unable_Tackle_1255 • 1h ago
A method for checking whether an abandoned contract actually owes you money, and two pools that fail it
Public indexes map hundreds of thousands of addresses to "claimable" balances in dead protocols. Almost none of those numbers are checked against the contract that would pay them, and three failure modes recur.
Token counts labelled as ETH. One 2016 index lists 81,295 "ETH" for 4,836 addresses in a DAO wrapper. The wrapper does hold 81,287 ETH, but the top listed holder has 10,200 DAO tokens, not 10,200 ETH, and withdraw() reverts for that address. The file's own header says balance_source: token.
A getter that does not answer. One game contract is indexed at 163.42 ETH for its top holder; balanceOf(0x0, holder) returns zero. The pool holds 2,424 ETH, so the money is real and the address mapping is wrong.
A payout that is not the getter. Another indexed 141.97 ETH for its top holder, while the contract's own curve function returns 87.83 ETH. A token count was priced as if 1:1.
The method that catches all three, in order:
- Denomination. Only eth-sourced balances count as ETH. Token, weth and vault sources need a per-pool rate and must never be summed into an ETH total.
- Selector provenance. Pull PUSH4 constants out of the deployed runtime bytecode and match them to signatures. Do not trust an ABI, and do not trust an index's stated claim path.
- Getter read. Ask the contract what it owes a specific address.
- Claim simulation. eth_call the actual withdrawal from the holder's address. A revert means there is nothing collectable there, whatever the index says.
- Executor. Decide whether the claim is owner-only (pays msg.sender) or third-party (anyone can trigger payout to the registered recipient, as with merkle airdrops and bridge finalisations). This single axis decides whether a public-good claimer is even possible.
Run against a 2020-era exchange contract, this verified a pool holding 15,673 ETH across 119,430 addresses, with a 946 ETH top holder whose withdrawal simulates cleanly at 42,077 gas, using a different claim selector than the better-known EtherDelta-style contract it resembles.
The uncomfortable part is economics, not cryptography. Where the claim pays msg.sender, no relayer or incentive contract can collect for someone else. Of the 400 largest holders, 97% signed a transaction historically but only 4.5% have signed one in the last year. Chain state cannot distinguish a lost key from indifference, and a lost key makes the balance permanently unrecoverable.
I have a read-only checker that runs the whole read in one call and prints the exact transaction per claim. Not linking it here given the self-promotion rules - comment or message me and I will send it with the raw JSON-RPC body so you can replay it against your own node.