Get Started
Slashing & Rehabilitation
Lightchain AI workers stake 50,000 LCAI on mainnet (5,000 on testnet) to be eligible for inference jobs. That stake is the lever the protocol pulls when a worker misbehaves: the stake is reduced (slashed), and after enough offenses the worker is temporarily removed from the eligible set (suspended). Suspension is always recoverable — there is no permanent tombstoning in the current design — but the operator must explicitly callreinstate() once the cooldown has passed.
This page covers every offense that can lead to a slash, how the slash propagates through the contracts, the states a worker can end up in, and the exact runbook for getting a suspended worker back online.
Slashing offenses
A worker can be slashed for three reasons. All three are enforced byJobRegistry and result in a call to one of WorkerRegistry's slash functions (slash, slashWithBounty, slashWithBountyBps), all callable only by JobRegistry.
The slash amount is computed as:
CodeHTML
maxSlashBps, currently 5,000 (50%). The owner of AIConfig (the protocol Safe) can change maxSlashBps up to 10,000.
The current values for timeoutSlashBps, completionTimeoutSlashBps, disputeSlashBps, minWorkerStake, suspensionThreshold, and suspensionCooldown are all defined in AIConfig and listed in Governance & Protocol Parameters.
Live values (checked 2026-10-21). Both networks have timeoutSlashBps, completionTimeoutSlashBps and disputeSlashBps at 0, set for the move to dispatcher-free mode. Mainnet additionally has suspensionThreshold raised to 1,000,000, so nothing suspends automatically there; testnet keeps the threshold at 3. Offences are still recorded at 0 bps and count once the rates and thresholds are restored. Testnet's ackTimeout is 119 s.
CodeBASH
How a slash propagates
When any of the three offenses fires, the contracts execute the following sequence:JobRegistrycalls one ofWorkerRegistry's slash functions. They areonlyJobRegistry— no other contract or EOA can slash directly.- The worker's stake is reduced by
slashAmount. Nothing is burned: the amount goes to theslashedFundspool inWorkerRegistry, minus a keeper bounty paid to the caller for timeouts (timeoutBountyBps, 10% today). Only the owner (the protocol Safe) can withdraw the pool, withwithdrawSlashedFunds(), and it goes to the Treasury. WorkerSlashed(address indexed worker, uint256 amount, uint256 newStake)is emitted.- If
newStake < minWorkerStake, the worker is immediately removed from every model's eligible set.WorkerDeactivated(worker, modelId)is emitted once per model. The worker can no longer be assigned new jobs. - The worker's
offenseCountis incremented. - If
offenseCount >= suspensionThreshold(default3), the worker is suspended:isSuspended = true,suspendedUntil = block.timestamp + suspensionCooldown(default 7 days), andWorkerSuspended(worker, until)is emitted. The worker is again removed from every eligible set if not already.
minWorkerStake keeps receiving jobs. Only the suspended state — or the below-minimum-stake state — actually takes the worker offline from the network's perspective: its claimSession transactions revert (see dispatcher-free mode).
Worker states
reinstate() clears both isSuspended and resets offenseCount to 0. There is no permanent removal — a worker can be suspended, reinstated, suspended again, and reinstated again indefinitely. Each suspension consumes another 7 days of downtime and, at default rates, at least 3,000 LCAI of stake (three offenses at 2%); nothing while the rates are 0.
How disputes lead to slashing
The most expensive offense (15%) comes from losing a dispute. Two paths trigger it:- Consumer-filed dispute. A consumer who is unhappy with the response can call
JobRegistry.disputeJob(jobId)withindisputeWindow(default 24 h) by posting a bond proportional to the job fee. The Disputer service re-executes the prompt against the same model and compares the worker's response to the re-execution using cosine similarity. If similarity <similarityThreshold(default 60%), the verdict is "worker guilty" and the worker is slashed bydisputeSlashBps. The consumer's bond is returned and the job fee is refunded. - Canary sampling. Independently of consumer behavior, the Disputer canary-samples ~
samplingRateBps(default 5%) of completed jobs and runs the same re-execution check. A guilty verdict slashes the worker identically. - Response mismatch. If a consumer can produce the worker's signed ciphertext and prove
keccak256(ciphertext) != job.responseCiphertextHash, callingJobRegistry.disputeResponseMismatch(jobId, ciphertext, signature)slashes the worker bydisputeSlashBpswithout going through similarity scoring at all.
Rehabilitation runbook
If your worker has been suspended, recover it in three steps: wait out the cooldown, top up the stake if a slash took it under the minimum, then reinstate. Thelightchain-worker CLI has a command for each of the last two, from release v0.0.2 on. Each one checks the on-chain state first and sends nothing when the call would fail:
CodeBASH
cast send against WorkerRegistry, which works with any worker version; the rest of this section shows that path.
The examples below assume you already have these environment variables set as in the standard Run a Worker — Mainnet guide:
CodeBASH
WorkerRegistry address above is the mainnet precompile-style fixed address; see Contract Addresses for the canonical list.)
1. Confirm the worker is suspended and read the cooldown deadline
CodeBASH
getSuspendedUntil returns Unix seconds. The cooldown has expired once block.timestamp >= suspendedUntil. Compare against current chain time:
CodeBASH
preflight from the run-a-worker guide: its suspended line shows the offense count and when the cooldown ends. (status prints registration and keys only.)
2. Top up stake if it fell below the minimum
If the slashes that caused suspension also pushed your stake under 50,000 LCAI,reinstate() will clear the suspension flag but will not re-add you to model eligible sets — the contract requires stake >= minWorkerStake for that.
Compare the current stake with the minimum, then top up the difference:
CodeBASH
CodeBASH
topUpStake() is not a substitute for reinstate(). Topping up alone does not clear the isSuspended flag — you must still call reinstate() once the cooldown has elapsed. Always treat reinstate() as the canonical path out of suspension.
3. Call reinstate() once the cooldown has passed
CodeBASH
- Reverts with
StillSuspended(worker, suspendedUntil)if the cooldown has not elapsed. - Reverts with
WorkerNotSuspended(worker)if the worker is not currently suspended. - Otherwise: clears
isSuspended, resetsoffenseCount = 0, and re-adds the worker to the eligible set for every supported model that is still whitelisted and enabled (assumingstake >= minWorkerStake). - Emits
WorkerReinstated(address indexed worker).
reinstate() has no fee — you only pay gas. Eligibility is read on-chain at claim time, so the worker can win sessions as soon as the transaction is mined.
4. Verify recovery
- Confirm
WorkerReinstatedis present in the transaction receipt:CodeBASH - Re-run
preflightfrom Run a Worker — Mainnet § Step 7: Preflight and confirm its line reads[PASS] suspended no. - Tail the worker container logs and look for
claimed session requestlines.
Events emitted
The authoritative event signatures fromIWorkerRegistry.sol:
CodeSOLIDITY
WorkerSlashedtypically pairs with theJobTimedOutevent or with aDisputeResolved(workerGuilty=true)event in the same transaction.- The slash that reaches
suspensionThresholdemitsWorkerSuspendedin the same transaction, before its ownWorkerSlashed. WorkerDeactivatedis emitted per model only when a slash leaves the stake belowminWorkerStake, also beforeWorkerSlashed. A suspension removes the worker from the eligible sets without it.
Parameter reference
These are the defaults at genesis. All can be changed by the owner ofAIConfig (the protocol Safe).
For the current values see Governance & Protocol Parameters.
Related pages
- Run a Worker — Mainnet — base operator guide for setting up and registering a worker.
- Worker API — REST and GraphQL surface for querying slash and suspension history.
- AIVM EL Architecture — Verification — full description of the Disputer pipeline.
- Governance & Protocol Parameters — current on-chain values for every parameter referenced here.
- Contract Addresses — canonical
WorkerRegistry,JobRegistry, andAIConfigaddresses.