Skip to content

fix: STATICCALL bypasses oracle access detection in MiniRex#183

Merged
Troublor merged 3 commits intomainfrom
william/fix/staticcall-oracle-detection
Mar 9, 2026
Merged

fix: STATICCALL bypasses oracle access detection in MiniRex#183
Troublor merged 3 commits intomainfrom
william/fix/staticcall-oracle-detection

Conversation

@Troublor
Copy link
Collaborator

@Troublor Troublor commented Mar 8, 2026

Summary

STATICCALL to the oracle contract incorrectly triggered oracle access detection in MiniRex. This PR fixes the spec gate so STATICCALL detection only activates in Rex+.

History

v1.0.1 (MiniRex): Oracle detection lived inside the call instruction handler (instructions.rs), so only the CALL opcode triggered it. CALLCODE, DELEGATECALL, and STATICCALL naturally bypassed detection since they had their own separate instruction handlers without oracle checks. This was the correct MiniRex behavior per spec.

v1.1.0: Commit 723fed6 ("refactor: move oracle access tracking to frame level (#86)") moved oracle detection from the CALL instruction handler into frame_init, which intercepts ALL call types (CALL, CALLCODE, DELEGATECALL, STATICCALL). The refactor checked call_inputs.target_address against the oracle address — this works correctly for CALL (detected) and for CALLCODE/DELEGATECALL (not detected, since target_address is the caller's address for those schemes). However, STATICCALL sets target_address to the called address (oracle), so it became incorrectly detected in MiniRex without a spec gate. The intent was for Rex to add STATICCALL detection, but the refactor applied it to all specs.

Fix

Gate oracle detection in frame_init on CallScheme:

  • Call → always detected (MiniRex+)
  • StaticCall → detected only in Rex+ (fixes the missing spec gate)
  • CallCode / DelegateCall → never detected (they execute in the caller's state context, not the oracle's)

Other changes

  • MiniRex tests (tests/mini_rex/oracle.rs): 3 tests — STATICCALL (not detected), DELEGATECALL (not detected), CALLCODE (not detected)
  • Rex tests (tests/rex/oracle.rs): 3 tests — STATICCALL (detected), DELEGATECALL (not detected), CALLCODE (not detected)
  • Spec fix (specs/MiniRex.md): Correct section 2.8.3 which listed all four call types as triggering oracle detection — now documents only CALL, with explanation of why the others are excluded

Test plan

  • cargo test -p mega-evm --test mini_rex -- oracle — all 22 oracle tests pass
  • cargo test -p mega-evm --test rex -- oracle — all 3 new oracle tests pass
  • cargo test -p mega-evm — full suite passes

Troublor added 2 commits March 8, 2026 22:31
In MiniRex, the oracle access detection in frame_init incorrectly
triggered for STATICCALL because it only checked target_address
(which equals the oracle address for STATICCALL). Rex intentionally
adds STATICCALL to the detection path.

Gate STATICCALL oracle detection on Rex+ via CallScheme check.
Add tests for CALLCODE/DELEGATECALL/STATICCALL oracle detection
in both MiniRex and Rex specs. Update MiniRex spec to match.
@Troublor Troublor requested a review from RealiCZ March 8, 2026 14:42
@RealiCZ
Copy link
Contributor

RealiCZ commented Mar 9, 2026

LGTM

Replay safety concern: This commit changes MiniRex semantics (STATICCALL to oracle no longer triggers detection). Since MiniRex is a stable, already-activated spec on mainnet, this could break replay if any transaction during the MiniRex window actually triggered STATICCALL oracle detection under the post-refactor code.

Verification result: safe. I checked the mainnet MiniRex window (chain 4326, block 1 to 2054928, ~8 hours from genesis to Rex activation at timestamp 1764851940):

  • Every block contains exactly 1 transaction, almost all are L1 deposit transactions (0xdeaddead... → L1Block predeploy).
  • ~546 user transactions total (estimated from 1% sampling), consisting of self-transfers, LayerZero cross-chain calls, Uniswap swaps, bridge operations, and contract deployments.
  • Zero direct calls to the oracle contract.
  • None of the 19 unique contracts called contain the oracle address (0x634200...0001) in their bytecode, meaning they cannot originate a STATICCALL to oracle.
  • Call traces of 10 representative contract-calling transactions confirm no oracle interaction of any kind.

The MiniRex window was the chain's initial bootstrap phase with minimal user activity and no oracle usage, so this fix is replay-safe.

@Troublor Troublor merged commit 83cfdad into main Mar 9, 2026
2 checks passed
@Troublor Troublor deleted the william/fix/staticcall-oracle-detection branch March 9, 2026 03:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants