Swap lifecycle
The contract exposes four actions. Let t₀ be the creation block timestamp, A the auction duration, and W the settlement window:
auctionEnd = t₀ + Adeadline = auctionEnd + Wbond = floor(ethPrincipal × BOND_BPS / 10,000)Creation
Section titled “Creation”createIntent requires positive principal, minimum XMR, height, and difficulty; exactly 95 recipient bytes; and an in-range window. Address contents are validated by the proof guest, so callers must supply a supported address.
The user is the caller. Initially bestSolver is zero and bestXmrAmount = minXmrAmount − 1.
Bidding
Section titled “Bidding”Before auctionEnd, placeBid requires a strictly higher XMR amount and exactly one bond, including for a self-rebid. The first bid may equal the user’s minimum.
The previous bond is returned with a 10,000-gas call. If that refund fails, the bond remains trapped. A replacement bid requires 100,000 gas remaining before the refund call. The auction never extends and needs no separate close or acceptance transaction.
Settlement
Section titled “Settlement”settle requires a winner, unused transaction/output markers, and a valid proof for the immutable program key and live terms. Its allowed interval is:
auctionEnd <= block.timestamp < deadlineAnyone may submit the proof; principal plus bond goes to the stored winner.
Expiry
Section titled “Expiry”| Live state | Earliest expiry | Original user receives |
|---|---|---|
| No winner | timestamp >= auctionEnd |
Principal |
| Winner, still unsettled | timestamp >= deadline |
Principal plus winning bond |
Anyone may call expire; there is no caller bounty or automatic refund.
Both terminal actions delete the live row and emit an event. ETH-transfer failure reverts the entire action, including markers and events. Afterwards, getSwap returns SwapNotFound; use events to distinguish settlement from expiry. There is no early cancellation, alternate payout address, or reversal.