From 643e8495bcc14527f4a2f2e00c47e95e3d76f2d4 Mon Sep 17 00:00:00 2001 From: Edgars Date: Fri, 3 Jul 2026 11:42:21 +0100 Subject: [PATCH 1/2] docs(validators): add staking penalties & quarantine recovery pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two validator-ops pages so operators can look up quarantine, ban, idleness, and strike semantics on docs.genlayer.com — previously the slashing concept page never used any of those terms. - staking-penalties: idleness strike system, quarantine vs temporary vs permanent ban, the slashing schedule (lazy + 2-epoch time-locked), and a table mapping monitoring status to on-chain protocol states. - quarantine-recovery: operator runbook to diagnose (strikes vs below-minimum vs not-primed/version/RPC), recover per cause, and know when to escalate to permanent ban. Wires both into pages/validators/_meta.json and cross-links from the setup guide, the Genesis Epoch 0 section of the staking guide, and the slashing concept page. Facts sourced from the genlayer-consensus staking-system spec (v0.6-dev). --- pages/developers/staking-guide.mdx | 6 + .../optimistic-democracy/slashing.mdx | 12 ++ pages/validators/_meta.json | 2 + pages/validators/quarantine-recovery.mdx | 165 ++++++++++++++++++ pages/validators/setup-guide.mdx | 6 + pages/validators/staking-penalties.mdx | 159 +++++++++++++++++ 6 files changed, 350 insertions(+) create mode 100644 pages/validators/quarantine-recovery.mdx create mode 100644 pages/validators/staking-penalties.mdx diff --git a/pages/developers/staking-guide.mdx b/pages/developers/staking-guide.mdx index df228bdc..930058ce 100644 --- a/pages/developers/staking-guide.mdx +++ b/pages/developers/staking-guide.mdx @@ -378,6 +378,10 @@ A: Yes, if you meet the minimum requirements. Stakes from epoch 0 carry forward **Q: What happens to my stake if I joined in epoch 0 but my node doesn't call validatorPrime() in epoch 2?** A: You'll be excluded from validator selection in epoch 4, but your stake remains. Once priming resumes, you'll be eligible for selection again. + + Once the network is operational (epoch 2+), validators are subject to idleness strikes, quarantine, and bans. See [Staking Penalties & Validator Lifecycle](/validators/staking-penalties) for the full model, and [Quarantine Recovery](/validators/quarantine-recovery) if your validator is ever excluded. + + --- ## Common Scenarios @@ -469,4 +473,6 @@ genStaking.validatorClaim(validatorWallet); - [Staking Concepts](/understand-genlayer-protocol/core-concepts/optimistic-democracy/staking) - How staking works in GenLayer - [Unstaking](/understand-genlayer-protocol/core-concepts/optimistic-democracy/unstaking) - Unstaking process details - [Slashing](/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing) - Slashing penalties and conditions +- [Staking Penalties & Validator Lifecycle](/validators/staking-penalties) - Idleness strikes, quarantine, bans, and the slashing schedule +- [Quarantine Recovery](/validators/quarantine-recovery) - Operator runbook for a quarantined or not-active validator - [GenLayer CLI Staking Commands](/api-references/genlayer-cli#staking-operations-testnet) - CLI reference for staking diff --git a/pages/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing.mdx b/pages/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing.mdx index 00737911..03317669 100644 --- a/pages/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing.mdx +++ b/pages/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing.mdx @@ -27,3 +27,15 @@ Validators in GenLayer can be slashed for several reasons: ### Amount Slashed The amount slashed varies based on the severity of the violation and the specific rules set by the GenLayer platform. The slashing amount is designed to be substantial enough to deter malicious or negligent behavior while not being excessively punitive for honest mistakes. + +## Slashing, Idleness, Quarantine, and Bans + +Slashing is the **economic** penalty (stake is reduced). It works alongside the **operational** penalties that stop a validator from being selected: + +- **Idleness** — a validator selected for a transaction that does not respond (commit/reveal) in time. Repeated idleness within an epoch accumulates **strikes**. +- **Quarantine / temporary ban** — a temporary exclusion (from idleness strikes or an in-progress deterministic-violation tribunal) that **recovers automatically** after the affected epoch(s). +- **Permanent ban** — a terminal exclusion applied after a deterministic-violation conviction (provable fraud), which does not auto-recover. + +Slashing is applied lazily at quarantine/ban enforcement — a recorded penalty becomes enactable roughly two epochs after the event and is deducted the next time the validator is primed. + +For the full lifecycle, strike thresholds, the slashing schedule, and how monitoring status maps to these states, see [Staking Penalties & Validator Lifecycle](/validators/staking-penalties). For a hands-on recovery runbook, see [Quarantine Recovery](/validators/quarantine-recovery). diff --git a/pages/validators/_meta.json b/pages/validators/_meta.json index d1fda8ca..18427a42 100644 --- a/pages/validators/_meta.json +++ b/pages/validators/_meta.json @@ -1,5 +1,7 @@ { "setup-guide": "Setup Guide", + "staking-penalties": "Staking Penalties & Lifecycle", + "quarantine-recovery": "Quarantine Recovery", "monitoring": "Monitoring & Telemetry", "system-requirements": "System Requirements", "genvm-configuration": "GenVM Configuration", diff --git a/pages/validators/quarantine-recovery.mdx b/pages/validators/quarantine-recovery.mdx new file mode 100644 index 00000000..a3ad7c6b --- /dev/null +++ b/pages/validators/quarantine-recovery.mdx @@ -0,0 +1,165 @@ +--- +description: "Operator runbook for recovering a GenLayer validator that is quarantined, banned, or not active: diagnose the cause, follow the recovery path, and know when to escalate." +--- + +import { Callout } from "nextra-theme-docs"; + +# Quarantine Recovery + +Your validator shows as **quarantined**, **banned**, or **not active**, and you need it earning again. This runbook takes you from symptom to fix: diagnose the cause, apply the recovery path for that cause, and escalate only when you actually need to. + +For the full model behind these states — strikes, quarantine, bans, and slashing — see [Staking Mechanics: Penalties & Validator Lifecycle](/validators/staking-penalties). + + + **The short version:** most exclusions are temporary and recover on their own. Idleness bans clear after the current + next epoch. Below-minimum validators need a top-up. A validator that simply stopped priming just needs its node priming again. Permanent bans are the only state that does not self-heal — and on testnet, none have occurred. + + +## Diagnose the Cause + +Before doing anything, find out **which** state you are in. Run these against your validator wallet address: + +```bash copy +# Is my validator in the active set at all? +genlayer staking active-validators + +# What does the network think of my validator (stake, status, pending ops)? +genlayer staking validator-info 0xYourValidatorWallet... + +# Am I quarantined? +genlayer staking quarantined-validators + +# Am I banned — and is it temporary (has an end epoch) or permanent? +genlayer staking banned-validators + +# What epoch are we in? (needed to know when a temporary ban clears) +genlayer staking epoch-info +``` + +Match what you find to one of these causes: + +| Symptom | Likely cause | Go to | +|---------|--------------|-------| +| In `banned-validators` with an **end epoch**, or in `quarantined-validators` | **Idleness strikes** → temporary ban/quarantine | [Strikes](#cause-1-idleness-strikes-quarantine--temporary-ban) | +| `validator-info` shows stake **below 42,000 GEN** | **Below minimum** → not active | [Below minimum](#cause-2-below-minimum-stake-not-active) | +| Absent from `active-validators`, **not** in any ban/quarantine list, stake is fine | **Not primed**, or a version / RPC problem | [Not primed](#cause-3-not-primed--version--rpc) | +| In `banned-validators` flagged **permanent** | **Deterministic-violation conviction** | [Escalate](#when-to-escalate) | + + + Do not top up stake or restart your node blindly. Topping up will not clear an **idleness** ban, and restarting will not fix a **below-minimum** stake. Diagnose first, then apply the matching path below. + + +## Cause 1: Idleness Strikes (Quarantine / Temporary Ban) + +**How you got here:** your validator was selected for transactions but didn't respond (commit/reveal) in time, accumulated strikes within one epoch, and hit the strike threshold. That bans it for the **current and next epoch**. A quarantine tied to a deterministic-violation tribunal behaves similarly but resolves when the tribunal does. + +**Recovery path — wait one epoch, then confirm priming:** + +1. **Confirm it is idleness-based**, not a tribunal quarantine: `banned-validators` will list an **end epoch** for an idleness ban. Note that epoch. +2. **Fix the root cause of the misses** so it does not immediately recur — see [Prevent idleness strikes](#prevent-idleness-strikes) below. Recovering only to be re-banned next epoch helps no one. +3. **Wait for the ban window to pass.** Idleness bans clear automatically at the start of the end epoch — there is no "unban" you need to call. Use `epoch-info` to watch the current epoch advance past the end epoch. +4. **Ensure your node primes** for the upcoming epoch so it re-enters the active set the moment the ban lifts: + + ```bash copy + genlayer staking validator-info 0xYourValidatorWallet... # verify priming / pending state + ``` + + Priming is normally automatic — your node calls `validatorPrime()` each epoch. If it isn't happening, treat it as a [not-primed](#cause-3-not-primed--version--rpc) problem in parallel. + + + You cannot manually clear an idleness ban early — it is timed to the epoch boundary. Your job is to (a) stop the misses and (b) make sure the node primes so it rejoins selection automatically. Because strikes **reset every epoch**, once you fix the underlying cause the counter starts fresh. + + +### Prevent Idleness Strikes + +Idleness almost always traces back to the node not answering in time when selected. Check, in rough order of likelihood: + +- **Node health / uptime** — the node was down, restarting, or unreachable during a round it was selected for. Keep it running under a supervisor (`systemd`, `screen`/`tmux`, or the Docker `restart: unless-stopped` policy from the [Setup Guide](/validators/setup-guide)). +- **LLM provider reachability** — Intelligent Contract execution needs your configured LLM. If the provider is slow, rate-limited, or the API key expired, the node can miss its response window. Verify with `./bin/genlayernode doctor`. +- **GenVM modules** — the `web` and `llm` modules must be running (or `genvm.manage_modules: true`). If they are down, execution stalls. +- **ZKSync full node / RPC** — a lagging or unreachable GenLayer-chain RPC means the node can't read state or submit votes in time. Confirm the RPC and WebSocket URLs in `config.yaml` are healthy. +- **Clock / sync** — a node behind on sync may act on stale slot information and miss phase deadlines. + +## Cause 2: Below-Minimum Stake (Not Active) + +**How you got here:** "not active" (or "not participating" in the sense of not being in the active set) because your **self-stake fell below the minimum** — the 42,000 GEN reference minimum for validators. This is **distinct from quarantine**: you were not penalized, you simply no longer meet the bar for selection. It shows up as a low stake figure in `validator-info`, and the validator will **not** appear in any ban or quarantine list. + +**Recovery path — top up, then re-prime:** + +1. **Deposit enough to get back above the minimum:** + + ```bash copy + genlayer staking validator-deposit --amount gen + ``` + +2. **Let the deposit activate.** Deposits follow the **epoch +2 activation rule** — staged one epoch, active the next, and only if `validatorPrime()` runs in between. Watch it with: + + ```bash copy + genlayer staking validator-info 0xYourValidatorWallet... + ``` + +3. **Confirm priming happens** across the activation window so the topped-up stake is committed and the validator re-enters the active set. + + + A top-up is **not** instant — plan for the +2 epoch activation delay before the validator is selectable again. Depositing does nothing for an **idleness** ban; only use this path when the diagnosis is genuinely below-minimum stake. + + +## Cause 3: Not Primed / Version / RPC + +**How you got here:** the validator meets the minimum and isn't banned, but it's missing from the active set because `validatorPrime()` wasn't called for the upcoming epoch — or the node can't do its job because of a version mismatch or a broken RPC connection. If priming stops, the validator is **excluded from the next epoch** (no rewards), though its stake is untouched. + +**Recovery path — restore priming:** + +1. **Verify the node is actually running as a validator**, not silently as a full node. This happens when the operator key or validator wallet address is missing from the config — the [Setup Guide](/validators/setup-guide#running-the-node) calls this out explicitly. Both must be set. +2. **Run diagnostics:** + + ```bash copy + ./bin/genlayernode doctor + ``` + + This checks consensus-contract accessibility, GenVM module health, LLM connectivity, and ZKSync node reachability — the usual reasons priming silently fails. +3. **Check version.** Running an outdated node can cause it to fall out of step with the network. List available versions and upgrade if you are behind (see the [Upgrade Guide](/validators/upgrade) and the [Setup Guide download steps](/validators/setup-guide#download-the-node-software)). +4. **Confirm RPC / WebSocket connectivity.** A lagging or unreachable GenLayer-chain RPC prevents the node from priming on time. Verify the `genlayerchainrpcurl` and `genlayerchainwebsocketurl` values in `config.yaml`. +5. **If priming must be nudged manually**, it is permissionless — anyone can prime a validator: + + ```bash copy + genlayer staking validator-prime --validator 0xYourValidatorWallet... + ``` + + Longer term, your node should prime automatically every epoch; a manual prime is a stopgap, not a fix for a node that has stopped priming on its own. + + + Priming is **permissionless and incentivized** — anyone can call it, and whoever primes a validator with a pending slash earns 1% of the slashed amount. This means a healthy validator is normally kept primed by its own node, but the network can also prime it. If yours consistently needs manual priming, the underlying node problem still needs fixing. + + +## When to Escalate + +Most states above are self-service. Escalate — rather than wait — when: + +- **`banned-validators` flags your validator as permanent.** A permanent ban comes from a **deterministic-violation conviction** (provable fraud), not from downtime, and it **does not auto-recover**. On testnet, no validator has hit permanent ban, so seeing this is unexpected and worth raising with the team. Recovery generally means standing up a **new** validator; the banned wallet will not come back on its own. +- **A temporary ban does not clear after its end epoch.** If `epoch-info` shows the current epoch has passed the end epoch reported in `banned-validators` but the validator is still excluded, something is off beyond a normal idleness ban. +- **You've corrected the root cause and still can't re-enter the active set** after a full activation window — for example, priming succeeds, stake is above minimum, `doctor` is clean, yet the validator never rejoins `active-validators`. +- **You suspect an incorrect slash or ban.** Bans and slashes carry a **2-epoch governance delay** specifically so an incorrect penalty can be reversed before it takes effect. If you believe a penalty is wrong, raise it within that window rather than waiting for it to enact. + + + A **permanent ban** is the one state this runbook cannot walk you out of. If you are genuinely permanently banned, do not wait for a recovery that will not come — escalate, and plan to redeploy a fresh validator. Everything else on this page recovers with patience plus the right fix. + + +## Quick Reference + +| Diagnosis | Recovery | Auto-recovers? | +|-----------|----------|:--------------:| +| Idleness strikes (temporary ban / quarantine) | Fix the cause of the misses, **wait** out current + next epoch, keep priming | Yes | +| Deterministic-violation tribunal quarantine | Wait for tribunal to resolve | Yes (on resolution) | +| Below-minimum stake (not active) | **Top up** with `validator-deposit`, wait +2 epochs, re-prime | After top-up | +| Not primed | Restore automatic priming; `doctor`; nudge with `validator-prime` if needed | Once priming resumes | +| Version / RPC problem | Upgrade node, fix RPC/WebSocket URLs, re-run `doctor` | Once fixed | +| Permanent ban | **Escalate**; redeploy a new validator | No | + +## Related Resources + +- [Staking Mechanics: Penalties & Validator Lifecycle](/validators/staking-penalties) — the full model behind these states +- [Setup Guide](/validators/setup-guide) — installation, staking, priming, and running the node +- [Upgrade Guide](/validators/upgrade) — keeping your node version current +- [Monitoring & Telemetry](/validators/monitoring) — dashboards and alerting to catch idleness early +- [Slashing (concept)](/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing) — protocol-level slashing rationale +- [`genlayer staking validator-info`](/api-references/genlayer-cli/staking/staking/validator-info) · [`banned-validators`](/api-references/genlayer-cli/staking/staking/banned-validators) · [`quarantined-validators`](/api-references/genlayer-cli/staking/staking/quarantined-validators) · [`validator-deposit`](/api-references/genlayer-cli/staking/staking/validator-deposit) · [`validator-prime`](/api-references/genlayer-cli/staking/staking/validator-prime) · [`epoch-info`](/api-references/genlayer-cli/staking/staking/epoch-info) diff --git a/pages/validators/setup-guide.mdx b/pages/validators/setup-guide.mdx index 08d86e39..6d92e32c 100644 --- a/pages/validators/setup-guide.mdx +++ b/pages/validators/setup-guide.mdx @@ -12,6 +12,8 @@ Validators require both a staking deposit and a validator priming transaction to For a deeper understanding of how staking works in GenLayer, see the [Staking documentation](/understand-genlayer-protocol/core-concepts/optimistic-democracy/staking). +Once your validator is running, see [Staking Penalties & Validator Lifecycle](/validators/staking-penalties) to understand idleness strikes, quarantine, and bans — and the [Quarantine Recovery runbook](/validators/quarantine-recovery) if your validator ever shows as quarantined or not active. + ## System Requirements | Resource | Requirement | @@ -171,6 +173,10 @@ genlayer staking validator-claim genlayer staking set-identity --validator 0x... --moniker "New Name" ``` + + If your validator shows as **quarantined**, **banned**, or **not active**, follow the [Quarantine Recovery runbook](/validators/quarantine-recovery) to diagnose the cause and recover. For the mechanics behind those states — idleness strikes, bans, and slashing — see [Staking Penalties & Validator Lifecycle](/validators/staking-penalties). + + --- ## Set Up the Validator Node diff --git a/pages/validators/staking-penalties.mdx b/pages/validators/staking-penalties.mdx new file mode 100644 index 00000000..2e0f82ae --- /dev/null +++ b/pages/validators/staking-penalties.mdx @@ -0,0 +1,159 @@ +--- +description: "Staking penalties and the validator lifecycle in GenLayer: idleness strikes, quarantine, temporary and permanent bans, slashing, and how monitoring status maps to on-chain protocol states." +--- + +import { Callout } from "nextra-theme-docs"; + +# Staking Mechanics: Penalties & Validator Lifecycle + +This page explains what happens to a validator that misbehaves or goes offline: the **idleness strike system**, **quarantine**, **temporary and permanent bans**, and **slashing**. It also maps the status labels you see while monitoring to the underlying protocol states, so an operator watching a dashboard can tell exactly what the network thinks of their validator. + +If your validator is already flagged and you just need the fix, jump straight to the [Quarantine Recovery runbook](/validators/quarantine-recovery). For everyday setup and operation, see the [Setup Guide](/validators/setup-guide). + + + All values on this page (strike thresholds, slash percentages, minimum stake, epoch length) are governance parameters or testnet defaults. Treat them as **reference/default** values — final mainnet values are still to be determined and several can be changed by on-chain governance without a code change. + + +## The Validator Lifecycle at a Glance + +A validator moves between a small number of states. Only one of them — **active** — earns rewards and gets selected for transactions. + +| State | Selected for transactions? | Earning rewards? | How you got here | How you leave | +|-------|:--------------------------:|:----------------:|------------------|---------------| +| **Active** | Yes | Yes | Stake ≥ minimum, primed each epoch | Miss priming, drop below minimum, or get quarantined/banned | +| **Not active** (below minimum) | No | No | Stake fell **below the minimum** | Top up stake to the minimum, then re-prime | +| **Not participating** (not primed) | No | No | `validatorPrime()` was **not called** for the upcoming epoch | Ensure your node primes each epoch | +| **Quarantined / temporarily banned** | No | No | **Idleness strikes** reached the threshold, or a deterministic-violation tribunal is in progress | Wait out the epoch(s); reactivation is automatic | +| **Permanently banned** | No | No | Convicted of a **deterministic violation** (provable fraud) | Does not auto-recover — a new validator is required | + + + "Active" is defined as being eligible for **selection in the current epoch**. A validator is inactive if it is below the minimum stake threshold, banned, or not primed. Being inactive is not the same as being penalized — a validator that simply forgot to prime loses selection but is not slashed. + + +## Idleness and Strikes + +**Idleness** means a validator was **selected for a transaction but did not respond in time** — it failed to commit or reveal its vote within the phase timeout. Idleness is about liveness: the validator was asked to do work and didn't. + +GenLayer tracks idleness with a **strike system**: + +- Each time a selected validator fails to respond, it accumulates **one strike**. +- Strikes are counted **per epoch** and **reset at every epoch boundary** — a fresh epoch starts you back at zero. +- When strikes reach the **strike threshold**, the validator is banned for the **current and next epoch**, then reactivated automatically. + + + The strike threshold is a **governance parameter** (`setStrikesMax()`), so the exact number can change. The documented default is **3 strikes** within a single epoch. Because strikes reset each epoch, an occasional single miss will not accumulate into a ban — sustained idleness within one epoch does. + + +**Failure to reveal a vote** is treated the same way: if a validator commits a vote but never reveals it within the timeout, that counts as **one strike** toward the ban threshold (in addition to being slashed — see [Slashing](#slashing)). + + + A consensus **timeout** decided by the validators (leader timeout / validator timeout) is a system-level determination and is **not** the same as idleness. Idleness is a validator failing to participate when it was selected — that is what earns strikes and slashing. + + +## Quarantine vs. Ban + +At the protocol level, GenLayer distinguishes **why** a validator is excluded, but exposes both through a single on-chain "excluded validators" query surface. For an operator, the important split is **temporary vs. permanent**. + +### Temporary: Quarantine / Idleness Ban + +Both of these are **temporary exclusions that recover automatically**: + +- **Idleness ban** — reaching the strike threshold bans the validator for the **current and next epoch**. It then reactivates on its own; no manual action is needed beyond continuing to prime. +- **Quarantine** — applied automatically when the consensus system detects a **deterministic violation** (validators with identical votes producing mismatched execution result hashes). Quarantine takes effect immediately and lasts **until the tribunal appeal process completes**, regardless of the outcome. While quarantined, the validator is not selected for new rounds and the leader is rotated to another validator so the transaction keeps moving. + +On-chain, temporary exclusions carry an **end epoch** and expire at the beginning of that epoch. Quarantine and (temporary) ban are, for query purposes, the same excluded-validator state — a monitoring tool will surface them together. + + + A quarantine that arises from an in-progress tribunal cannot be manually cleared — it resolves when the tribunal does. An **idleness** ban simply waits out its 1–2 epoch window. See the [Recovery runbook](/validators/quarantine-recovery) for how to tell which one you are in. + + +### Permanent Ban + +A **permanent ban** is the terminal state. It is applied after a **tribunal conviction** for a deterministic violation — for example, a leader found not to be in the majority after appeal, i.e. provable fraud (censorship or a forged receipt). A permanently banned validator is excluded from current, future, and (if not yet finalized) previous epochs, and **does not auto-recover**. + + + Permanent ban is reserved for provable, deterministic misbehavior — not for going offline. On testnet, no validator has reached permanent ban. If you believe your validator was permanently banned, it almost always indicates a genuine deterministic-violation conviction and should be escalated (see the [Recovery runbook](/validators/quarantine-recovery#when-to-escalate)) rather than waited out. + + +### Governance Delay Before a Ban Takes Effect + +Bans carry a **2-epoch governance delay** (`delayInEpochs = 2`) before execution, which gives governance a window to intervene and reverse an incorrect ban before it is enforced. + + + **Timestamp-based exclusion:** A banned validator is excluded from transactions **created after** the quarantine timestamp. For transactions that already existed **before** the ban, the validator may still be selected and **must keep participating**, or it risks additional slashing. This keeps in-flight transactions deterministic without disrupting them. + + +## Slashing + +**Slashing** is the economic penalty — GEN is removed from the validator's stake (and, for percentage-based slashes, partly from delegated stake). It is separate from banning: banning stops you from being *selected*, slashing reduces your *stake*. + +### When It Is Applied (Lazy + Time-Locked) + +Slashing does **not** hit your balance the instant the infraction happens. Two gates control it: + +1. **2-epoch delay** — a recorded penalty (idleness, failure-to-reveal, deterministic violation) becomes **enactable only ~2 epochs later** (`delayInEpochs = 2` in the slashing logic). At the ~1-day minimum epoch length, that is roughly a two-day window in which governance can reverse an incorrect slash. +2. **Lazy application at priming** — the deduction is actually applied the next time the validator is processed by **`validatorPrime()`** (the same call that rolls stake forward for the upcoming epoch). Slashing is "pull-based": it takes effect on the next prime, not on a fixed clock. + +Because priming is **permissionless**, anyone can trigger a pending slash. Whoever primes a validator that has a pending slash receives **1% of the slashed amount** immediately (deducted before the remainder is burned) — this pays third parties to enforce slashing even if the validator never primes itself. + +### Slashing Schedule + +The percentages below are the documented testnet schedule. Percentage-based slashes (idleness, failure-to-reveal, deterministic violation) split the slashed amount **80% from the validator's self-stake and 20% from delegated stake**. + +| Trigger | What is slashed | Self / delegated split | +|---------|-----------------|:----------------------:| +| **Idleness** (selected but did not respond in time) | ~1% of stake | 80% / 20% | +| **Failure to reveal vote** | ~1% of stake | 80% / 20% | +| **Deterministic violation** (provable fraud) | Leader ~5%, other minority validators ~1%, capped at ~10% per epoch | 80% / 20% | +| **Incorrect result** (voted with the losing side after appeal) | Negative fee charge to stake (burned) **plus** forfeited reward | Pro-rata to stake | +| **Failed appeal** | 100% of the appeal bond (forfeited to the round's validators — **not** burned) | — | + + + Slashed tokens from percentage-based penalties are **burned** (permanently removed from supply). Incorrect-result penalties are deducted pro-rata across self-stake and delegated stake in proportion to their share of the validator's total stake at priming time. A **failed appeal** forfeits the bond to the round's validators rather than burning it. + + + + **Slash-evasion caveat (known limitation):** because enactment is lazy, a validator that **exits before it is next primed** can avoid a pending slash — the deduction is only computed at priming. The 2-epoch delay bounds the window and the 1% caller incentive pays others to prime-and-slash first, but the gap is only partially mitigated. + + +## Mapping Monitoring Labels to Protocol States + +When you watch a validator — via `genlayer staking validator-info`, the banned/quarantined lists, or a Grafana dashboard fed by node metrics — the status you see corresponds to one of the protocol states above. Use this table to cross-reference what the monitoring surface reports against what the network is actually doing: + +| What you observe | Protocol state | What it means | First action | +|------------------|----------------|---------------|--------------| +| Validator absent from the **active set** (`active-validators`) but not in any ban/quarantine list | **Not participating** (not primed) or **not active** (below minimum) | Node isn't being selected; either priming stopped or stake dropped below the minimum | Check priming and stake — see [recovery](/validators/quarantine-recovery#diagnose-the-cause) | +| Validator appears in the **quarantined** list (`quarantined-validators`) | **Quarantined** | Excluded due to idleness strikes or an in-progress deterministic-violation tribunal | Identify which; usually **wait** — see [recovery](/validators/quarantine-recovery) | +| Validator appears in the **banned** list (`banned-validators`) with an **end epoch** | **Temporary ban** | Idleness/temporal ban that expires automatically at the listed epoch | Wait out the window, keep priming | +| Validator appears in the **banned** list flagged **permanent** | **Permanent ban** | Deterministic-violation conviction; does not auto-recover | [Escalate](/validators/quarantine-recovery#when-to-escalate) | +| Stake reported **below the minimum** in `validator-info` | **Not active** (below minimum) | Fell under the 42,000 GEN reference minimum | Top up, then re-prime | + + + The on-chain excluded-validator query returns, per validator, an **end epoch** ("banned until") and a **permanent** flag. A temporary quarantine or ban shows a concrete end epoch and clears at the start of that epoch; a permanent ban is marked accordingly and never expires on its own. Query these with `genlayer staking banned-validators` and `genlayer staking quarantined-validators`. + + +## Reference Parameters + +| Parameter | Reference / default value | Notes | +|-----------|---------------------------|-------| +| Epoch length | ~24 hours (minimum 1 day) | Can extend past 24h due to finalization constraints | +| Validator minimum self-stake | 42,000 GEN | Governance-configurable; below this the validator is **not active** | +| Delegator minimum stake | 42 GEN | Per validator | +| Idleness strike threshold | 3 strikes per epoch (default) | Governance parameter (`setStrikesMax()`); strikes reset each epoch | +| Idleness ban duration | Current + next epoch | Then auto-reactivates | +| Slash enactment delay | ~2 epochs | Applied lazily at the next `validatorPrime()` | +| Unbonding period (exit) | 7 epochs | Applies to voluntary exits, unrelated to penalties | + + + These are **reference/default** values for testnet. Minimum-stake figures, strike thresholds, and slash percentages are all subject to change — final mainnet values are TBD and several are adjustable by governance. + + +## Related Resources + +- [Quarantine Recovery](/validators/quarantine-recovery) — operator runbook for a quarantined or not-active validator +- [Setup Guide](/validators/setup-guide) — validator installation, staking, and priming +- [Monitoring & Telemetry](/validators/monitoring) — metrics, dashboards, and alerting +- [Staking Contract Guide](/developers/staking-guide) — direct Solidity interactions, including [Genesis Epoch 0](/developers/staking-guide#genesis-epoch-0) +- [Slashing (concept)](/understand-genlayer-protocol/core-concepts/optimistic-democracy/slashing) — protocol-level rationale for slashing +- [Staking (concept)](/understand-genlayer-protocol/core-concepts/optimistic-democracy/staking) — epochs, shares, weights, and rewards +- [`genlayer staking validator-info`](/api-references/genlayer-cli/staking/staking/validator-info) · [`banned-validators`](/api-references/genlayer-cli/staking/staking/banned-validators) · [`quarantined-validators`](/api-references/genlayer-cli/staking/staking/quarantined-validators) From a0c650bf65993a6936d667d70c3fedaac97bd408 Mon Sep 17 00:00:00 2001 From: Edgars Date: Fri, 3 Jul 2026 11:48:13 +0100 Subject: [PATCH 2/2] docs: strike threshold is 5 (current network setting), not 3 --- pages/validators/staking-penalties.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/validators/staking-penalties.mdx b/pages/validators/staking-penalties.mdx index 2e0f82ae..f5961d4f 100644 --- a/pages/validators/staking-penalties.mdx +++ b/pages/validators/staking-penalties.mdx @@ -41,7 +41,7 @@ GenLayer tracks idleness with a **strike system**: - When strikes reach the **strike threshold**, the validator is banned for the **current and next epoch**, then reactivated automatically. - The strike threshold is a **governance parameter** (`setStrikesMax()`), so the exact number can change. The documented default is **3 strikes** within a single epoch. Because strikes reset each epoch, an occasional single miss will not accumulate into a ban — sustained idleness within one epoch does. + The strike threshold is a **governance parameter** (`setStrikesMax()`), so the exact number can change. The current network setting is **5 strikes** within a single epoch. Because strikes reset each epoch, an occasional single miss will not accumulate into a ban — sustained idleness within one epoch does. **Failure to reveal a vote** is treated the same way: if a validator commits a vote but never reveals it within the timeout, that counts as **one strike** toward the ban threshold (in addition to being slashed — see [Slashing](#slashing)). @@ -139,7 +139,7 @@ When you watch a validator — via `genlayer staking validator-info`, the banned | Epoch length | ~24 hours (minimum 1 day) | Can extend past 24h due to finalization constraints | | Validator minimum self-stake | 42,000 GEN | Governance-configurable; below this the validator is **not active** | | Delegator minimum stake | 42 GEN | Per validator | -| Idleness strike threshold | 3 strikes per epoch (default) | Governance parameter (`setStrikesMax()`); strikes reset each epoch | +| Idleness strike threshold | 5 strikes per epoch (current network setting) | Governance parameter (`setStrikesMax()`); strikes reset each epoch | | Idleness ban duration | Current + next epoch | Then auto-reactivates | | Slash enactment delay | ~2 epochs | Applied lazily at the next `validatorPrime()` | | Unbonding period (exit) | 7 epochs | Applies to voluntary exits, unrelated to penalties |