Reserve DTF Auction Price Band Invariant
The per-pair auction price always stays inside the band the launcher published, at every block during the auction.
Reserve DTF Protocol lets anyone deploy a Folio: an ERC-20 share that represents a basket of underlying tokens. When the composition needs to change, governance opens a Dutch auction. An AUCTION_LAUNCHER publishes a per-pair price band, and bidders swap one basket token for another within that band as the per-pair price p decays from startPrice (worst for the bidder) to endPrice (best for the bidder) over the auction window. The decay is exponential, computed via PRBMath fixed-point ln and exp.
We worked with Reserve to formally verify that _price, the function every bid runs through, always returns a value inside the launcher-published band. The proof covers all three branches of the function: the start-time boundary, the end-time boundary, and the interior exponential decay.
Why this matters
If _price ever returns a value outside [endPrice, startPrice], a bidder can buy basket tokens at a price the launcher never authorized. Above startPrice, the protocol pays out more sell-token per unit of buy-token than the auction band allows; below endPrice, the opposite. Either way, value leaks out of the basket on every bid.
Every bid goes through _price, so a bug here would leak basket value at a per-bid rate that scales with auction volume.
What this invariant covers
The proof covers all three branches of _price: the start-time boundary, the end-time boundary, and the interior exponential decay. It holds for any block.timestamp in the auction window, any per-token price band, and any output of the PRBMath exp function.
The proof depends on the band being well-formed (endPrice ≤ startPrice), which the auction launcher establishes when calling openAuction (the launcher cannot publish a band where low > high). The proof takes the band as an input precondition and does not re-verify the launcher.
How this was proven
The interior branch of _price uses non-linear fixed-point arithmetic: a logarithm to compute the decay rate, an exponential to compute the current price, and ceiling division to apply it. Bounded model checkers and similar tools cannot reason about ln and exp, because they are computed by long polynomial approximations whose every bit cannot be checked by symbolic execution.
We modeled the contract in Verity, our Lean 4 framework for reasoning about Solidity. Instead of re-checking every bit of ln and exp, we rely on one mathematical fact about exp: it never returns a value greater than 1 when its input is at most 0. That single property is enough to prove the band invariant.
Verify it yourself
git clone https://github.com/lfglabs-dev/verity-benchmark cd verity-benchmark lake build Benchmark.Cases.Reserve.AuctionPriceBand
If the build succeeds, the proof is correct. Source repository
Hypotheses
The proof relies on the following assumptions:
exp behaves like a real exponential
PRBMath SD59x18 trust boundary
MathLib_exp_nonpositive_le_D18The proof assumes
exp(x) ≤ 1for anyx ≤ 0. The PRBMathexpimplementation is a long polynomial approximation, and the proof does not re-verify every bit. We assume it satisfies this standard property of exponentials.the price band is well-formed
openAuction input check
hBandThe band must satisfy
endPrice ≤ startPrice, so the launcher cannot publish a band where the best price for the bidder is higher than the worst.openAuctionrejects any such input.the auction is not an atomic swap
Used only at the end-time boundary
hStartNeEndThe proof assumes
auction.startTime ≠ auction.endTime. This excludes the edge case where the launcher sets the same start and end time (an atomic swap). In that case the band collapses to a single price and the invariant holds trivially.the decay exponent fits in a signed integer
Realistic auction range
InteriorSafe.hKElapsedFitsIntThe proof assumes
k × elapsed < 2^255: the decay-rate term times elapsed seconds stays within the positive int256 range. With Reserve's one-week maximum auction length and realistic launcher prices, this is met with many orders of magnitude of headroom.start price stays below about 10^59
Realistic launcher range
InteriorSafe.hMulNoOverflowThe proof assumes
startPricestays below roughly 1059. A stablecoin priced in ETH gives astartPricearound 1030, and even a 1000:1 launcher band stays below 1033. That leaves 26 orders of magnitude of headroom against any realistic price.
Learn more
What is a formal proof? A short explanation for non-specialists.
More research
Dromos MetaDEX Allocation Conservation
In the root-ledger model, chain allocations sum to committed voting power.

KPK Shares Settlement Accounting
A successful kpkShares settlement batch processes each eligible request at most once and accounts exactly for its fees, shares and asset transfers.
Railnet Queue Nominal Conservation
No matter how many partial redemptions happen, or in what order, the queue never records paying out more than it recorded receiving.
