When your app is challenged
Anyone can challenge a batch on Monad. Until the judges rule, nothing settles. Where the bench can rule on its own, your app keeps running and Monad catches up after the verdict.
A challenge names one committed batch and puts up a bond. The judges replay it, the validator and the challenger narrow the disagreement down to one transaction, and the bench votes. Until it does, nothing the node executed after that batch settles on Monad.
What your users see
Interlude can keep your app running through a dispute. It is switched on per app, off by default, and only where the bench’s judge bots can reach the vote on their own. Then calls answer as usual and the node queues its batches. It stops taking calls, until the verdict or until the reason goes, whenever the queue is at risk: a judge votes fraud, the validator’s move runs late, or too few bots answer with the vote a move away. Otherwise the app takes no calls until the verdict. Either way, put the banner on the page:
export const { DisputeBanner, useDispute } = createInterludeHooks(interlude);
function Header() {
// One line, or nothing while there is no dispute. With a className, your styles only:
// data-dispute carries the status.
return <DisputeBanner className="notice" />;
}
// The same state without React:
const state = await interlude.dispute();- verifying
- Verification in progress: this app keeps running, settlement on Monad resumes by 16:30. What you do meanwhile is confirmed by this app and settles after the verdict; it is rolled back if fraud is proven or no verdict comes in time.
- frozen
- Verification in progress: this app is paused until the judges rule
- dismissed
- Claim rejected by the judges: the challenger's bond was burned
- fraud
- Fraud proven: the validator was slashed and state after batch 40 was unwound
It reads the node’s health every 5 s, and the hub on Monad when the node cannot say. An outcome stays on screen for an hour.
What settles later
After a dismissal the node commits its queue in order, merged into as few batches as fit, and Monad catches up. settled waits through the whole dispute and never reports a queued call lost. waitSettled with a timeoutMs of your own ends with SettlementPausedError instead. Do not send a queued call again: it already ran.
The 2-hour cap
The node queues at most 2 hours of work, and 600 batches. Past that it takes no new calls until the verdict, and refuses them with SettlementPausedByDisputeError: nothing ran. What it queued keeps its place, and the banner says the app is paused.
Funds
Funds are never released from state that has not settled. The app’s delegated state stays locked on Monad through the dispute, and value only moves on Monad, so a cash-out made meanwhile pays once the verdict is in and the commit carrying it lands. If fraud is proven, the validator is slashed, every batch from the challenged one on is unwound, and the queue is dropped. If the judges do not vote in time, the session closes and the queue is dropped too. Either way settled rejects with SettlementLostError, reason: "dispute". The node shuts down with its session, so the SDK confirms the end on the hub before it says so, and asks the hub when the node stops answering.
