Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Implement a Graduated Warning System with Staking

Build a proportional disciplinary framework for decentralized applications. This guide covers smart contract design for tracking infractions, issuing warnings, and escalating to stake slashing.
Chainscore © 2026
introduction
TUTORIAL

How to Implement a Graduated Warning System with Staking

A practical guide to building a slashing mechanism that issues warnings before penalizing user funds, using smart contract staking.

A graduated enforcement system is a security and governance mechanism that escalates penalties based on the severity or frequency of a user's infractions. Instead of immediately slashing a staker's entire deposit for a minor violation, the system issues warnings or imposes smaller, incremental penalties first. This approach is common in Proof-of-Stake (PoS) networks and decentralized autonomous organizations (DAOs) to ensure fairness and deter malicious behavior without being overly punitive. Implementing such a system requires a smart contract that can track user states, define violation tiers, and execute corresponding actions.

The core logic involves managing a staker's status within the contract. Typically, you would create a mapping, like mapping(address => Enforcer.Status) public userStatus, where Status is an enum (e.g., CLEAN, WARNED, SLASHED). When a condition for a minor violation is met—such as missing a governance vote or being offline in a validator set—the contract logic should first check the user's current status. If the status is CLEAN, it transitions to WARNED and may emit an event. A subsequent violation while WARNED would then trigger a slashing penalty, moving the status to SLASHED and deducting a percentage of the staked funds.

Here's a simplified Solidity code snippet illustrating the state transition logic:

solidity
enum Status { CLEAN, WARNED, SLASHED }
mapping(address => Status) public status;
uint256 public constant SLASH_PERCENTAGE = 10; // 10% slash

function reportViolation(address user) external {
    Status currentStatus = status[user];
    if (currentStatus == Status.CLEAN) {
        status[user] = Status.WARNED;
        emit UserWarned(user, block.timestamp);
    } else if (currentStatus == Status.WARNED) {
        status[user] = Status.SLASHED;
        // Logic to slash 10% of user's staked balance
        _slashFunds(user, SLASH_PERCENTAGE);
        emit UserSlashed(user, SLASH_PERCENTAGE);
    }
    // If already SLASHED, no further action
}

This pattern ensures users receive a grace period to correct their behavior, which is crucial for network health and user retention.

For a production system, you must integrate this with a secure staking contract. The _slashFunds function would interact with the staking ledger to deduct tokens, which may be burned, sent to a treasury, or redistributed. Key considerations include:

  • Time-based resets: Should a WARNED status expire after a compliant period?
  • Violation tiers: Different actions (e.g., double-signing vs. downtime) might skip the warning stage entirely.
  • Governance: Who can call reportViolation? It should be a permissioned function, often restricted to a governance module or proven by cryptographic evidence.
  • Front-running: Design the contract to prevent users from withdrawing funds after being warned but before being slashed.

Real-world implementations can be studied in protocols like Cosmos SDK's Slashing module or Ethereum's consensus layer penalty system. These systems often have complex parameters, such as a slash_factor_downtime (e.g., 0.01%) for minor offenses and a slash_factor_double_sign (e.g., 5%) for severe ones. By starting with the basic state-machine pattern shown here and carefully parameterizing the escalation path, developers can create more humane and effective enforcement mechanisms for their staking applications.

prerequisites
TUTORIAL

Prerequisites and Setup

This guide details the technical prerequisites and initial setup required to implement a graduated warning system using a staking mechanism.

