Skip to content

Review follow-ups: transport, Tenderly, Safe v0.6, paymaster, and allowance fixes - #229

Merged
sherifahmed990 merged 9 commits into
devfrom
release_0.4.1
Jul 28, 2026
Merged

Review follow-ups: transport, Tenderly, Safe v0.6, paymaster, and allowance fixes#229
sherifahmed990 merged 9 commits into
devfrom
release_0.4.1

Conversation

@sherifahmed990

@sherifahmed990 sherifahmed990 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Fixes a batch of issues surfaced by bot review findings, each independently verified against the code before applying. Every fix ships with regression tests; the full suite (548
tests, 26 suites) and type tests pass.

Transport

  • Don't let non-RPC JSON error bodies mask the HTTP status (b90a12c) — HttpTransport.send treated any non-null error field as a JSON-RPC error envelope, so an HTTP failure with a
    body like {"error": "rate limited"} bypassed the HTTP-status branch and surfaced only a generic "malformed JSON-RPC response", losing the status code (e.g. 429). Only a properly
    shaped JSON-RPC error object (numeric code, string message) now falls through to response parsing.

Tenderly simulation

  • Merge state overrides case-insensitively by address (089f602) — the EIP-7702 delegation-code injection looked up the sender in caller stateOverrides by lowercase key only; a
    checksummed caller entry was missed, producing two state_objects keys for the same EVM address and undefined server-side resolution. Both injection sites now merge via a shared
    withSenderCodeOverride helper, and callTenderlySimulateBundle normalizes all override keys to lowercase, rejecting same-address keys that differ only in case.

Safe accounts

  • Resolve V0.6 initCode override before dummy signature and estimation (b5a41e4) — overrides.initCode was applied only after the base builder had derived isInit from factoryAddress
    and estimated gas with a factory-derived initCode. A caller-supplied "0x" or custom initCode therefore produced a mismatched WebAuthn dummy-signature encoding and estimation op. The
    final initCode is now resolved first and isInit derives from it.
  • Validate recurring allowance validity period against uint16 (13734b7) — an out-of-range recurringAllowanceValidityPeriodInMinutes previously surfaced as the ABI encoder's generic
    "value out-of-bounds for uint16" error; it's now rejected up front with a RangeError that names the parameter.

WorldId paymaster

  • Gas estimation inputs (6f7156b, refined by 39c4c3a) — final behavior: only preVerificationGas is zeroed before eth_estimateUserOperationGas, since the paymaster's proof calldata
    is what invalidates it. Supplied verificationGasLimit/callGasLimit are paymaster-independent on v0.7+ and pass through as trusted prior estimates — bundlers that skip estimating
    supplied fields answer faster — with the existing max(supplied, estimated) clamp as a guard. The precondition is documented on the method.

Test infrastructure

  • Detect src deletions in the dist freshness check (e58084e) — _ensureFreshDist ignored directory mtimes, so deleting a src file never triggered a rebuild and tests kept running
    against stale dist code.

Review findings intentionally skipped

  • Extracting the duplicated Erc7677/Candide estimation logic into a shared helper: a ~200-line behavior-preserving refactor with provider-specific exceptions; deferred to its own
    change.
  • Further Tenderly helper extraction: already covered by withSenderCodeOverride; the remaining duplication is a two-line null check.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Safe v0.6 initialization code handling so gas estimation reflects the final init mode when overrides are provided.
    • Added stricter validation for recurring allowance validity periods to prevent out-of-range values.
    • Enhanced HTTP transport error reporting for malformed/non-standard JSON-RPC error payloads.
    • Strengthened Tenderly simulations by canonicalizing state override addresses and rejecting case-duplicate overrides.
    • Preserved expected gas estimate behavior during paymaster user operation creation and re-estimation.
  • Tests

    • Added regression and behavior tests for Safe init code, allowance validation, HTTP errors, paymaster gas handling, and Tenderly override merging/duplication.
  • Chores

    • Improved Jest rebuild detection reliability for directory trees.

sherifahmed990 and others added 7 commits July 28, 2026 16:59
hasRpcError treated any non-null "error" field as a JSON-RPC error, so an
HTTP failure with a body like {"error": "rate limited"} bypassed the
HTTP-status branch and surfaced only "malformed JSON-RPC response",
losing the status code and text (e.g. 429 Too Many Requests). Require a
properly shaped JSON-RPC error object (numeric code, string message)
before trusting the body over the status.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The EIP-7702 delegation-code injection looked up the sender in caller
stateOverrides by lowercase key only, so an entry keyed by a checksummed
address was missed and the payload carried two state_objects keys for
the same EVM address — Tenderly then resolved the duplicate
unpredictably, dropping either the caller's override or the delegation
code. Merge the sender entry case-insensitively at both injection
sites, and in callTenderlySimulateBundle normalize all override keys to
lowercase, rejecting same-address keys that differ only in case.

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

