Skip to content

fix(sdk): skip outer-tx gas check for SCA / relayed steps#377

Merged
chybisov merged 3 commits intomainfrom
check-balance-flow-adjustments
Apr 30, 2026
Merged

fix(sdk): skip outer-tx gas check for SCA / relayed steps#377
chybisov merged 3 commits intomainfrom
check-balance-flow-adjustments

Conversation

@chybisov
Copy link
Copy Markdown
Member

Which Linear task is linked to this PR?

https://linear.app/lifi-linear/issue/JUM-868/safe-app-balance-check-uses-connected-wallet-instead-of-safe-wallet

Why was it implemented this way?

CheckBalanceTask enforced that the funding wallet hold enough native token to pay outer-tx gas. For Safe Apps and other smart-contract wallets that's wrong — the SCA executor / 4337 bundler / paymaster pays gas, not the Safe — so a Safe with sufficient USDC but no ETH was incorrectly rejected with "The balance is too low". Same story for relayed steps.

  • checkBalance now partitions per-token requirements into source / gas / fee and gains a walletPaysGas opt-in (default true, preserving today's strict behavior). When false, gas is excluded from the sufficiency check and the slippage-rescue reservation; pure-gas entries are pre-filtered out so the RPC isn't queried for them. Source amount and non-included native fees (e.g. LayerZero msg.value) are still verified.
  • CheckBalanceTask exposes a protected getCheckBalanceOptions(context) hook so chain-specific subclasses decide per step. Default returns {} — no behavior change for any provider that doesn't override.
  • New EthereumCheckBalanceTask overrides the hook: short-circuits relayer steps, otherwise reads eth_getCode (via a shared, deliberately uncached getAccountCode) on step.action.fromChainId for step.action.fromAddress and OR-s the verdict with EIP-7702 detection — delegated EOAs still pay their own gas.
  • The same building blocks de-duplicate canAccountUseNativePermits (extracted from getNativePermit.ts) and isSafeWallet (which previously took an optional viemClient and ran getCode inline). isSafeWallet still falls through to the Safe Transaction Service on RPC failure as an independent fallback.

Skip-bias is intentional: a wrong skip surfaces immediately as a wallet rejection; a wrong enforce silently blocks a valid tx.

Visual showcase (Screenshots or Videos)

N/A — backend logic change. Manual repro per the Linear ticket: USDC bridge from a Safe whose signer holds no ETH no longer trips the balance check.

Checklist before requesting a review

  • I have performed a self-review and testing of my code.
  • This pull request is focused and addresses a single problem.
  • If this PR modifies the SDK API or adds new features that require documentation, I have updated the documentation in the public-docs repository.

Test plan

  • pnpm check — green
  • pnpm check:types — green
  • pnpm test:unit — 381 passing / 5 skipped (no regressions); 67 in sdk-provider-ethereum, 220 in sdk core
  • Manual repro (Linear JUM-868): open Jumper via Safe Apps with a Safe holding USDC and a signer with no ETH; start a swap/bridge — expect the balance check to pass and the tx to reach the Safe's signing flow
  • Manual sanity (EOA, default path): EOA execution with an underfunded native balance still produces "The balance is too low" before wallet simulation

@chybisov chybisov merged commit 3fcf318 into main Apr 30, 2026
1 of 2 checks passed
@chybisov chybisov deleted the check-balance-flow-adjustments branch April 30, 2026 08:24
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