Skip to content

fix: resolve fee bump downgrade, soroban panic decoding, signing session timeout, and sep10 nonce randomization (#854, #859, #860, #861) - #883

Open
OluwapelumiElisha wants to merge 1 commit into
Sorokit:mainfrom
OluwapelumiElisha:fix/core-issues-854-859-860-861
Open

OluwapelumiElisha wants to merge 1 commit into
Sorokit:mainfrom
OluwapelumiElisha:fix/core-issues-854-859-860-861

Conversation

@OluwapelumiElisha

Copy link
Copy Markdown

Summary

This PR resolves issues #854, #859, #860, and #861 across the transaction, Soroban, wallet, and SEP-10 integration modules.

Closes #854
Closes #859
Closes #860
Closes #861


Detailed Changes

1. #854: Prevent Fee Bump Downgrades in buildFeeBumpTransaction

  • Problem: buildFeeBumpTransaction accepted any base fee without verifying that it exceeded the inner transaction's fee, allowing accidental fee downgrades that caused fee bumps to be rejected or ineffective.
  • Solution: Validated bumpFee > innerFee immediately after parsing the inner transaction envelope. Rejects fees less than or equal to the original transaction fee with a descriptive TX_BUILD_FAILED error.
  • Files: src/transaction/feeBumpTransaction.ts, src/transaction/feeBump.ts, src/tests/feeBumpTransaction.test.ts.

2. #859: Soroban Panic & VM Trap Decoder (SorobanErrorDecoder)

  • Problem: Soroban VM traps and contract panics were returned in cryptic serialized formats and converted to generic "invocation failed" messages, hindering contract debugging.
  • Solution: Implemented SorobanErrorDecoder and decodeSorobanPanic to decode panics into human-readable descriptions, integrated into decodeContractError.
  • Formats Decoded:
    • WASM VM Traps:
      • unreachable -> WebAssembly unreachable instruction executed (assertion failure or explicit panic)
      • integer overflow / arithmetic overflow / overflow during arithmetic -> Arithmetic overflow or underflow
      • division by zero / remainder by zero -> Division or remainder by zero
      • out of bounds -> Memory or table index out of bounds
      • stack overflow / call stack exhausted -> WebAssembly call stack exhausted
      • unaligned memory -> Unaligned memory access
      • indirect call type mismatch -> Function signature mismatch on indirect call
    • Host Error Traps:
      • Error(WasmVm, Trapped) -> WebAssembly VM execution trapped
      • Error(Context, Trap) -> Soroban host context trap occurred
      • Error(Budget, ExceededLimit) -> Soroban compute or memory resource budget exceeded
      • Error(Storage, MissingValue) -> Missing or expired contract storage key
      • Error(Auth, Invalid) -> Contract authorization failed or invalid credentials
      • Error(Contract, #<code>) -> Custom contract error code extraction
    • Rust Panics: panicked at '...', src/lib.rs:line:col extracted with clean reason and source location.
    • Fallback: Graceful fallback to generic descriptive messages for unknown panic formats.
  • Files: src/soroban/sorobanErrorDecoder.ts, src/soroban/contractErrors.ts, src/soroban/index.ts, src/tests/sorobanErrorDecoder.test.ts.

3. #860: Enforce Configurable Timeout & Cancellation on TransactionSigningSession

  • Problem: Wallet signing requests had no timeout mechanism, causing applications to hang indefinitely if users left prompts open or if the wallet extension crashed.
  • Solution: Introduced TransactionSigningSession and signTransactionWithSession with timeout tracking and active lifecycle control.
  • Default Timeout: Default duration is 5 minutes (DEFAULT_SIGNING_SESSION_TIMEOUT_MS = 300,000 ms).
  • How Callers Extend/Cancel:
    • session.extendTimeout(additionalMs): Adds additional milliseconds to the active session deadline while pending.
    • session.resetTimeout(newTimeoutMs): Resets the timeout duration from the current moment.
    • session.cancel(reason?): Immediately cancels the pending session and resolves the signing promise with a WALLET_SIGN_REJECTED error.
    • When the timeout expires, the session resolves cleanly with a SorokitErrorCode.OPERATION_TIMEOUT error.
  • Files: src/wallet/transactionSigningSession.ts, src/wallet/index.ts, src/tests/transactionSigningSession.test.ts.

4. #861: Cryptographically Secure Random Nonces in SEP-10 Challenge Generation

  • Problem: SEP-10 challenge generation risk of using predictable or static nonces allowed challenge pre-computation and replay attacks.
  • Solution: Implemented generateSep10Nonce and generateSep10Challenge ensuring every challenge contains a unique cryptographically secure random nonce.
  • Random Source: Environment CSPRNG via crypto.randomBytes(48) (Web Crypto API getRandomValues in browser, Node crypto.randomBytes in Node.js).
  • Nonce Format: 48-byte cryptographically secure random buffer (384 bits of entropy) stored in the client account manageData operation (${homeDomain} auth), meeting the SEP-10 specification.
  • Files: src/integration/sep10Auth.ts, src/integration/index.ts, src/tests/sep10ChallengeNonce.test.ts.

…ion timeout, and sep10 nonce randomization (Sorokit#854, Sorokit#859, Sorokit#860, Sorokit#861)

- Sorokit#854: Validate fee bump fee is strictly higher than original transaction fee in buildFeeBumpTransaction to prevent accidental fee downgrades
- Sorokit#859: Implement SorobanErrorDecoder to parse Soroban panic messages and VM traps into readable descriptions instead of generic invocation failures
- Sorokit#860: Enforce configurable timeout (default 5m) and cancellation support in TransactionSigningSession to prevent indefinite hangs
- Sorokit#861: Introduce cryptographically random nonce generation in SEP-10 challenge generation to prevent challenge replay attacks
@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@OluwapelumiElisha Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment