test: diagnose transient batch fund failure on Tempo#21
Open
test: diagnose transient batch fund failure on Tempo#21
Conversation
The Tempo batch TX (0xedf034...ac94ae) deploys the escrow at 0x7e97...b995 but sends the subsequent approve + fund calls to 0xd69b...d2aa, which has no code. EVM CALL to a codeless address succeeds silently, so the batch doesn't revert but the escrow is never funded. Root cause is upstream in the batch construction code which pre-computes the wrong target address for post-deploy calls. The obfuscated fund() selector (0x49364cd4) and dispatch logic are correct — confirmed via eth_call on the live escrow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Tempo testnet, escrow funding intermittently fails with
"Contract is not funded"despite the batch transaction succeeding. The node logs show:Failing TX:
0xedf034...ac94aeRoot Cause
The batch transaction has 3 steps:
0x7e97...b9950xD69B...D2Aa0x49364cd4)0xD69B...D2AaThe escrow deploys correctly at
0x7e97..., but the approve and fund calls target0xD69B...— an address with zero code. In the EVM, a CALL to a codeless address succeeds silently (returns empty data, near-zero gas). So the batch doesn't revert, but fund() never executes. The escrow remains unfunded.The obfuscation is not the issue — the obfuscated fund selector
0x49364cd4is present in the deployed dispatcher and routes correctly. The original selector0xa65e2cfdis absent as expected post-obfuscation.The bug is upstream in the batch construction code (nomad_enclave), which pre-computes the escrow address for post-deploy calls and gets it wrong.
0xD69B...does not match any CREATE nonce (0–200) from the sender0xA790...BBaD, ruling out a simple off-by-one.Cross-TX Verification
Comparing a successful batch against the failing one confirms the root cause:
0x8bff4e...(success)0x7720...5c9e0x7720...5c9e0x7720...5c9e0xedf034...(failure)0x7e97...b9950xD69B...D2Aa0xD69B...D2AaWhen the batch targets the correct address, it works. When wrong, silent no-op.
What We Tested (29 tests)
H1 — Bytecode & selector verification (3 tests)
fund(uint256,uint256)selector0xa65e2cfdexists in deployed bytecodeH2 — msg.sender context in batch (3 tests)
H3 — Lenient batcher swallows reverts (2 tests)
H4 — Batch reverts after fund (2 tests)
H5 — No-op token (1 test)
H6 — Non-compliant token (2 tests)
H7 — staticcall (eth_call) (1 test)
H8 — Batch targets wrong address (ROOT CAUSE) (3 tests, using real on-chain values)
testCallToEmptyAddressSucceeds: Calling0x49364cd4(723471, 100000000)on0xD69B...returns success with empty data — the EVM behavior that enables silent failuretestExactTempoFailure_WrongAddressBatch: Full reproduction — deploy escrow, approve + fund to wrong address, escrow stays unfundedtestObfuscatedFundWorksAtCorrectAddress: Same amounts, same token — fund() works when called at the right addressBaseline & edge cases (9 tests)
On-chain constants used
All H8 tests use verified values from the failing TX:
0x20C0000000000000000000000000000000000000(PathUSD)0x7e9798a62b42D97fb05b9e092a9A2117FA3fB9950xD69B8fC5D21819A713fDE3e051C97e1Cb09BD2Aa0xA79045285379f02ad505D7338523843D3A73BBaDreward=723471,amount=1000000000x49364cd4