Skip to content

Turn the auction contract into a real competitive discount-funding mechanism #1054

Description

@sanmipaul

Problem

contracts/auction exists in the workspace but has no live caller. Its only integration point into pool was fund_invoice_with_discount, which was removed as confirmed dead code during a recent CI-stabilization pass — a grep across the workspace and frontend/SDK turned up zero remaining references to the auction contract anywhere. It currently sits in the repo as an unreachable skeleton: no bidding lifecycle, no escrow, no settlement path, no tests beyond the bare minimum.

Proposed scope

Build out auction into a real competitive discount-funding mechanism for invoices, integrated with pool via cross-contract calls (mirroring how the new secondary_market satellite contract calls back into pool's trusted market_settle_listing entrypoint for settlement — see contracts/pool/src/lib.rs and contracts/secondary_market/src/lib.rs).

Work required:

  • Contract: design and implement the actual auction mechanics — opening an auction for an invoice at a target discount/rate, investors placing competitive bids (with bid escrow so funds are locked, not just promised), a close/settlement path that picks the winning bid(s) and funds the invoice through a trusted cross-contract call into pool (new auction-side settlement entrypoint on pool, following the market_settle_listing trust pattern: satellite calls in as itself, pool compares against a stored trusted address), bid withdrawal/refund for non-winning bids, and auction expiry handling.
  • Storage/state: bids, auction lifecycle status, per-investor escrowed amounts — sized and indexed so listing/settlement stays bounded (cap on bids per auction, matching the MAX_LISTINGS_PER_INVOICE-style bound used elsewhere in this codebase).
  • Tests: full lifecycle coverage (auction open → bids placed → close → settlement, competing bids at different discount rates, expiry with no bids, expiry with unfilled capacity, bid withdrawal, double-bid/self-bid rejection, unauthorized settlement attempts) plus fuzz/property tests for the bid-ranking and settlement math, following the pattern in contracts/pool/tests/fuzz_tests.rs.
  • SDK: add an AuctionClient to packages/sdk/src/clients/ (mirroring PoolClient/the new secondary-market client), covering open/bid/withdraw/close/query methods, and reflect it in sdk/'s built output.
  • Frontend: UI for browsing open auctions, placing/withdrawing a bid, and viewing an invoice's auction history, wired through frontend/lib/contracts.ts with a NEXT_PUBLIC_AUCTION_CONTRACT_ID env var.
  • Indexer: parse and store the auction's emitted events (open/bid/close/settle/expire) in indexer/src/parser.ts, following the existing event-namespace pattern used for pool/secondary-market events.

Acceptance criteria

  • An SME can have an invoice funded via a competitive auction end-to-end: open auction → multiple investors bid → auction closes → winning bid(s) settle through pool → invoice is funded, all exercised in integration tests.
  • Non-winning bids are refunded (escrowed funds released) on settlement or expiry.
  • cargo build --target wasm32-unknown-unknown --release produces an auction.wasm under Soroban's 200KB limit, with the CI wasm-size check green.
  • No regression in cargo clippy -- -D warnings or cargo fmt --check.
  • Frontend auction flows work end-to-end against a deployed auction contract on testnet, and the indexer correctly ingests all auction events.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions