Skip to content

fix: Tenderly simulation initCode split, 7702 sentinel forms, and bigint precision - #223

Merged
Sednaoui merged 3 commits into
devfrom
fix/tenderly-simulation
Jul 27, 2026
Merged

fix: Tenderly simulation initCode split, 7702 sentinel forms, and bigint precision#223
Sednaoui merged 3 commits into
devfrom
fix/tenderly-simulation

Conversation

@sherifahmed990

@sherifahmed990 sherifahmed990 commented Jul 22, 2026

Copy link
Copy Markdown
Member

Fixes in utilsTenderly that made simulations wrong or lossy.

  • Every v0.6 deployment simulation was failing: the v0.6 initCode was split at 22 chars instead of 42, truncating the factory address to 10 bytes and leaking its second half
    into an unprefixed factoryData.
  • EIP-7702 sentinel only matched the short form: the check matched 0x7702 but not the 20-byte right-padded form accepted by EntryPoint v0.8, which fell through — skipping the delegation code override, or triggering a bogus deployment simulation in the callData path.
  • Precision loss above 2^53: callTenderlySimulateBundle typed value/gasPrice as number, silently rounding large wei amounts. bigint is now accepted and serialized as a decimal string.
  • Caller's stateOverrides mutated in place: the stateDiffstorage rename rewrote the caller's object; the conversion now works on a copy.

Summary by CodeRabbit

  • Bug Fixes
    • Improved EIP-7702 delegation simulation to correctly support both compact and padded factory sentinel forms.
    • Fixed factory address and factory-data extraction when parsing combined init-code in call-data simulations.
    • Prevented precision loss by serializing large gas price and value inputs safely.
    • Enhanced state override processing with stricter validation and non-mutating behavior, including correct handling of storage/state-diff formats.
  • Tests
    • Added regression coverage for EIP-7702 simulation behaviors and override merging/non-mutation.

…cision

- v0.6 initCode was split at 22 chars instead of 42, truncating the
  factory address to 10 bytes and leaking its second half into an
  unprefixed factoryData — every v0.6 deployment simulation was garbage.
- the EIP-7702 factory sentinel check only matched the short '0x7702'
  form; the 20-byte right-padded form accepted by EntryPoint v0.8 fell
  through, skipping the delegation code override (or triggering a bogus
  deployment simulation in the callData path).
- callTenderlySimulateBundle typed value/gasPrice as number, silently
  rounding wei amounts above 2^53; bigint is now accepted and serialized
  as a decimal string.
- stateOverrides passed by the caller were rewritten in place
  (stateDiff renamed to storage); the conversion now works on a copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df98c176-c329-4f66-abf1-c44b888bf025

📥 Commits

Reviewing files that changed from the base of the PR and between e1e4940 and a6f3bf7.

📒 Files selected for processing (2)
  • src/utilsTenderly.ts
  • test/utilsTenderly7702.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utilsTenderly.ts

📝 Walkthrough

Walkthrough

Tenderly simulation helpers now recognize both EIP-7702 sentinel formats, parse full factory addresses from initCode, serialize bigint transaction values safely, and validate copied state overrides without mutating caller-owned data.

Changes

Tenderly simulation updates

Layer / File(s) Summary
EIP-7702 sentinel and initCode handling
src/utilsTenderly.ts, test/utilsTenderly7702.test.js
Centralizes recognition of short and padded EIP-7702 sentinels, applies it to delegation overrides and call-data normalization, and tests packed initCode, initialization sequencing, override merging, and absent authorization.
Bundle serialization and state overrides
src/utilsTenderly.ts
Accepts bigint gasPrice and value, serializes them as decimal strings, and validates copied state overrides while normalizing stateDiff into storage and rejecting both fields together.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant UserOperation
  participant TenderlyHelper
  participant StateOverrides
  participant Tenderly
  UserOperation->>TenderlyHelper: provide factory and factoryData
  TenderlyHelper->>TenderlyHelper: normalize sentinel and build initCode
  TenderlyHelper->>StateOverrides: install delegation code
  TenderlyHelper->>Tenderly: submit simulation request
