Skip to content

fix(bid): enforce exact bid amount precision and overflow bounds (QE-… - #2556

Open
dumbdev wants to merge 1 commit into
QuickLendX:mainfrom
dumbdev:fix/bid-amount-precision-overflow-qe-2026-08
Open

fix(bid): enforce exact bid amount precision and overflow bounds (QE-…#2556
dumbdev wants to merge 1 commit into
QuickLendX:mainfrom
dumbdev:fix/bid-amount-precision-overflow-qe-2026-08

Conversation

@dumbdev

@dumbdev dumbdev commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

closes #2442

Centralise bid amount validation - sign, the i128::MAX / 10_000 overflow ceiling, the documented "bid amount <= invoice amount" rule, and the "expected_return >= bid_amount" return floor - in a documented, pure, tested module (bid_amount.rs) and route the bid-submission and auction-selection paths (contract.rs::place_bid, bid.rs::verify_bid_match) through it. Rejected amounts fail before any state change.

checked_bid_profit pins the auction ranking key that compare_bids computes with a lossy saturating_sub: for any pair accepted by validate_bid the exact subtraction is non-negative and cannot overflow i128, so ranking is deterministic; adversarial pairs outside that contract surface as ArithmeticOverflow instead of a clamped, attacker-chosen rank. checked_bid_amount_sum and checked_bid_fee_amount do the same for per-investor exposure aggregation and downstream bps fee math.

One explicit, documented tightening: bids financing more than the invoice face value, or offering a return below principal (previously accepted then ranked with a saturating_sub-clamped profit of 0) are now rejected with the existing QuickLendXError::InvalidAmount. No new error codes, no stored state touched, no migration.

Tests: 20 focused cases in test_bid_amount_precision.rs covering zero, min, max, near-overflow, fractional, and conversion-boundary values, inclusive boundaries, a 5,000-iteration deterministic random sweep against an independent oracle, overflow-vs-clamp, and purity/repeatability. cargo test --lib: 37 passed. cargo build (dev + release WASM profile with overflow-checks) and cargo clippy --lib: clean.

CI note: the failing build check is a pre-existing repo-wide failure, not introduced by this PR

The Soroban Smart Contracts CI / build job fails at a single step — Run Cargo tests (cargo test --verbose) — while compiling two legacy integration-test files that this PR does not touch:

File Errors Cause
quicklendx-contracts/tests/bid_acceptance_replay.rs 59 no method named get_bid / get_bids_for_invoice / accept_bid_and_fund / get_escrow_details … found for QuickLendXContractClient
quicklendx-contracts/tests/invoice_lifecycle_e2e.rs 76 no method named get_invoice / process_partial_payment / settle_invoice / get_platform_metrics … found for QuickLendXContractClient

These files expect the full contract ABI, but the crate is currently a minimal skeleton (lib.rs exposes only errors + invoice_amount, and now bid_amount). The CI workflow itself acknowledges this state: # TODO: restore the original 95% gate after the legacy test suite is repaired.

This failure predates the PR and exists on main:

Commit build check
main HEAD (d9ca8323) ❌ failure
71593c46 — merged PR #2551 (invoice_amount), the precedent this PR mirrors ❌ failure
every recent main commit (4bc72012, c096a080, 96f4e922, …) ❌ failure
this PR (b2334f8b) ❌ failure — identical step, identical two files

Every CI step this change can affect passes:

  • ✅ Build Cargo project
  • ✅ Check code quality (cargo check --lib)
  • ✅ Build and check WASM size budget (contract compiles; new module is #![no_std]-clean)
  • ✅ Run WASM size budget regression tests
  • ❌ Run Cargo tests — fails only on the two unrelated legacy files above

Local validation of this change:

cargo test --lib           → 37 passed (17 existing + 20 new), 0 failed
cargo build                → clean
cargo build --release      → clean (WASM profile, overflow-checks = true)
cargo clippy --lib         → no new warnings
rustfmt --check (new files) → clean

Repairing the legacy tests/ suite or gating that CI step is out of scope for this issue ("no unrelated refactors, disabled CI") and belongs in a separate infrastructure PR.

…2026-08)

Centralise bid amount validation - sign, the i128::MAX / 10_000 overflow
ceiling, the documented "bid amount <= invoice amount" rule, and the
"expected_return >= bid_amount" return floor - in a documented, pure,
tested module (bid_amount.rs) and route the bid-submission and
auction-selection paths (contract.rs::place_bid, bid.rs::verify_bid_match)
through it. Rejected amounts fail before any state change.

checked_bid_profit pins the auction ranking key that compare_bids computes
with a lossy saturating_sub: for any pair accepted by validate_bid the
exact subtraction is non-negative and cannot overflow i128, so ranking is
deterministic; adversarial pairs outside that contract surface as
ArithmeticOverflow instead of a clamped, attacker-chosen rank.
checked_bid_amount_sum and checked_bid_fee_amount do the same for
per-investor exposure aggregation and downstream bps fee math.

One explicit, documented tightening: bids financing more than the invoice
face value, or offering a return below principal (previously accepted then
ranked with a saturating_sub-clamped profit of 0) are now rejected with
the existing QuickLendXError::InvalidAmount. No new error codes, no stored
state touched, no migration.

Tests: 20 focused cases in test_bid_amount_precision.rs covering zero,
min, max, near-overflow, fractional, and conversion-boundary values,
inclusive boundaries, a 5,000-iteration deterministic random sweep
against an independent oracle, overflow-vs-clamp, and purity/repeatability.
cargo test --lib: 37 passed. cargo build (dev + release WASM profile with
overflow-checks) and cargo clippy --lib: clean.

Closes #QE-2026-08

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@dumbdev 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

@dumbdev

dumbdev commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Pls this is a wide repo problem
pls merge

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.

[Quality][High] bid submission and auction selection: amount precision and overflow — QE-2026-08

1 participant