feat: harden concurrent buys, wallet balance, challenge timing, and p… - #531
Merged
barry01-hash merged 3 commits intoAug 30, 2026
Conversation
…ayload limits - contract: add InsufficientBalance (55) and atomic max_supply check+increment+write immediately after reentrancy guard in execute_buy, buy_bundle, and lease_prompt to prevent concurrent oversell - contract: pre-check asset_client.balance before transfer_from to surface clear InsufficientBalance instead of raw Soroban op_underfunded - api: normalize challenge endpoint timing with dummy HMAC on validation failure to prevent wallet enumeration - api: add PAYLOAD_TOO_LARGE and WALLET_NOT_FUNDED error codes and map contract errors in promptHashClient (InsufficientBalance/op_underfunded, InvalidFieldLength) - tests: add 5 contract tests for supply enforcement and insufficient balance, and challenge enumeration test
|
@ExcelDsigN-tech 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! 🚀 |
added 2 commits
August 28, 2026 19:42
- contracts/types.rs: remove stray PromptExpiryWarning(u128) from PriceHistoryEntry struct (98943397248) - workflows/security-pentest.yml: chmod 777 reports before ZAP scan (98943398022) - workflows/soroban-schema-validation.yml: add corepack enable before yarn (98943397019) - postcss.config.js: use @tailwindcss/postcss for Tailwind v4 (98943397042) and add devDep - package.json: downgrade stellar-wallets-kit 2.5.0 -> 1.9.5 to restore WalletNetwork/ALBEDO_ID/allowAllModules API (98943396889) and add @tailwindcss/postcss - api/auth/rotateSecret.ts: remove duplicate auth check missing brace (98943396564) - api/moderation/logs.ts: add missing return after 403 (98943396564) - api/prompts/unlock.test.ts: add missing } after MISSING_FIELDS test (98943396564) - api/prompts/unlock.ts: collapse duplicate integrity blocks and fix missing } / duplicate res.json before catch (98943396564) - src/components/SearchBar.tsx: relax eslint-disable rule to avoid missing plugin (98943396564)
…-and-payload-hardening
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: harden concurrent buys, wallet balance, challenge timing, and payload limits
Closes #510, Closes #511, Closes #512, Closes #513
Overview
Hardens 4 critical reliability and security paths in the prompt-hash contract and API subsystem to address race conditions, timing side-channels, cryptic transaction errors, and silent payload storage limit violations.
Feature Summary
max_supplychecks andsales_countincrements into an atomic step before token transfersop_underfunded/ token errors to a structuredInsufficientBalancecontract error and user-friendly client messagePAYLOAD_TOO_LARGEerrors when encrypted prompt payloads exceed the 4096-character contract limitTechnical Implementation
contracts/prompt-hash/contract.rs):execute_buy,buy_bundle, andlease_promptto checkmax_supply, incrementsales_count, and invokeStorage::update_promptimmediately after setting the reentrancy guard and before initiating anytransfer_fromoperationscontracts/prompt-hash/types.rs,contract.rs,promptHashClient.ts):InsufficientBalance = 55to theErrorenumasset_client.balance(&buyer)pre-checks withensure!(balance >= price, InsufficientBalance)prior to callingtransfer_fromacross all purchase and lease flowsCONTRACT_ERROR_CODESandclassifyContractErrorinpromptHashClient.tsto translateInsufficientBalanceandop_underfundedintoWALLET_NOT_FUNDEDandINSUFFICIENT_BALANCEapi/auth/challenge.ts):createHmac("sha256", secret).update("padding").digest("base64url")processing onparseRequestBodyfailures to normalize response latency across valid and invalid inputssrc/lib/api/errorCodes.ts):PAYLOAD_TOO_LARGEandWALLET_NOT_FUNDEDvariants with user-actionable error messagesTest Coverage
contracts/prompt-hash/src/test.rs:test_buy_returns_insufficient_balance_when_wallet_unfundedtest_buy_supply_enforcement_is_atomictest_buy_bundle_returns_insufficient_balance_when_wallet_unfundedtest_buy_bundle_supply_enforcement_blocks_when_fulltest_lease_returns_insufficient_balance_when_wallet_unfundedapi/auth/challenge.test.tsverifying identical 400MISSING_FIELDSresponses across invalid addressescargo testandvitestsuite runs pending CI execution under Rust 1.91+ toolchain and installed dependency treeChecklists