A graduated warning system with staking is a smart contract pattern where users deposit a stake (like ETH or a protocol's native token) as collateral. The system can then issue escalating warnings or penalties by progressively slashing this stake based on predefined, on-chain rules. This is commonly used in decentralized applications (dApps) for governance, service-level agreements, or behavior enforcement. Before writing any code, you must have a foundational understanding of Solidity, Ethereum development tools like Hardhat or Foundry, and the concept of ERC-20 tokens for the staking asset.

Your development environment must be configured. Install Node.js (v18+ recommended) and a package manager like npm or yarn. Initialize a new project and install core dependencies: a development framework (e.g., hardhat), the OpenZeppelin Contracts library for secure, audited base contracts (@openzeppelin/contracts), and a testing library like chai. You will also need an Ethereum wallet (MetaMask) with testnet ETH (from a faucet like Sepolia) for deployment and interaction. Set up a .env file to securely manage your private key and RPC URL using dotenv.

The core contract architecture involves at least two smart contracts. First, an ERC-20 token contract (or a reference to an existing one) that will be used as the staking asset. Second, the main WarningSystem contract. This contract must inherit from OpenZeppelin's Ownable for access control and ReentrancyGuard for security. It will need state variables to track each user's stakedAmount, their current warningLevel (e.g., 0 for none, 1 for minor, 2 for major), and a mapping of warningThresholds that define the stake slash percentage for each level.

Define the key functions your contract will expose. The stake(uint256 amount) function should transfer tokens from the user to the contract and update their staked balance. A issueWarning(address user, uint8 level) function, restricted to an owner or oracle, should increase the user's warning level and execute a corresponding slash via an internal _slashStake function. Finally, a withdraw() function allows users to retrieve their remaining, un-slashed stake. Always implement events like Staked, WarningIssued, and StakeSlashed for off-chain monitoring.

Thorough testing is a non-negotiable prerequisite. Write comprehensive unit tests using Hardhat/Waffle or Foundry's Forge. Test critical paths: successful staking, correct slash calculation for different warning levels, failed withdrawals when warnings are active, and proper access control on the issueWarning function. Use a forking testnet or a local Hardhat network to simulate real interactions. Consider edge cases, such as issuing multiple warnings or attempting to slash more than the user's stake.

Once tested, plan your deployment script. Use Hardhat deployment scripts or Foundry scripts to deploy the token and then the WarningSystem contract, passing the token's address to its constructor. Verify your contracts on block explorers like Etherscan for transparency. The final setup step is integrating the deployed contract with a front-end (using ethers.js or web3.js) or a backend service, enabling real users to stake and allowing authorized actors to trigger warnings based on your application's logic.

system-design-overview
SYSTEM ARCHITECTURE AND DESIGN

How to Implement a Graduated Warning System with Staking

A graduated warning system uses escalating penalties to deter protocol misbehavior. This guide explains how to architect one using staked collateral as an enforcement mechanism.

A graduated warning system is a governance or security mechanism that applies progressively severe penalties for repeated or escalating offenses, rather than an immediate, maximum punishment. This design is common in decentralized autonomous organizations (DAOs) for member conduct, oracle networks for data quality, or validator slashing protocols. The core principle is proportionality; a minor first infraction might trigger a warning, while a third offense could result in a significant stake slash. This approach improves user experience by allowing for corrections and provides a clear, transparent escalation path that enhances protocol security and fairness.

The system's architecture revolves around a state machine tracking participants. Each participant (e.g., a validator or delegate) has an associated warning score or strike count stored in a smart contract. Key events, like a governance proposal failing a sanity check or a validator missing a signature, are processed by a verification module. When the module confirms an infraction, it calls the enforcement contract to increment the user's strike count and execute the corresponding penalty tier. The contract must also manage appeals and state resets, often requiring a DAO vote or a time-based decay function for strike expiration.

Staking is the enforcement backbone of this system. Participants must lock a stake (e.g., ETH, protocol tokens) to participate. The penalty schedule is directly tied to this stake. For example, a first strike might incur a 1% stake slash and a temporary voting freeze. A second strike could escalate to a 10% slash and a longer cooldown. A third strike might result in full slashing and removal from the participant set. This creates a direct financial disincentive. The slashed funds are typically burned or sent to a treasury, ensuring the penalty has real economic weight.

Here is a simplified Solidity code structure for the core state and enforcement logic. It defines a mapping for strikes, a staking balance, and a function to penalize a user based on their current strike count.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract GraduatedWarningSystem {
    mapping(address => uint256) public strikeCount;
    mapping(address => uint256) public stakeBalance;
    address public governance;

    // Penalty schedule: slash percentages per strike count (1-indexed)
    uint256[] public slashPercentages = [0, 10, 25, 100]; // 0%, 10%, 25%, 100%

    event StrikeIssued(address indexed user, uint256 newStrikeCount, uint256 amountSlashed);

    function issueStrike(address _user) external {
        require(msg.sender == governance, "Unauthorized");
        uint256 strikes = strikeCount[_user] + 1;
        strikeCount[_user] = strikes;

        // Apply slash if within schedule
        if (strikes < slashPercentages.length) {
            uint256 slashPct = slashPercentages[strikes];
            uint256 slashAmount = (stakeBalance[_user] * slashPct) / 100;
            stakeBalance[_user] -= slashAmount;
            emit StrikeIssued(_user, strikes, slashAmount);
        } else {
            // For strikes beyond schedule, apply maximum penalty
            uint256 totalStake = stakeBalance[_user];
            stakeBalance[_user] = 0;
            emit StrikeIssued(_user, strikes, totalStake);
        }
    }
}

Critical design considerations include oracle selection for infraction reporting, appeal mechanisms, and parameter governance. The entity triggering the issueStrike function must be highly secure and trusted—often a multisig or the DAO itself. An appeal process might involve a time-locked challenge period or a jury of peers. The penalty schedule (slashPercentages) and stake requirements are system parameters that should be adjustable via governance to adapt to network conditions. Furthermore, consider implementing a strike decay mechanism where strikes are reduced after a period of good behavior, which encourages rehabilitation.

In practice, you can see variants of this pattern in live systems. Aave's Governance uses a proposal queuing system where malicious proposals can be canceled by guardians. Chainlink's oracle reputation framework indirectly employs graduated penalties, as nodes providing poor data lose future job assignments and staked LINK. When implementing your own, start with a conservative slash schedule and high governance thresholds. Use time-locked upgrades for the penalty contract to prevent malicious parameter changes. A well-architected graduated warning system creates a self-regulating community where the cost of misconduct is clear, proportional, and automatically enforced.

core-contract-components
GRADUATED WARNING SYSTEM

Core Smart Contract Components

A graduated warning system uses staking to enforce protocol rules through escalating penalties, from slashing to forced exit. This guide covers the key components for building one.

01

Stake Escrow and Deposit Logic

The foundation is a secure escrow contract that accepts and locks ERC-20 tokens. Implement deposit functions with validation to prevent zero-value stakes. Use a mapping like mapping(address => uint256) public stakes; to track deposits. This contract must also handle the transfer of slashed funds to a treasury or burn address.

02

Infraction Registry and Severity Levels

Define and store rule violations with associated severity. A common pattern is an enum: enum Severity { Warning, Minor, Major, Critical }. Store infractions in a struct: struct Infraction { Severity level; uint256 timestamp; }. Use events to log infractions for off-chain monitoring. This registry is the source of truth for the penalty engine.

03

Penalty Engine and Slashing Schedule

This component applies penalties based on infraction history. Implement a function that calculates slash amounts, such as 10% for a Minor infraction or 100% for Critical. The logic should check for repeat offenses, potentially increasing the penalty. Use a withdrawal delay or cooldown period instead of immediate slashing for lower-severity warnings.

04

Appeal and Governance Mechanism

Allow stakers to challenge infractions. Implement a timelocked appeal process that freezes the associated stake. For decentralized resolution, integrate with a governance module or oracle (like UMA or Chainlink) to adjudicate disputes. A successful appeal should reverse the penalty and refund the stake.

05

Forced Exit and Unstaking Logic

For repeated or critical violations, implement a forced exit. This function, callable by a guardian or governance, forcibly returns a user's remaining stake (minus penalties) and bans the address from future participation. Ensure the unstaking process has a delay (e.g., 7 days) to prevent front-running during an investigation.

step-1-violation-registry
FOUNDATION

Step 1: Building the Violation Registry

The first step in implementing a graduated warning system is to define and store the rules. This guide covers creating a smart contract registry that catalogs violation types, their severity, and associated penalties.

A violation registry is the core data structure for any on-chain governance or reputation system. It acts as a single source of truth, defining what constitutes a violation, its severity level (e.g., Minor, Major, Critical), and the corresponding penalty. This contract is typically immutable or upgradeable only via governance, ensuring rule consistency. Common violations in DeFi or DAO contexts include - failing to vote on a critical proposal, - missing a service-level agreement (SLA) for a validator, or - attempting to front-run a public transaction.

The registry is implemented as a mapping from a violationId (a bytes32 or uint256 identifier) to a structured Violation type. This struct should contain fields for description (a human-readable string), severityScore (a numerical weight), cooldownPeriod (a time lock before re-penalization), and action (an enum defining the penalty, such as Slash, Jail, or Warning). Storing this on-chain makes the rules transparent and verifiable by all participants, which is a cornerstone of trust-minimized systems.

Here is a simplified Solidity example of the registry's core structure:

solidity
enum PenaltyAction { Warning, Slash, Jail }

struct Violation {
    string description;
    uint8 severityScore; // e.g., 1-10
    uint256 cooldownPeriod;
    PenaltyAction action;
    uint256 slashAmountBps; // Basis points to slash if action is Slash
}

contract ViolationRegistry {
    mapping(bytes32 => Violation) public violations;
    
    function registerViolation(
        bytes32 violationId,
        string memory description,
        uint8 severityScore,
        uint256 cooldownPeriod,
        PenaltyAction action,
        uint256 slashAmountBps
    ) external onlyGovernance {
        violations[violationId] = Violation(
            description,
            severityScore,
            cooldownPeriod,
            action,
            slashAmountBps
        );
    }
}

Once deployed, the registry must be populated by governance. Each violationId can be a keccak256 hash of a descriptive string (e.g., keccak256('MISSED_VOTE')) for consistency. The severityScore is crucial as it will later determine the accumulation rate in a user's violation history. A slashing action might deduct a percentage of a user's staked tokens, while jailing could temporarily revoke their privileges. The registry itself does not enforce penalties; it simply defines them for other contracts to query.

This foundational step separates the definition of rules from their execution. By having a standalone registry, you can update the penalty logic or staking mechanics in a separate contract without redefining every violation. This modular design follows best practices for upgradeability and maintainability. The next step involves tracking individual user histories against this registry to implement the graduated warning logic.

step-2-staking-escrow
CONTRACT LOGIC

Step 2: Implementing the Staking Escrow Contract

This section details the implementation of a Graduated Warning System within a staking escrow contract, using Solidity to enforce escalating penalties for protocol violations.

A Graduated Warning System introduces a tiered penalty mechanism for protocol infractions, moving beyond binary slashing. The core contract state must track a staker's warning level, which increments with each violation. This is typically implemented with a mapping, such as mapping(address => uint8) public warningLevel;, where the level dictates the severity of the penalty applied. The system's rules are defined by constants like MAX_WARNING_LEVEL and arrays for corresponding penaltyPercentages (e.g., [0, 10, 25, 50, 100]). This structure allows for flexible, transparent enforcement.

The primary logic resides in an internal function, often called _applyWarning, which is invoked by other contract functions that detect violations (e.g., a keeper missing a commitment). This function checks if the staker is below the maximum level, increments their warningLevel, and then executes a proportional penalty. A critical implementation detail is ensuring the penalty is calculated correctly, for example: uint256 penalty = (stakedAmount * penaltyPercentages[level]) / 100;. The slashed funds can be burned or sent to a treasury, while the remaining stake stays locked, preserving the economic security of the escrow.

For the system to be effective, it must integrate seamlessly with the staking lifecycle. The stake function must initialize a user's warningLevel to zero. More importantly, the slash or release functions need to read the current warning level to determine the final penalty upon an unstaking request or a final adjudication. Emitting events like WarningIssued(address indexed staker, uint8 newLevel, uint256 penalty) is essential for off-chain monitoring and transparency. This design creates a clear, auditable history of compliance for each participant.

Testing this system requires verifying the escalation logic. Write unit tests (using Foundry or Hardhat) that simulate multiple violations for a single staker and assert that: the warning level increments correctly, the penalty percentage increases according to the defined schedule, the slashed amount is transferred accurately, and the contract correctly prevents escalation beyond MAX_WARNING_LEVEL. This ensures the contract behaves predictably under all conditions, which is paramount for user trust and protocol security.

When deploying, carefully consider the governance of the penalty parameters. Setting the MAX_WARNING_LEVEL and penaltyPercentages in the constructor or making them upgradeable via a governance contract allows the system to adapt. The goal is to disincentivize minor negligence without being overly punitive, and to reserve full slashing for repeated or severe offenses. This nuanced approach can improve protocol health by giving stakers a chance to correct behavior before losing their entire stake, aligning long-term incentives between stakers and the protocol.

step-3-enforcement-logic
IMPLEMENTING SLASHING

Step 3: Writing the Enforcement Logic

This section details how to program the core on-chain logic for a graduated warning system, moving from detection to action.

The enforcement logic is the smart contract function that executes the graduated penalties based on the severity of the violation. It must be deterministic, gas-efficient, and tamper-proof. This logic is typically triggered by an off-chain oracle or a permissioned role after a violation is verified. The core function will receive the validator's address and a violationSeverity parameter (e.g., an enum like Low, Medium, High) to determine the appropriate penalty tier.

A common implementation uses a switch or if-else statement to map severity to actions. For a Low severity offense, the contract might issue a warning by emitting a specific event and locking a small portion of staked tokens for a short cooldown period. A Medium offense could trigger a larger, temporary slashing of stake and a longer lock-up. The High severity tier would result in the most severe penalty: a significant, permanent slash of the validator's stake and immediate ejection from the active set.

Here is a simplified Solidity code snippet illustrating this structure:

solidity
enum Severity { Low, Medium, High }

function enforcePenalty(address validator, Severity severity) external onlyOracle {
    uint256 currentStake = stakes[validator];
    
    if (severity == Severity.Low) {
        // Issue warning, lock 5% for 7 days
        uint256 slashAmount = (currentStake * 5) / 100;
        _lockStake(validator, slashAmount, 7 days);
        emit WarningIssued(validator, slashAmount);
    } else if (severity == Severity.Medium) {
        // Slash 15%, lock for 30 days
        uint256 slashAmount = (currentStake * 15) / 100;
        _slashStake(validator, slashAmount);
        _lockStake(validator, 0, 30 days); // Lock remaining stake
        emit PenaltyEnforced(validator, slashAmount, "MEDIUM");
    } else if (severity == Severity.High) {
        // Slash 50% and eject
        uint256 slashAmount = (currentStake * 50) / 100;
        _slashStake(validator, slashAmount);
        _ejectValidator(validator);
        emit ValidatorEjected(validator, slashAmount);
    }
}

Critical to this logic are the internal _slashStake, _lockStake, and _ejectValidator functions. _slashStake should permanently burn or redistribute the slashed tokens. _lockStake prevents the validator from withdrawing or transferring the affected funds for a set duration. _ejectValidator removes the actor from the active validator set, often by setting a flag or deleting them from a mapping, which will be checked by the network's consensus or delegation logic.

When designing this system, you must carefully balance the penalty weights to disincentivize malicious behavior without being overly punitive for minor, honest mistakes. The parameters—slash percentages, lock-up durations, and severity thresholds—should be adjustable, possibly through a governance mechanism, to allow the system to adapt based on network experience and economic conditions. Always ensure the contract logic is thoroughly audited, as bugs in slashing code can lead to irreversible loss of funds and loss of trust in the protocol.

STAKING SLASHING FRAMEWORK

Violation Tier and Penalty Matrix

A graduated penalty system for protocol violations, correlating severity with slashing percentage and lock-up periods.

Violation TierDescription & ExamplesSlash %Stake Lock-upWarning Issued

Tier 1: Minor

Late oracle update, missed non-critical heartbeat

0.5%

7 days

Tier 2: Moderate

Single instance of incorrect validation, temporary downtime

2%

30 days

Tier 3: Major

Double-signing, malicious MEV extraction, protocol griefing

10%

90 days

Tier 4: Critical

Collusion attack, stealing user funds, protocol exploit

100%

Permanent

Recidivism Multiplier

Penalty for repeated offenses within a 90-day window

+50%

+30 days

step-4-integration-frontend
IMPLEMENTATION

Step 4: Frontend Integration and User Flow

This guide details how to build a frontend that connects to your smart contract, displays real-time staking status, and triggers graduated warnings based on user actions.

The frontend's primary role is to act as a real-time dashboard for the staking contract's warning system. It must fetch and display the user's current warningLevel and warningPoints from the contract's public view functions. Use a Web3 library like ethers.js or viem to connect. The key is to listen for the WarningIssued event emitted by the contract. When this event fires, the UI should update immediately to reflect the new warning state, providing instant feedback to the user. This creates a transparent and responsive experience.

To implement the graduated warnings, map the warningLevel integer (0-3) to distinct UI states. For example: Level 0 (Normal): Green indicator. Level 1 (Notice): Yellow banner with a simple message. Level 2 (Warning): Orange banner with a more urgent message and a link to documentation. Level 3 (Critical): Red banner, potentially disabling certain high-risk functions like unstaking or delegation, with a clear call-to-action to contact support. Each state should be visually distinct and escalate in prominence.

User flows must be designed to surface warnings contextually. When a user initiates an action that could incur a penalty—like an early unstake—the UI should first check their current warningLevel via a read call. If the level is 2 or higher, you can preemptively display a confirmation modal that explicitly states the potential penalty and their warning status. This proactive approach ensures informed consent and can deter behavior that would trigger an automated penalty from the contract.

Here is a simplified React component example using ethers.js to fetch and display a user's warning status:

javascript
import { useEffect, useState } from 'react';
import { ethers } from 'ethers';
import stakingContractABI from './StakingContractABI.json';

const CONTRACT_ADDRESS = '0x...';

function WarningDisplay({ userAddress }) {
  const [warningData, setWarningData] = useState({ level: 0, points: 0 });

  useEffect(() => {
    const fetchWarning = async () => {
      const provider = new ethers.BrowserProvider(window.ethereum);
      const contract = new ethers.Contract(CONTRACT_ADDRESS, stakingContractABI, provider);
      const level = await contract.getWarningLevel(userAddress);
      const points = await contract.getWarningPoints(userAddress);
      setWarningData({ level: Number(level), points: Number(points) });
    };
    fetchWarning();
  }, [userAddress]);

  // ... render UI based on warningData.level
}

Finally, integrate a clear remediation path. For users at Level 1 or 2, provide a direct UI element, like a button, to call the contract's remediateWarning function (if your design includes it). This allows users to reduce their points by completing a task, such as viewing an educational module. Track the transaction's success and update the UI accordingly. Log all warning interactions for analytics to understand which triggers are most common. This data is invaluable for refining contract parameters and improving user education to prevent issues before they escalate to penalty stages.

STAKING & SLASHING

Frequently Asked Questions

Common technical questions and solutions for implementing a graduated warning system in staking protocols.

A graduated warning system is a slashing mechanism that applies escalating penalties for repeated or increasingly severe validator misbehavior, rather than a single, maximum penalty for any infraction. It works by tracking a validator's offense history on-chain.

For example, a protocol might implement a three-strike rule:

  • First minor offense: A small penalty (e.g., 0.1 ETH) and a warning flag.
  • Second offense: A larger penalty (e.g., 0.5 ETH).
  • Third offense: Full slashing (e.g., 1 ETH) and forced exit from the validator set.

This system improves protocol resilience by giving validators a chance to correct issues (like occasional downtime) while still punishing malicious or chronically unreliable actors. It's a key feature for Proof-of-Stake (PoS) networks like Ethereum, Cosmos, and Polkadot to balance security with fairness.

conclusion-next-steps
IMPLEMENTATION GUIDE

Conclusion and Next Steps

This guide has walked through building a graduated warning system using staking slashing. Here's a summary of the key concepts and where to go from here.

A graduated warning system is a powerful tool for protocol governance, using economic incentives to enforce rules before resorting to permanent bans. The core mechanism involves a staking contract where users deposit collateral. When a rule is violated, a portion of this stake is slashed as a penalty. The severity of the penalty escalates with repeated offenses, creating a clear, automated path from warning to removal. This is more flexible and transparent than binary allow/deny lists.

The implementation typically involves several key smart contract functions: a stake() function for users to deposit funds, a slash() function that can be called by a permissioned actor (like a multisig or DAO) to penalize a user, and a state variable to track a user's strikeCount. The slashing logic is often structured as a mapping, for example: slashPercentage[0] = 10, slashPercentage[1] = 50, slashPercentage[2] = 100. After the final strike, the user's remaining stake is fully slashed and they can be added to a blocklist.

For production use, critical next steps include security audits and designing a robust governance framework. The permission to call the slash function should be carefully controlled, often delegated to a DAO vote or a multisig wallet of elected stewards. You must also decide on appeal mechanisms and data availability. Consider using an oracle or an attestation station like EAS to record the evidence for each slashing event on-chain, making the process verifiable and transparent.

To experiment with this pattern, you can deploy and test a basic version on a testnet. Start with a simplified contract, use a tool like Foundry or Hardhat to write tests that simulate user staking and multiple infractions, and verify the slashing amounts are correct. Review existing implementations from protocols like Aave for their safety module or Lido for their node operator penalties to understand real-world complexity and security considerations.