overrides.initCode was applied only after the base builder had derived
isInit from factoryAddress and estimated gas with a factory-derived
initCode, so a caller-supplied "0x" or custom initCode produced a
mismatched WebAuthn dummy-signature encoding and estimation op. Resolve
the final initCode first and derive isInit from it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Only preVerificationGas was zeroed before estimateUserOperationGas, so
caller-supplied verificationGasLimit and callGasLimit leaked into the
estimation request. Zero all three (matching SafeAccount and
Erc7677Paymaster); supplied limits still act as minimums afterward.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An out-of-range recurringAllowanceValidityPeriodInMinutes previously
surfaced as the ABI encoder's generic "value out-of-bounds for uint16"
Error. Reject it up front with a RangeError that names the parameter,
consistent with the existing timestamp validation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
newestMtimeMs ignored directory mtimes, so deleting a src file (which
only updates the parent directory) never triggered a rebuild and tests
kept running against stale dist code. Include each directory's own
mtime in the scan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Partially reverts 6f7156b. On v0.7+ verificationGasLimit and
callGasLimit are paymaster-independent (paymaster validation has its
own gas field), so the caller's prior estimates stay valid and are
passed through — bundlers that skip estimating supplied fields answer
faster. Only preVerificationGas is zeroed for re-estimation, since the
paymaster proof calldata grows it. Documented that supplied limits are
trusted as prior estimates.

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

coderabbitai Bot commented Jul 28, 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: 624ba813-2a50-4e57-9215-d571ac020737

📥 Commits

Reviewing files that changed from the base of the PR and between 39c4c3a and 7349258.

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

📝 Walkthrough

Walkthrough

The changes resolve Safe v0.6 initialization state, validate allowance periods, clarify and test paymaster gas estimation, tighten HTTP error parsing, normalize Tenderly state overrides, and improve test distribution freshness checks.

Changes

Safe initialization

Layer / File(s) Summary
Resolve v0.6 initCode and signer mode
src/account/Safe/SafeAccount.ts, test/safe/initCodeOverrideIsInit.test.js
Resolves effective v0.6 initCode before estimation and signing, derives initialization mode from it, and tests default, empty, and custom overrides.

Allowance validation

Layer / File(s) Summary
Validate recurring allowance periods
src/account/Safe/modules/AllowanceModule.ts, test/safe/allowanceModule.test.js
Rejects validity periods outside the contract’s uint16 range and tests negative and overflowing values.

Paymaster estimation

Layer / File(s) Summary
Preserve trusted gas fields during re-estimation
src/paymaster/WorldIdPermissionlessPaymaster.ts, test/paymaster/worldIdPermissionlessPaymaster.test.js
Documents and verifies that only preVerificationGas is reset while other gas fields are reused as minimums without mutating the input operation.

Transport error handling

Layer / File(s) Summary
Validate JSON-RPC error envelopes
src/transport/HttpTransport.ts, test/transport/httpErrorHandling.test.js
Requires numeric code and string message fields before treating an HTTP failure body as a JSON-RPC error, with status-based tests for malformed bodies.

Tenderly state overrides

Layer / File(s) Summary
Merge and canonicalize EIP-7702 overrides
src/utilsTenderly.ts, test/utilsTenderly7702.test.js
Merges sender overrides case-insensitively, lowercases bundle keys, rejects case-only duplicates, and tests both simulation paths without mutating caller state.

Test build freshness

Layer / File(s) Summary
Track directory modification times
test/_ensureFreshDist.cjs
Includes directory timestamps in recursive freshness checks.

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

Possibly related PRs

Suggested reviewers: sednaoui

Poem

I’m a rabbit with cleaner code,
Hopping through each validation road.
InitCode settles, overrides align,
Gas fields keep their trusted design.
Errors now speak in shapes that are true—
Tenderly’s keys know where to queue!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the changes and tests, but it does not follow the required Summary/Test/Risk / Compatibility template. Rewrite it using the repo template with separate Summary, Test, and Risk / Compatibility sections, and include concise compatibility notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main batch of fixes, though it is broad and framed as follow-ups.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/utilsTenderly.ts`:
- Around line 53-60: Update the state-overrides handling before the merge loop
in callTenderlySimulateBundle to detect multiple sender override keys
case-insensitively and reject them before any entries are combined. Preserve the
duplicate entries long enough to validate them, and only merge overrides when no
duplicate sender keys exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17dd5bc4-f0c2-40ab-9493-9275f207b49e

📥 Commits

Reviewing files that changed from the base of the PR and between 7ef7e43 and 39c4c3a.

📒 Files selected for processing (11)
  • src/account/Safe/SafeAccount.ts
  • src/account/Safe/modules/AllowanceModule.ts
  • src/paymaster/WorldIdPermissionlessPaymaster.ts
  • src/transport/HttpTransport.ts
  • src/utilsTenderly.ts
  • test/_ensureFreshDist.cjs
  • test/paymaster/worldIdPermissionlessPaymaster.test.js
  • test/safe/allowanceModule.test.js
  • test/safe/initCodeOverrideIsInit.test.js
  • test/transport/httpErrorHandling.test.js
  • test/utilsTenderly7702.test.js

Comment thread src/utilsTenderly.ts Outdated
withSenderCodeOverride silently folded multiple caller entries matching
the sender under different casings (last key's fields winning), which
also collapsed them before callTenderlySimulateBundle's duplicate-key
rejection could see them — so duplicates for the sender merged silently
while duplicates for any other address threw. Reject them with the same
RangeError as the choke point; merging only happens when the sender has
at most one entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sherifahmed990
sherifahmed990 merged commit 0819cb5 into dev Jul 28, 2026
3 checks passed
@sherifahmed990
sherifahmed990 deleted the release_0.4.1 branch July 28, 2026 16:16
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.

1 participant