Skip to content

fix: buffer gas prices in self-funded session fallback - #107

Merged
tarrencev merged 1 commit into
cartridge-gg:mainfrom
Await-0x:fix/self-funded-session-gas-prices
Sep 8, 2026
Merged

tarrencev merged 1 commit into
cartridge-gg:mainfrom
Await-0x:fix/self-funded-session-gas-prices

Conversation

@Await-0x

@Await-0x Await-0x commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Self-funded session transactions can fail when gas prices rise between estimation and submission, even with selfFundedGasMultiplier: 10. Add 50% headroom to all three gas prices in the automatic paymaster-to-self-funded fallback, matching the keychain confirmation flow.

Cause

try_session_execute_with_gas_multiplier first tries outside execution. On PaymasterNotSupported, it passes the result of estimate_invoke_fee directly to execute_with_gas_multiplier. estimate_fee() returns raw RPC prices: the .gas_price_estimate_multiplier(2.0) on its builder does not modify the returned estimate. Execution then explicitly sets each price from that estimate, bypassing starknet-rs's automatic price buffering.

This path also bypasses the keychain's toStarknetFeeEstimate, which normally adds 50% to prices. The amount multiplier introduced by cartridge-gg/controller#2669 only changes gas amounts, so raising it cannot address this rejection.

Observed L1 gas price: signed cap 96966059925918, submission price 97728921905943. L1 data gas: signed cap 134488580849, submission price 135546644105. Both increased by roughly 0.79%.

Paymaster success uses a different path: the SDK signs an outside-execution message and the relayer submits the outer transaction. The SDK never constructs self-funded resource bounds in that case. Cartridge's public paymaster implementation independently buffers both amounts and prices; its default is 2.5x. This is a source comparison, not a claim about the hosted service's deployed configuration.

Change

  • Buffer L1 gas, L1 data gas, and L2 gas prices once, at the automatic fallback boundary.
  • Use integer arithmetic with saturation to preserve precision and avoid overflow.
  • Preserve gas amounts for the existing configurable multiplier. Leave overall_fee as the raw cost estimate.
  • Preserve explicitly supplied max-fee prices, which may already include headroom or represent an approved limit.

No automatic resubmission is added. This addresses missing price headroom; it does not guarantee acceptance through arbitrary price increases or delays. Browser rollout requires publishing the updated WASM package and consuming it in the hosted keychain.

Validation

  • Added a local RPC regression that rejects the reported price drift and checks serialized bounds with both default and 10x amount multipliers. Confirmed it fails with the buffering call removed and passes with the fix.
  • Added checks for unchanged explicit prices, paymaster success bypassing self-funded estimation/submission, integer rounding, zero prices, and saturation.
  • cargo test -p account_sdk --lib gas::tests — 8 passed.
  • cargo test -p account_sdk --lib session_execution_test — 3 passed.
  • cargo test -p account_sdk --lib --features filestorage session_execution_test — 3 passed.
  • cargo test -p account_sdk --lib test_paymaster_fallback -- --test-threads=1 with Katana v1.7.0-alpha.0 — 2 passed.
  • cargo clippy -p account_sdk --lib -- -D warnings — passed.
  • cargo check -p account-wasm --target wasm32-unknown-unknown --features controller_account — passed, with warnings in unchanged code.
  • Changed-file rustfmt check and git diff --check — passed.

The full all-feature CI suite was not run locally.

@tarrencev
tarrencev merged commit 45ea144 into cartridge-gg:main Sep 8, 2026
5 checks passed
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