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.
Problem
contracts/auctionexists in the workspace but has no live caller. Its only integration point intopoolwasfund_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
auctioninto a real competitive discount-funding mechanism for invoices, integrated withpoolvia cross-contract calls (mirroring how the newsecondary_marketsatellite contract calls back intopool's trustedmarket_settle_listingentrypoint for settlement — seecontracts/pool/src/lib.rsandcontracts/secondary_market/src/lib.rs).Work required:
pool(newauction-side settlement entrypoint onpool, following themarket_settle_listingtrust pattern: satellite calls in as itself,poolcompares against a stored trusted address), bid withdrawal/refund for non-winning bids, and auction expiry handling.MAX_LISTINGS_PER_INVOICE-style bound used elsewhere in this codebase).contracts/pool/tests/fuzz_tests.rs.AuctionClienttopackages/sdk/src/clients/(mirroringPoolClient/the new secondary-market client), covering open/bid/withdraw/close/query methods, and reflect it insdk/'s built output.frontend/lib/contracts.tswith aNEXT_PUBLIC_AUCTION_CONTRACT_IDenv var.indexer/src/parser.ts, following the existing event-namespace pattern used for pool/secondary-market events.Acceptance criteria
pool→ invoice is funded, all exercised in integration tests.cargo build --target wasm32-unknown-unknown --releaseproduces anauction.wasmunder Soroban's 200KB limit, with the CI wasm-size check green.cargo clippy -- -D warningsorcargo fmt --check.auctioncontract on testnet, and the indexer correctly ingests all auction events.