Skip to content

SigvaraStaking Contract

RunTimeAdmin edited this page Nov 2, 2026 · 19 revisions

SigvaraStaking Contract

**Referenced Files in This Document** - [SigvaraStaking.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraStaking.sol) - [SigvaraIdentity.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraIdentity.sol) - [SigvaraReputation.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraReputation.sol) - [stake.ts](https://github.com/RunTimeAdmin/Sigvara/blob/main/packages/sdk/src/stake.ts) - [SigvaraStaking.t.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/test/SigvaraStaking.t.sol) - [StakingInvariant.t.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/test/StakingInvariant.t.sol) - [whitepaper.md](https://github.com/RunTimeAdmin/Sigvara/blob/main/docs/whitepaper.md) - [README.md](https://github.com/RunTimeAdmin/Sigvara/blob/main/README.md) - [InflowGuard.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/InflowGuard.sol) - [TimelockedGrants.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/TimelockedGrants.sol) - [0005-governance-and-emergency-powers.md](https://github.com/RunTimeAdmin/Sigvara/blob/main/docs/adr/0005-governance-and-emergency-powers.md)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

The SigvaraStaking contract is the economic-security layer for registered agents. It holds staked bond tokens, enforces minimum collateral requirements, manages unbonding withdrawals, and implements a slash lifecycle that can permanently penalize misbehaving operators. The design ties agent status, stake accounting, dispute windows, and reputation zeroing together so that an Active agent always has something at risk.

Key goals:

  • Only the operator may deposit or withdraw stake for their agent.
  • An agent becomes Active and scoreable only after reaching minimumStake; any stake it holds, queued or not, is slashable.
  • Withdrawals are queued for an unbonding period during which they remain slashable.
  • Slash proposals suspend the agent immediately, allow a challenge window, then distribute proceeds and mark the agent terminal.
  • Disputes freeze the stake until the admin rules on them; unresolved disputes expire after a bounded period.

This page describes the contract on main. The Arc testnet proxy has run it since its upgrade to 25c2d59 on 2 November 2026, where a slash pays the committee nothing; it took the bound on upholding a dispute at its upgrade of 28 October, and the rest at its upgrade of 26 October. Its role administrators and parameters were set by the September initialisation, so the timelocked grant of the committee role described below does not apply there, and the bounds that initialize now checks apply only to a fresh deployment. A withdrawal queued before the 26 October upgrade follows the live unbonding period until it is claimed.

Section sources

Project Structure

The staking logic lives in one main Solidity contract and integrates with identity and reputation contracts through explicit roles and interfaces. Tests cover unit behavior, storage layout safety, and fuzzed invariants. The SDK exposes a helper for client-side stake deposits.

graph TB
Client["Client / SDK"] --> Staking["SigvaraStaking"]
Staking --> Token["SVR ERC-20 Token"]
Staking --> Identity["SigvaraIdentity"]
Staking --> Reputation["SigvaraReputation"]
Committee["Slashing Committee"] --> Staking
Loading

Diagram sources

Section sources

Core Components

  • Stake accounting: Each agent’s didHash maps to a Stake struct tracking active amount, lock timestamp, queued withdrawal amount, and queue initiation time.
  • Slash proposals: Each didHash maps to a SlashProposal tracking reporter, victim, timing, state, evidence hash, and challenge/dispute deadlines.
  • Re-file cooldown: lastDroppedAt[didHash] records when a proposal against the agent was last dropped (cancelled, vetoed, expired, or ruled against the slash). initiateSlash refuses with SlashCooldownActive until one challenge period has passed.
  • Fixed claim time: unbondingClaimableAt[didHash] records when a queued withdrawal becomes claimable, fixed when it is queued. A withdrawal queued before that field existed has none and keeps the older rule: its queue time plus the period in force when it is claimed.
  • Rejected evidence: evidenceRejected[didHash][keccak256(evidence)] is set when the admin vetoes a proposal or rules against it. initiateSlash refuses that evidence for that agent with EvidenceAlreadyRejected.
  • Roles:
    • SLASHING_COMMITTEE_ROLE: initiates slashes and cancels pending slashes. It does not rule on disputes. A proposal can be executed only while its reporter still holds the role. The role is administered by UPGRADER_ROLE, so granting it takes the timelock's delay.
    • DEFAULT_ADMIN_ROLE: parameter changes (within the floors and ceilings below), resolveDispute, vetoSlash, and instant revocation of any role except UPGRADER_ROLE.
    • UPGRADER_ROLE: UUPS upgrades, and the grants of its own role and of SLASHING_COMMITTEE_ROLE. The mainnet target holder is the governance timelock.
    • GUARDIAN_ROLE: pauses new deposits for three days at a time (pauseInflows), and nothing else.
  • Token handling: Uses SafeERC20; deposits measure actual received balance delta to tolerate fee-on-transfer tokens safely.
  • Events: Stake changes, withdrawal lifecycle, slash lifecycle, and parameter updates emit indexed events for off-chain indexing.

Important constants and parameters:

  • minimumStake: activation floor. Zero is refused, in initialize and in setMinimumStake.
  • challengePeriod: time before anyone can execute an undisputed slash. It also sets the re-file cooldown after a dropped proposal.
  • unbondingPeriod: delay a withdrawal queued from now must wait. Each withdrawal keeps the period in force when it was queued.
  • MIN_CHALLENGE_PERIOD (3 days), MIN_UNBONDING_PERIOD (1 day): lower bounds protecting against admin abuse.
  • MAX_CHALLENGE_PERIOD (30 days), MAX_UNBONDING_PERIOD (90 days): ceilings, so a typo or a compromised key cannot lock every withdrawal queued while a bad value stands or put a slash out of reach. initialize and the setters hold both bounds, and initializeV2 holds them for the unbonding period.
  • DISPUTE_RESOLUTION_PERIOD (14 days): how long the admin has to rule on a dispute before anyone may expire it. On main an uphold is refused once that period has passed.
  • EXECUTION_PERIOD (14 days): how long after its challenge deadline a Pending proposal can still be executed before anyone may expire it.

Section sources

Architecture Overview

The staking contract coordinates three subsystems:

  1. Identity: stores agent registration, operator binding, and status transitions (PendingBond, Active, Suspended, Slashed).
  2. Reputation: tracks scores; slashing zeroes reputation via a narrow interface.
  3. Staking: holds bonds, enforces collateralization, queues withdrawals, and executes slash settlement.
sequenceDiagram
participant Operator as "Operator"
participant Staking as "SigvaraStaking"
participant Identity as "SigvaraIdentity"
participant Reputation as "SigvaraReputation"
participant Token as "SVR Token"
Operator->>Token : approve(staking, amount)
Operator->>Staking : depositStake(didHash, amount)
Staking->>Token : safeTransferFrom(operator, staking, amount)
Staking->>Staking : update stakes[didHash]
alt Agent reaches minimumStake from PendingBond
Staking->>Identity : updateStatus(didHash, Active)
end
Staking-->>Operator : StakeDeposited event
Loading

Diagram sources

Detailed Component Analysis

Stake Management: Deposit, Withdrawal, and Activation

  • depositStake:

    • Validates the caller is the agent operator and the agent is not unregistered or slashed.
    • Measures actual token transfer delta to avoid over-crediting on fee-on-transfer tokens.
    • Accumulates stake and records lockedAt.
    • Activates a PendingBond agent if total stake reaches minimumStake.
    • Reverts while a guardian pause is running (whenInflowsOpen). The pause covers only this deposit path: withdrawals, claims, disputes, rulings and slash execution never wait on it.
    • Emits StakeDeposited.
  • initiateWithdrawal:

    • Requires existing stake and no already-queued withdrawal.
    • Freezes withdrawals while a slash proposal is Pending or Disputed.
    • Ensures an Active agent cannot drop below minimumStake unless fully exiting (which requires prior suspension).
    • Moves the requested amount into unbondingAmount, sets unbondingAt, and records the claim time in unbondingClaimableAt.
    • Emits WithdrawalInitiated with claimableAt = block.timestamp + unbondingPeriod, fixed at that moment.
  • claimWithdrawal:

    • Requires a queued withdrawal, correct operator, no active slash proposal, and that the claim time fixed when it was queued has been reached.
    • Clears the fixed claim time and transfers the queued amount back to the operator.
    • Emits WithdrawalClaimed.
  • SDK helper depositStake:

    • Approves the staking contract if needed, then calls the on-chain function.
flowchart TD
Start(["Deposit / Withdraw Flow"]) --> CheckOperator["Check caller is operator"]
CheckOperator --> DepositPath{"Action?"}
DepositPath --> |Deposit| MeasureDelta["Measure token balance delta"]
MeasureDelta --> UpdateStake["Update active stake and lockedAt"]
UpdateStake --> ActivateCheck{"Agent PendingBond<br/>and >= minimumStake?"}
ActivateCheck --> |Yes| Activate["Set agent Active"]
ActivateCheck --> |No| EmitDeposit["Emit StakeDeposited"]
DepositPath --> |Withdraw| CheckQueue["No queued withdrawal?"]
CheckQueue --> SlashFreeze{"Slash Pending or Disputed?"}
SlashFreeze --> |Yes| RevertSlash["Revert SlashAlreadyPending"]
SlashFreeze --> |No| CheckRemaining["Active agent remaining >= minimumStake?"]
CheckRemaining --> |No| RevertMin["Revert InsufficientStake"]
CheckRemaining --> Queue["Move amount to unbondingAmount/unbondingAt"]
Queue --> EmitWithdraw["Emit WithdrawalInitiated"]
EmitWithdraw --> ClaimCheck{"Unbonding elapsed?<br/>No slash pending?"}
ClaimCheck --> |No| RevertUnbond["Revert UnbondingPeriodActive or SlashAlreadyPending"]
ClaimCheck --> Transfer["Transfer queued amount to operator"]
Transfer --> EmitClaim["Emit WithdrawalClaimed"]
Loading

Diagram sources

Section sources

Slashing Lifecycle: Proposal, Challenge Window, Dispute, Finalization

The slash lifecycle protects victims while giving operators a chance to contest accusations.

Lifecycle states:

  • None: no active proposal.
  • Pending: initiated by committee; agent suspended; challenge window open.
  • Disputed: operator disputed within the challenge window; stake frozen until the admin rules or the dispute expires.
  • Executed: slash finalized; stake swept; agent marked Slashed; reputation zeroed.
  • Cancelled: proposal withdrawn, vetoed, expired or ruled against without execution.

Key operations:

  • initiateSlash:

    • Requires SLASHING_COMMITTEE_ROLE.
    • Refuses a victim that is the reporter (VictimIsReporter) or any other holder of SLASHING_COMMITTEE_ROLE (VictimIsCommittee).
    • Checks total slashable balance includes both active stake and queued withdrawal.
    • Refuses while a proposal is Pending or Disputed, and for one challenge period after the last dropped proposal against the agent (SlashCooldownActive).
    • Refuses evidence the admin has already vetoed or ruled against for the agent (EvidenceAlreadyRejected), checked after the cooldown.
    • Creates a SlashProposal, snapshots challengeDeadline, and suspends the agent.
    • Emits SlashInitiated.
  • disputeSlash:

    • Allowed by the operator within the challenge window.
    • Changes state to Disputed and freezes further withdrawals.
    • Emits SlashDisputed.
  • resolveDispute:

    • Admin-only (DEFAULT_ADMIN_ROLE) decision to uphold or drop. The committee files a slash and does not rule on it.
    • Uphold triggers _settleSlash, but reverts (ChallengePeriodActive) until the challenge deadline fixed at filing has passed, so a dispute never brings a slash forward. It does not depend on the reporter still being on the committee. On main it also reverts (DisputeResolutionExpired) once DISPUTE_RESOLUTION_PERIOD has passed since the dispute was filed, the moment expireDispute stops refusing. Drop records the proposal's evidence as rejected for the agent, triggers _dropProposal, and is open at any time.
  • expireDispute:

    • Permissionless expiration after DISPUTE_RESOLUTION_PERIOD to prevent indefinite freezes. From that moment an uphold is refused, so the two never overlap.
  • expireSlash:

    • Permissionless lapse of a Pending proposal that nobody executed or cancelled, once EXECUTION_PERIOD (14 days) has passed since its challenge deadline. The proposal is dropped like any other.
  • cancelSlash:

    • Committee-only cancellation of a Pending proposal.
  • vetoSlash:

    • Admin-only drop of a Pending or Disputed proposal at any point, including after the challenge deadline and before anyone executes it. Records the proposal's evidence as rejected for the agent. Emits SlashVetoed alongside SlashCancelled.
  • executeSlash:

    • Anyone can call after the challenge deadline, as long as the reporter still holds SLASHING_COMMITTEE_ROLE (ReporterNotAuthorized otherwise, checked after the window). Revoking a compromised member therefore defuses what it had filed: any current member can cancel such a proposal, and anyone can lapse it. Once EXECUTION_PERIOD has passed since the deadline, anyone may lapse the proposal with expireSlash instead.
    • Sweeps active stake and queued withdrawal.
    • Burns 75% and credits 25% to the victim. The reporter, like every committee member, gets nothing.
    • Marks agent Slashed and zeros reputation.
    • Emits SlashExecuted.
  • claimSlashProceeds:

    • Pull-based payout for the victim. A reporter's credit left from the earlier split stays claimable.
    • Emits SlashProceedsClaimed.
stateDiagram-v2
[*] --> None
None --> Pending : "initiateSlash"
Pending --> Disputed : "disputeSlash"
Pending --> Executed : "executeSlash after challenge"
Disputed --> Executed : "resolveDispute(uphold)"
Disputed --> Cancelled : "resolveDispute(drop), vetoSlash or expireDispute"
Pending --> Cancelled : "cancelSlash, vetoSlash or expireSlash"
Executed --> [*]
Cancelled --> [*]
Loading

Diagram sources

Section sources

Unbonding Period Mechanics and Withdrawal Restrictions

  • A queued withdrawal remains slashable until claimed.
  • During a Pending or Disputed slash, neither initiating nor claiming a withdrawal is allowed.
  • While Active, an operator cannot reduce active stake below minimumStake unless fully exiting; full exit requires first moving the agent to Suspended.
  • At the claim time fixed when the withdrawal was queued (unbondingPeriod from then), the operator may claim the queued amount once. Changing unbondingPeriod later does not move it.

These rules ensure that:

  • Operators cannot escape accountability by queuing all funds.
  • Agents remain economically accountable throughout the challenge window.
  • Admins cannot set unrealistically short periods that undermine security, nor periods above the ceilings (a huge unbonding period would lock every queued withdrawal).

Section sources

Relationship with Slash Proposals and Dispute Resolution

  • Slash proposals are keyed by didHash; only one active proposal per agent at a time.
  • The agent is suspended immediately upon initiation, preventing activity during dispute.
  • Disputes do not cancel the proposal; they freeze the stake and require an admin ruling.
  • If the admin never rules, anyone (the operator included) can expire the dispute after the fixed period, but this does not reinstate the agent automatically if collateral is insufficient.
  • The admin can also drop a Pending or Disputed proposal at any point with vetoSlash, and a Pending proposal that nobody executes can be lapsed by anyone 14 days after its deadline.
  • Dropping or expiring a proposal clears the slash suspension; if the agent still meets minimumStake, it is reinstated to Active; otherwise it remains Suspended until the operator tops up. After any drop the committee must wait one challenge period before filing against the same agent again.
sequenceDiagram
participant Committee as "Committee"
participant Admin as "Admin"
participant Staking as "SigvaraStaking"
participant Operator as "Operator"
participant Identity as "SigvaraIdentity"
Committee->>Staking : initiateSlash(didHash, victim, evidence)
Staking->>Identity : updateStatus(Suspended)
Note over Staking : SlashProposal created with challengeDeadline
Operator->>Staking : disputeSlash(didHash)
Staking->>Staking : state = Disputed
Admin->>Staking : resolveDispute(didHash, uphold/drop)
alt uphold
Staking->>Staking : _settleSlash()
Staking->>Identity : updateStatus(Slashed)
else drop
Staking->>Staking : _dropProposal()
Staking->>Identity : clearSlashSuspension or updateStatus(Active)
end
Loading

Diagram sources

Section sources

Examples of Stake Operations and Scenarios

Example: Stake Deposit

  • Register an agent → status PendingBond.
  • Approve SVR tokens to the staking contract.
  • Call depositStake with enough to reach minimumStake.
  • Agent becomes Active; StakeDeposited emitted.

Validation examples:

  • Non-operator reverts with NotOperator.
  • Unregistered or slashed agent reverts with AgentNotActive.
  • Deposits accumulate across multiple calls.

Section sources

Example: Withdrawal During Different Agent States

  • Active: partial withdrawal allowed only if remaining stake stays above minimumStake.
  • Suspended: full withdrawal allowed; after unbonding, claim succeeds.
  • Slash Pending or Disputed: withdrawal initiation and claim both revert.

Section sources

Example: Slashing Scenario

  • Committee calls initiateSlash; agent suspended.
  • Operator may dispute within challenge window.
  • If undisputed, anyone calls executeSlash after deadline.
  • 75% burned, 25% to victim, nothing to the reporter; agent marked Slashed; reputation zeroed.
  • The victim pulls its proceeds via claimSlashProceeds.

Section sources

Economic Incentives and Penalties

  • Honest behavior incentive: Active agents must maintain at least minimumStake; misbehavior risks losing stake.
  • Deterrence via unbonding: Queued withdrawals remain slashable, preventing exit-before-discovery.
  • No reporter reward: The committee member who files a slash takes no share of it, and no member can be named as the victim, so nobody on the committee profits from slashing (ADR 0007).
  • Victim compensation: Victims receive a share, aligning incentives for affected parties.
  • Burn mechanism: Three quarters of slashed stake is burned, reducing supply and signaling cost.
  • Terminal penalty: Slashed agents become terminal and lose reputation, preventing reuse of compromised identities.

Section sources

Event Emissions

  • StakeDeposited: emitted when stake increases.
  • WithdrawalInitiated: emitted when a withdrawal is queued, including claimableAt.
  • WithdrawalClaimed: emitted when queued funds are transferred.
  • SlashInitiated: emitted when a slash proposal starts.
  • SlashDisputed: emitted when an operator disputes.
  • SlashExecuted: emitted when slash settles, with the burned and toVictim amounts. The event lost its reporter amount at the 2 November 2026 testnet upgrade, so an indexer that decodes it sees a new signature from then on.
  • SlashCancelled: emitted when a proposal is cancelled.
  • SlashVetoed: emitted alongside SlashCancelled when the admin, not the committee, dropped the proposal.
  • SlashProceedsClaimed: emitted when an account pulls its credited proceeds.
  • Parameter updates: MinimumStakeUpdated, ChallengePeriodUpdated, UnbondingPeriodUpdated.
  • Inflow pause (from InflowGuard): InflowsPaused, InflowsResumed.

Section sources

Gas Optimization and Storage Efficiency Patterns

  • Fee-on-transfer safety: Deposits measure actual balance delta rather than trusting amount, avoiding silent over-crediting.
  • Pull-based payouts: Slash proceeds are credited to claimable and pulled by recipients, preventing stuck settlements due to non-receiving contracts.
  • Append-only storage: New variables are appended after mappings to preserve proxy storage layout; tests pin mapping slots and verify upgrade safety.
  • Namespaced pause state: InflowGuard keeps its state in an ERC-7201 slot rather than in the contract's own layout, so adding it to a live proxy shifts no existing variable.
  • CEI pattern: State changes precede external calls where appropriate to reduce reentrancy risk.
  • Named errors: Arithmetic failures use custom errors with context instead of panics, improving debugging and gas efficiency compared to generic revert strings.
  • Minimal view functions: Read-only accessors return compact data for efficient off-chain queries.

Section sources

Invariant Testing Results and Security Guarantees

The invariant test suite asserts properties across randomized action sequences:

  • Custody matches obligations: Contract balance equals sum of active stakes, queued withdrawals, and unclaimed slash proceeds.
  • Token conservation: Total deposited equals held plus claimed plus burned plus pulled proceeds.
  • Slashed agents fully zeroed: Slashed agents have zero stake and zero queued withdrawal.
  • Burned only grows: Burn address balance never decreases.
  • Disputed agents stay bonded: Disputed proposals keep some bond at risk.
  • Active agents are collateralized: Active agents hold at least minimumStake across active stake and queued withdrawal.

These invariants provide strong guarantees:

  • No creation or loss of tokens in custody.
  • Slashed identities cannot retain economic value.
  • Disputes cannot release stake prematurely.
  • Active agents cannot operate without collateral.

Section sources

Dependency Analysis

SigvaraStaking depends on:

  • SigvaraIdentity: reads agent identity and status; writes status transitions for activation, suspension, and slashing.
  • SigvaraReputation: narrows dependency to zeroReputation(bytes32) via IReputationZero to avoid pulling the full reputation contract graph.
  • OpenZeppelin libraries: UUPSUpgradeable, Initializable, ReentrancyGuard, SafeERC20, IERC20, and AccessControlUpgradeable through TimelockedGrants.
  • Shared bases: TimelockedGrants (the committee role is granted through the timelock, and the admin can still revoke it at once) and InflowGuard (the guardian's pause on deposits).

Coupling and cohesion:

  • High cohesion around stake and slash state management.
  • Controlled coupling to identity and reputation through minimal interfaces and role checks.
  • External dependencies are well-scoped and tested for upgrade safety.

Potential circular dependencies:

  • Avoided by importing only necessary interfaces and keeping shared enums/types in shared contracts.

External integration points:

  • ERC-20 token transfers via SafeERC20.
  • Role-based governance via AccessControl.
  • Proxy upgradeability via UUPS.
classDiagram
class SigvaraStaking {
+initialize(...)
+depositStake(didHash, amount)
+initiateWithdrawal(didHash, amount)
+claimWithdrawal(didHash)
+initiateSlash(didHash, victim, evidenceHash)
+disputeSlash(didHash)
+resolveDispute(didHash, uphold)
+expireDispute(didHash)
+expireSlash(didHash)
+cancelSlash(didHash)
+vetoSlash(didHash)
+executeSlash(didHash)
+claimSlashProceeds()
+getStake(didHash)
+hasMinimumStake(didHash)
+getPendingWithdrawal(didHash)
+unbondingClaimableAt(didHash)
+evidenceRejected(didHash, evidenceKey)
+getSlashProposal(didHash)
}
class SigvaraIdentity {
+getIdentity(didHash)
+updateStatus(didHash, status)
+clearSlashSuspension(didHash)
}
class IReputationZero {
+zeroReputation(didHash)
}
SigvaraStaking --> SigvaraIdentity : "reads/writes agent status"
SigvaraStaking --> IReputationZero : "zeros reputation"
Loading

Diagram sources

Section sources

Performance Considerations

  • Deposit measurement overhead: Two extra balanceOf calls protect against fee-on-transfer tokens; acceptable given the catastrophic alternative of misaccounted stake.
  • Pull-based slash proceeds: Avoids blocking settlement on recipient contract behavior; callers pay gas to claim.
  • State-first external calls: Follows CEI pattern to minimize reentrancy risk and simplify reasoning.
  • Storage append rule: Preserves proxy storage layout; new variables added at the end to avoid slot shifts.
  • View functions: Minimal returns reduce calldata costs for off-chain consumers.

Troubleshooting Guide

Common issues and resolutions:

  • Insufficient allowance: Approve SVR tokens to the staking contract before depositing.
  • Not operator: Ensure the caller matches the agent’s operator in the identity registry.
  • Agent not active: Registration alone leaves an agent PendingBond; deposit at least minimumStake to activate.
  • Withdrawal blocked by slash: Wait for slash resolution or expiration; withdrawals are frozen during Pending or Disputed.
  • Unbonding not elapsed: Wait until claimableAt; check getPendingWithdrawal.
  • Cannot claim slash proceeds: Call claimSlashProceeds as the victim; a slash credits nobody else, and proceeds are pull-based.
  • Admin period too short: setChallengePeriod and setUnbondingPeriod enforce minimums (PeriodTooShort) and ceilings (PeriodTooLong); adjust within bounds.
  • Cannot file a slash again: SlashCooldownActive means a proposal against the agent was dropped less than one challenge period ago; wait until refileAt.
  • Cannot file the same evidence again: EvidenceAlreadyRejected means the admin vetoed or ruled against that evidence for this agent; file new evidence.
  • Victim refused: VictimIsReporter or VictimIsCommittee means the victim named is the filing member or another holder of SLASHING_COMMITTEE_ROLE; name the harmed party, which may not sit on the committee.
  • Cannot execute a slash: ReporterNotAuthorized means the member who filed it no longer holds SLASHING_COMMITTEE_ROLE; a current member can cancel it, or anyone can lapse it 14 days after its deadline.
  • Proposal stuck in Pending: once EXECUTION_PERIOD has passed since its challenge deadline, anyone can call expireSlash (ExecutionPeriodActive before then).
  • Deposit reverts with InflowsPausedUntil: the guardian has paused new deposits; the pause ends by itself after three days. Withdrawals and claims are unaffected.

Section sources

Conclusion

SigvaraStaking provides a robust economic-security model for agents:

  • Stake accumulation activates and sustains agent eligibility.
  • Unbonding delays and slashable queued withdrawals prevent exit-before-discovery.
  • Slash proposals suspend agents, enable challenges, and distribute proceeds securely.
  • Disputes freeze stake until the admin rules, with bounded expiration, and a proposal nobody executes can be lapsed by anyone after 14 days.
  • Invariant tests validate custody, conservation, terminal slashing, and collateralization.
  • Gas-efficient patterns and upgrade-safe storage layout support long-term operation.

Together, these mechanisms align incentives toward honest behavior and provide clear penalties for misconduct.

Appendices

Agent Status State Machine

stateDiagram-v2
[*] --> PendingBond : registerAgent()
PendingBond --> Active : depositStake() reaches minimumStake
Active --> Suspended : operator.updateStatus() or StakingCore.initiateSlash()
Suspended --> Active : operator.updateStatus() or resolveDispute(false) or cancelSlash() / vetoSlash() / expireDispute() / expireSlash()
Active --> Slashed : StakingCore.executeSlash()
Suspended --> Slashed : StakingCore.executeSlash()
Slashed --> [*] : terminal
Loading

Section sources

Overview

Clone this wiki locally