Repository navigation
Status Management and Control
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains how agent status is managed and controlled in SigvaraIdentity, focusing on suspension, reactivation, the meaning and permissions of each status, and the contract interactions that enforce them. It also documents event emissions for off-chain monitoring and provides practical workflow examples based on the actual Solidity implementation.
The system separates identity management from stake management:
- SigvaraIdentity stores agent identities, their operator, public key, and status.
- SigvaraStaking manages collateral, slashing, and dispute timelines, and coordinates with SigvaraIdentity to update status during slash flows.
There are no standalone functions named suspendAgent or reactivateAgent. Suspension and reactivation are performed through the shared updateStatus function, with different callers (operator vs staking core) and different preconditions depending on the target state.
This page describes the contracts on main. The Arc testnet proxies have run this code since 26 October 2026 (apart from the bound on upholding a dispute, which they take at their next upgrade), but their role administrators were written by the September initialisation, so there the admin (not the timelock) grants the staking-core role and repoints the stake view.
The relevant code lives in two contracts:
-
SigvaraIdentity: Agent registry, status transitions, operator control, and slash-suspension locking. -
SigvaraStaking: Stake bonding, withdrawal, slashing initiation/dispute/execution, and coordination with identity status.
graph TB
Operator["Operator"]
StakingCommittee["Slashing Committee<br/>STAKING_CORE_ROLE caller"]
Identity["SigvaraIdentity"]
Staking["SigvaraStaking"]
Reputation["Reputation Registry"]
Token["SVR Token"]
Operator --> Identity
StakingCommittee --> Staking
Staking --> Identity
Staking --> Reputation
Staking --> Token
Diagram sources
Section sources
- Agent status is represented by an enum with four values:
Active,Suspended,Slashed, andPendingBond. - The primary write interface for status changes is
updateStatus(bytes32 didHash, AgentStatus newStatus). - The staking contract calls
updateStatuswhen initiating a slash, resolving disputes, executing slashes, or dropping proposals. - A special internal lock
slashSuspended[didHash]prevents an operator from reactivating an agent while a slash initiated by the staking core is pending.
Key responsibilities:
-
Operator: Can toggle between
ActiveandSuspended, subject to collateral checks when returning toActive. -
Staking core: Can set
Suspended(slash initiation), clear the slash-suspension lock, reinstate toActiveafter a dropped proposal if bonded, and setSlashed(terminal). - Anyone: Can observe events and view states; only authorized roles can change critical statuses.
Section sources
The status lifecycle is enforced across both contracts:
stateDiagram-v2
[*] --> PendingBond : registerAgent()
PendingBond --> Active : depositStake() reaches minimumStake
Active --> Suspended : operator.updateStatus()
Active --> Suspended : StakingCore.initiateSlash()
Suspended --> Active : operator.updateStatus() with sufficient collateral
Suspended --> Active : resolveDispute(false) and bond >= minimumStake
Suspended --> Active : cancelSlash()/vetoSlash()/expireDispute()/expireSlash() and bond >= minimumStake
Active --> Slashed : StakingCore.executeSlash()
Suspended --> Slashed : StakingCore.executeSlash()
Slashed --> [*] : terminal
Diagram sources
- README.md:215-241
- SigvaraIdentity.sol:338-397
- SigvaraStaking.sol:473-528
- SigvaraStaking.sol:683-701
- SigvaraStaking.sol:712-776
-
Active: Fully operational agent backed by at leastminimumStake. Operators may suspend it; staking core may slash it. -
Suspended: Temporarily halted. May be self-imposed by the operator or imposed by the staking core during a slash challenge window. Key rotation remains allowed for recovery. -
Slashed: Terminal state. No further status updates or key rotation are permitted. Reputation is zeroed out by staking settlement. -
PendingBond: Initial registration state before any stake is posted. BecomesActiveautomatically once the first deposit meetsminimumStake.
Permissions summary:
- Only the operator can toggle
Active↔Suspended. - Only the staking core can set
Slashed. - Returning to
Activealways requires sufficient collateral via the stake view oracle. - The stake view is repointed only by
UPGRADER_ROLE(setStakeView), the timelock's role and not the admin's, because a contract that answers yes for everyone would switch the collateral gate off. -
STAKING_CORE_ROLEis administered byUPGRADER_ROLE: the admin cannot grant it, but can revoke it at once. - An operator cannot lift a staking-core-applied suspension until the staking core clears the lock.
- A guardian pause closes new registrations (
registerAgent) and nothing else here:updateStatusand key rotation keep working while it runs.
Section sources
Suspension is implemented through updateStatus(didHash, Suspended):
-
Operator-initiated suspension:
- Caller must be the operator.
- Does not set the slash-suspension lock.
- Immediately halts the agent’s capabilities.
- Allows key rotation even while suspended.
-
Staking-core-initiated suspension:
- Caller must have
STAKING_CORE_ROLE. - Sets
slashSuspended[didHash] = true, preventing the operator from reactivating mid-challenge. - Used by
initiateSlashto halt activity during the dispute window.
- Caller must have
Immediate effects:
- The agent becomes non-active; downstream systems should treat it as unavailable.
- If the staking core applied the suspension, the operator cannot call
updateStatus(Active)until the staking core clears the lock.
Section sources
Reactivation is implemented through updateStatus(didHash, Active):
-
Operator-driven reactivation:
- Requires the caller to be the operator.
- Requires the stake view oracle to report sufficient collateral (
hasMinimumStake). - Allowed only if there is no active slash-suspension lock.
- Restores normal agent capabilities.
-
Staking-core-driven reactivation:
- Permitted only when clearing a slash-suspension lock or reinstating after a dropped proposal.
- Also enforces sufficient collateral before setting
Active. - Clears
slashSuspended[didHash]when transitioning fromSuspendedtoActive.
Cooldown periods:
- There is no explicit cooldown timer in
updateStatus. - Time-based constraints come from the staking flow:
- Challenge period before slash execution.
- Dispute resolution period before anyone can expire an unresolved dispute.
- Execution period (14 days after the challenge deadline) before anyone can lapse a pending proposal that nobody executed.
- Re-file cooldown: after a proposal is dropped, the committee cannot suspend the agent through a new one for one challenge period.
- Unbonding period before withdrawing queued stakes.
Privilege restoration:
- On successful reactivation, the agent regains its full operational privileges.
- Reputation is not restored by reactivation; reputation is zeroed only when slashed.
Section sources
- Caller: operator
- Function:
identity.updateStatus(didHash, Suspended) - Validation:
- Agent must be registered.
- Caller must be the operator.
- Agent must not be
Slashed.
- Effect:
- Status becomes
Suspended. - Slash-suspension lock remains false.
- Agent capabilities are halted.
- Status becomes
- Caller: operator
- Function:
identity.updateStatus(didHash, Active) - Validation:
- Agent must be registered.
- Caller must be the operator.
- Agent must not be
Slashed. - Stake view oracle must confirm sufficient collateral.
- Slash-suspension lock must be false.
- Effect:
- Status becomes
Active. - Agent regains full capabilities.
- Status becomes
- Caller: staking core (
STAKING_CORE_ROLE) - Function:
staking.initiateSlash(...)which internally callsidentity.updateStatus(didHash, Suspended) - Validation:
- Caller has
SLASHING_COMMITTEE_ROLE. - Victim is not the reporter.
- Total slashable balance is nonzero.
- No active slash proposal exists.
- No proposal against the agent was dropped less than one challenge period ago.
- Caller has
- Effect:
- Agent becomes
Suspended. - Slash-suspension lock becomes true.
- Slash proposal enters pending state.
- Agent becomes
- Caller: staking core
- Function:
identity.clearSlashSuspension(didHash) - Validation:
- Caller has
STAKING_CORE_ROLE. - Agent is registered.
- Caller has
- Effect:
- Slash-suspension lock becomes false.
- Agent remains
Suspendedunless the operator explicitly reactivates it.
These examples reflect the actual validation paths and side effects defined in the contracts.
Section sources
sequenceDiagram
participant Operator as "Operator"
participant Identity as "SigvaraIdentity"
participant Staking as "SigvaraStaking"
participant StakeView as "IStakeView"
Operator->>Identity : "updateStatus(didHash, Suspended)"
Identity-->>Operator : "status = Suspended"
Operator->>Staking : "depositStake(didHash, amount)"
Staking->>StakeView : "hasMinimumStake(didHash)"
StakeView-->>Staking : "bool"
Staking->>Identity : "updateStatus(didHash, Active) if PendingBond and bonded"
Identity-->>Staking : "status updated"
Staking->>Identity : "updateStatus(didHash, Suspended) on initiateSlash"
Identity-->>Staking : "slashSuspended = true"
Staking->>Identity : "updateStatus(didHash, Active) on drop/cancel if bonded"
Identity-->>Staking : "slashSuspended = false"
Staking->>Identity : "updateStatus(didHash, Slashed) on executeSlash"
Identity-->>Staking : "terminal state"
Diagram sources
- SigvaraIdentity.sol:338-397
- SigvaraStaking.sol:320-363
- SigvaraStaking.sol:473-528
- SigvaraStaking.sol:683-701
- SigvaraStaking.sol:712-776
Operations available per state:
-
PendingBond:- Register: already done.
- Deposit stake: allowed; auto-activates when reaching
minimumStake. - Suspend/reactivate: not applicable until bonded.
-
Active:- Suspend: allowed by operator.
- Slash: possible via staking committee.
- Withdraw: allowed under staking rules.
-
Suspended:- Reactivate: allowed by operator if bonded; allowed by staking core when clearing slash lock.
- Rotate key: allowed for recovery.
- Slash: possible if slash was initiated while active.
-
Slashed:- No status changes.
- No key rotation.
- Reputation zeroed.
Section sources
Off-chain systems should listen for these events:
-
AgentRegistered: New agent identity created; includesdidHash,operator,agentAddress, anded25519PubKey. -
AgentStatusUpdated: Any status transition; includesdidHashandnewStatus. -
PublicKeyRotated: Ed25519 key changed; includesdidHashand new key. -
OperatorTransferOffered,OperatorTransferCancelled,OperatorTransferred: Ownership handover lifecycle. -
StakeViewSet: Stake view oracle address configured.
Monitoring recommendations:
- Track
AgentStatusUpdatedto maintain a real-time status map. - Use
AgentRegisteredto bootstrap identity indexes. - Use
PublicKeyRotatedto refresh verification keys. - Combine with staking events (
SlashInitiated,SlashDisputed,SlashExecuted,SlashCancelled, andSlashVetoedwhen the admin dropped the proposal) to correlate slash-related suspensions and terminations.
Section sources
- SigvaraIdentity depends on OpenZeppelin upgradeable access control and UUPS upgradeability.
- SigvaraStaking imports SigvaraIdentity directly to share the
AgentStatusenum and interact with identity storage. - SigvaraStaking also interacts with a reputation registry to zero reputation upon slashing.
- SigvaraIdentity uses an
IStakeViewinterface to check collateral without creating a circular dependency.
classDiagram
class SigvaraIdentity {
+enum AgentStatus
+function updateStatus(didHash, newStatus)
+function rotatePublicKey(didHash, newEd25519PubKey)
+function clearSlashSuspension(didHash)
+event AgentStatusUpdated
+event PublicKeyRotated
}
class SigvaraStaking {
+function initiateSlash(...)
+function disputeSlash(...)
+function executeSlash(...)
+function cancelSlash(...)
+function vetoSlash(...)
+function expireDispute(...)
+function expireSlash(...)
+event SlashInitiated
+event SlashExecuted
+event SlashCancelled
}
class IStakeView {
+function hasMinimumStake(didHash) bool
}
SigvaraStaking --> SigvaraIdentity : "updates status"
SigvaraIdentity --> IStakeView : "checks collateral"
Diagram sources
- SigvaraIdentity.sol:18-20
- SigvaraIdentity.sol:338-397
- SigvaraStaking.sol:473-528
- SigvaraStaking.sol:712-776
Section sources
- Status transitions are constant-time operations except where operator index maintenance is involved.
- Operator agent lists use swap-and-pop removal with recorded positions to avoid linear scans for most cases.
- Off-chain consumers should page through
getOperatorAgentsPagedrather than fetching unbounded lists. A limit of the maximumuint256asks for the rest of the list; it used to overflow. - Collateral checks rely on the external
IStakeView; performance depends on the underlying staking implementation.
Common issues and resolutions:
-
Attempting to reactivate without sufficient collateral:
- Error:
InsufficientCollateral. - Resolution: Deposit enough stake so
hasMinimumStakereturns true, then callupdateStatus(Active).
- Error:
-
Trying to reactivate while slash-suspension lock is active:
- Error:
SlashSuspensionLocked. - Resolution: Wait for the staking core to clear the lock via
clearSlashSuspensionor a resolved/dropped slash flow.
- Error:
-
Calling
updateStatus(Slashed)on a slashed agent:- Error:
SlashedAgentImmutable. - Resolution: No further status changes are allowed; the agent is terminated.
- Error:
-
Trying to return to
PendingBond:- Error:
CannotReturnToPendingBond. - Resolution: Agents do not revert to
PendingBond; they suspend and exit instead.
- Error:
-
Not being the operator:
- Error:
NotOperator. - Resolution: Ensure the caller matches the stored operator for the agent.
- Error:
-
Stake view not configured:
- Error:
StakeViewNotSet. - Resolution: The admin calls
initializeV2, or the upgrader (the timelock's role) callssetStakeView, with a valid stake view contract.
- Error:
Section sources
Agent status management in SigvaraIdentity is centered around updateStatus, with strict role-based controls and collateral enforcement. Suspension can be operator-driven or staking-core-driven, with the latter imposing a protective lock to prevent premature reactivation during slash challenges. Reactivation requires sufficient collateral and clearance of any slash-suspension lock. The four status values define a clear lifecycle: registration begins at PendingBond, moves to Active upon bonding, can be temporarily halted at Suspended, and ends permanently at Slashed. Off-chain systems should monitor the emitted events to keep status, ownership, and cryptographic keys synchronized with on-chain state.
- Agent Registration and Lifecycle
- Contract Overview and Architecture
- Economic Security Model and Incentives
- Evidence Verification and Merkle Proofs
- Key Management and Rotation
- Maturity Mechanism and Score Release
- Proposal Workflow and Challenge System
- Score Storage and Data Model
- SigvaraIdentity Contract
- SigvaraOracleBond Contract
- SigvaraReputation Contract
- SigvaraStaking Contract
- Slashing Lifecycle and Dispute Resolution
- Stake Management Functions
- Status Management and Control
- Token and Fee Contracts
- Unbonding Period and Withdrawal Security
- Anti-Manipulation and Security Measures
- Community Flag Processing
- Evidence Sources and Verification
- External Trust Integration
- Merkle Proof System
- Oracle Score Computation
- Payment-Backed Attestations
- Scoring Model and Formulas
- Agent Creation and Key Management
- Agent Operations
- Agent Registration Workflow
- Challenge-Response Authentication
- Gate Access Control
- Integration Patterns and Examples
- SDK Overview and Setup
- Verifier Functions