Loading

Possibly related PRs

Poem

I’m a rabbit with padded bytes,
Hopping through simulations bright.
Bigints turn to decimal trails,
State overrides leave no stale details.
EIP-7702 sentinel signs—
Tenderly follows cleaner lines.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the changes but does not follow the required Summary/Test/Risk template. Add the missing Summary, Test, and Risk / Compatibility sections with concise details for each.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main Tenderly simulation fixes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@Sednaoui Sednaoui left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes based on live Tenderly verification.

What is working:

  • The padded EIP-7702 marker in the full handleOps path is valid. Simulation 07bb5508-667b-4deb-8580-c4af19bfd61e completed with status=true, included the sender code override, and executed the expected 1-wei internal transfer.
  • The v0.6 split, bigint serialization, and non-mutating state-override changes also behaved correctly in isolated request probes.

Two EIP-7702 cases still need correction:

  1. The short marker with non-empty factoryData is packed as 0x7702<factoryData> rather than a 20-byte right-padded marker followed by the data.
  2. The direct call-data path removes the sentinel but does not install the delegation override and discards initialization data. In simulation 001431d4-9e83-409d-b667-49cafe163d16, Tenderly returned status=true but no internal transfer executed. The same call with the missing delegation override added (c727864a-f42e-4e0e-8228-371482f24fa2) executed successfully.

Please add regression coverage for short/padded markers, fresh delegation, and non-empty factoryData.

Comment thread src/utilsTenderly.ts
if (
!isV6UserOperation &&
(userOperation as UserOperationV7 | UserOperationV8 | UserOperationV9).factory === "0x7702"
isEip7702FactorySentinel(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expanded padded-marker detection is valid, but the short-marker case is still malformed when factoryData is non-empty. The initCode construction above concatenates the data immediately after 0x7702, producing e.g. 0x77021234; EntryPoint requires 0x7702 right-padded to 20 bytes before the initialization data. A live Tenderly run decoded exactly 0x77021234 and reverted through the ordinary deployment path with AA10 sender already constructed. Please normalize the short marker during initCode construction and add a regression test for non-empty factoryData.

Comment thread src/utilsTenderly.ts
// factoryData:null. This doesn't represent an actual factory
// deployment, so normalize to null.
if (factory === "0x7702") {
if (isEip7702FactorySentinel(factory)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids treating the padded marker as a factory, but the direct simulation is still semantically incomplete: it neither installs the sender's EIP-7702 delegation-code override nor preserves non-empty factoryData as the sender initialization call. In live Tenderly simulation 001431d4-9e83-409d-b667-49cafe163d16, this path returned status=true while executing no internal transfer; adding the missing code override made the same call execute successfully (c727864a-f42e-4e0e-8228-371482f24fa2). Please mirror the full simulation's delegation override here and, when factoryData is non-empty, enqueue the SenderCreator-to-sender initialization before the call-data transaction.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

sherifahmed990 and others added 2 commits July 25, 2026 19:34
The handleOps encoding concatenated the short 0x7702 factory sentinel
directly with factoryData, producing a malformed initCode head;
normalize it to the 20-byte right-padded marker EntryPoint requires
(also in the executeUserOp rewrite path). The direct call-data
simulation dropped the sentinel entirely: it now installs the sender's
0xef0100 delegation-code override from eip7702Auth and routes non-empty
factoryData as the SenderCreator-to-sender initialization call. Adds
regression tests for short/padded markers, fresh delegation, and
non-empty factoryData.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sherifahmed990
sherifahmed990 requested a review from Sednaoui July 25, 2026 16:58
@Sednaoui
Sednaoui merged commit f27ba2f into dev Jul 27, 2026
3 checks passed
@Sednaoui
Sednaoui deleted the fix/tenderly-simulation branch July 27, 2026 11:02
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