Whitepaper / WITHDRAWAL PROOFS, DISPUTES, AND ROOT CHALLENGES
Dexter whitepaper

WITHDRAWAL PROOFS, DISPUTES, AND ROOT CHALLENGES

Every USDC payout — challenge profit share, leaderboard prize, referral commission — leaves the vault against a cryptographic proof that binds the user's wallet, the owed balance, the nonce, and a published settlement root committed to Base. If the Merkle proof does not reconstruct against the stored root, finalizeWithdraw reverts. This page walks the four-step request lifecycle, the three challenge methods that let any community member contest a bad root before USDC moves, and the exact recovery path if a withdrawal sits in the proof window longer than the 24-hour target.

Page last sync: May 24, 2026
Sections 2 Read 1 min Whitepaper chapter

Seven contract primitives compose the proof-based exit. The first four are required for every withdrawal; the last three are available to any address with standing to challenge a published root.

Mechanism What it does
requestWithdraw(amount) Emits an on-chain nonce that binds the user's wallet, amount, and timestamp to a specific withdrawal intent — no nonce, no exit path
State root history Append-only ring of recent settlement roots; finalizeWithdraw must reference a root still in this history, which makes silent replacement detectable
Merkle proof + leaf User-side leaf data (wallet, balance, nonce list) plus the sibling path that reconstructs the referenced root — reconstruction failure reverts the call
disputeWindowSec Configurable challenge window between root commit and earliest finalizeWithdraw; tuned to balance fast payouts against contest time
challengeRootFraudProof Submits a fraud-verifier output proving the runtime committed a root inconsistent with valid state transitions
challengeRootInvalidLeaf Submits a counter-leaf showing a specific account balance in the published tree contradicts what the runtime owes
challengeRootConflict Submits two roots whose declared parent or sequence numbers contradict each other, exposing a history fork

#The withdrawal path is proof-gated

The user starts by calling requestWithdraw with the USDC amount they want to exit. The contract emits a nonce that binds the request to the user's wallet, the amount, and the block timestamp. That nonce is the only thing the runtime is allowed to act on — a runtime-initiated payout to a wallet that never called requestWithdraw cannot pass finalizeWithdraw because no matching nonce exists in the Merkle leaf.

The runtime then includes the request in the next settlement state. When that state is committed to Base, the new root enters the append-only history ring and disputeWindowSec begins. The gateway exposes the user's leaf data and the sibling path needed to reconstruct the root, so the user (or any client they trust) can verify the proof off-chain before submitting it. Once disputeWindowSec elapses without a successful challenge, finalizeWithdraw is callable: the contract re-runs the Merkle reconstruction on-chain against the referenced root, checks that the nonce matches and has not been consumed, verifies the root is still in history, and only then transfers USDC to the user's wallet.

If a withdrawal sits past the 24-hour target, the failure is observable. Either disputeWindowSec is still open (visible on the contract), the root has not yet been committed (visible on Basescan as the absence of a commitSettlement transaction since requestWithdraw), or the manual review queue has flagged the payout for podium top-three or above-$5K verification. In every case the request remains queued and finalizable as soon as the gating condition clears — nothing about it expires.

TEXT
 requestWithdraw(amount)
   -> on-chain nonce binds wallet + amount + timestamp
   -> runtime includes request in next settlement root
   -> commitSettlement(root) posts to Base, enters history ring
   -> disputeWindowSec begins
   -> gateway exposes leaf + sibling path for off-chain verification
   -> disputeWindowSec elapses without successful challenge
   -> finalizeWithdraw(nonce, leaf, proof, rootRef) releases USDC

#Why challenges and fraud proofs exist

Publication is not the same as correctness. The dispute window exists so anyone who can construct a counter-example has standing to stop a bad root before USDC moves against it. Three challenge paths cover the three failure modes a malicious or buggy runtime could introduce. challengeRootFraudProof targets the case where the published root could not have been produced by valid state transitions — the fraud-verifier hook runs the disputed step on-chain and rejects the root if its output disagrees. challengeRootInvalidLeaf targets the case where a specific account leaf misstates a balance the runtime is supposed to owe; the challenger submits the counter-leaf and the contract compares signatures and accrued balances. challengeRootConflict targets history forks: two committed roots whose parent references or sequence numbers contradict each other are mutually exclusive and the contract invalidates the later commit.

A successful challenge invalidates the disputed root, freezes any withdrawals that referenced it, and forces the runtime to recompute and recommit from the last known-good state. A failed challenge consumes the challenger's posted bond and leaves the root in place. The economic asymmetry — bond loss for false alarms, vault-scale impact prevention for correct alarms — is deliberate. It rewards the discipline of submitting reproducible counter-examples rather than speculative complaints, while still keeping the contest path open to any address that can produce one.

This is why a Dexter withdrawal does not rest on trusting the runtime in isolation. It rests on a committed root, a verifiable proof, a history that cannot be silently rewritten, a window in which any third party can challenge, and a multi-sig vault that posts every finalization to Base.