fix(vm): resolve function selectors with leading zero bytes - #708
Open
Jon-Becker wants to merge 1 commit into
Open
fix(vm): resolve function selectors with leading zero bytes#708Jon-Becker wants to merge 1 commit into
Jon-Becker wants to merge 1 commit into
Conversation
Function selectors whose first byte is `0x00` (e.g. `0x00aabbcc`) were silently dropped from decompilation. The dispatcher's `PUSH4` constant is solidified via `encode_hex_reduced`, which strips leading zero bytes (`0xaabbcc`), but `resolve_entry_point` matched `jump_condition.contains` against the un-reduced selector string (`00aabbcc`). The comparison never matched, the entry point resolved to 0, and the function was skipped. Match against the same reduced form the solidifier produces so these selectors resolve correctly, while all other selectors are unaffected. Add a regression test with a minimal two-selector dispatcher (`0x00aabbcc` + `0x11223344`) asserting both functions are recovered.
Contributor
❌ Eval Report for 6ca7ea8
|
Contributor
✅ Coverage Report for 6ca7ea8
|
Contributor
Benchmark for 6ca7ea8Click to view benchmark
|
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.
What changed? Why?
Observed failure. While decompiling an unverified Polygon contract (a
participant-linked, bot-like contract adjacent to Polymarket, selected from
PolygonScan; heimdall-cli v0.9.2 on ARM64), any externally-dispatched function
whose 4-byte selector begins with a zero byte (e.g.
0x00aabbcc) was silentlydropped from the output. Those selectors never appeared in the recovered ABI or
Solidity, so the contract's routing/dispatch logic was incomplete and could not
be trusted.
Root cause. In
resolve_entry_point(crates/vm/src/ext/selectors.rs), thedispatcher's
PUSH4constant is solidified throughencode_hex_reduced, whichstrips leading zero bytes (
0x00aabbcc→0xaabbcc). The matcher, however,compared
jump_condition.contains(selector)against the un-reduced selectorstring (
00aabbcc). The substring never matched, the entry point resolved to0, andfind_function_selectorsskipped the selector entirely. Only selectorswithout a leading zero byte were affected — which is why the bug was intermittent
and easy to miss.
Fix. Compare against the same reduced form the solidifier emits
(
encode_hex_reduced(U256::from_be_slice(&selector_bytes))). Selectors with aleading zero byte now resolve; all other selectors are byte-for-byte unaffected.
Notes to reviewers
crates/vm/src/ext/selectors.rs—resolve_entry_point: match the reducedselector form; added
encode_hex_reduced/U256imports.crates/core/tests/test_decompile.rs— regression test.How has it been tested?
test_decompile_leading_zero_byte_selector: a minimal syntheticdispatcher routing
0x00aabbcc(leading zero byte, previously dropped) and0x11223344(control). It fails before the fix (only11223344recovered) andpasses after (both recovered). Verified the same before/after behavior directly
via the CLI on the fixture bytecode.
cargo test -p heimdall-vm: 153 + 34 tests pass.cargo +nightly fmt --checkand
cargo clippy -p heimdall-vmare clean. RPC/address-based tests were notrun (no
RPC_URLin this environment).Limitations
failing dispatcher pattern (leading-zero-byte selector); the original
unverified contract is not committed, and no PolygonScan/RPC dependency is
added. This change only restores discovery of these selectors — it does not
claim to recover the contract's higher-level business logic.