Repository navigation
Identity Layer
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains Sigvara’s identity layer and how it builds on ERC-8004. ERC-8004 provides canonical agent identity and a raw signed feedback ledger; Sigvara adds computed reputation and staked accountability on top. The system anchors an off-chain Ed25519 key to an on-chain agent registry, manages operator control, enforces a strict status lifecycle, and integrates with staking and slashing so that only bonded agents can earn spendable reputation.
The design intentionally separates:
- Canonical identity and raw feedback (ERC-8004).
- Computed reputation score (SigvaraReputation).
- Bonding, unbonding, and slashing (SigvaraStaking).
- On-chain identity extension for Ed25519 keys and slash state (SigvaraIdentity).
Direction of travel, not the present state: ADR 0001 makes ERC-8004 agent ids the intended long-term key, with SigvaraIdentity shrinking to an extension keyed to one. That cutover has not happened. Every agent registered today is keyed by its didHash in SigvaraIdentity, which script/Deploy.s.sol deploys for mainnet and which every deployed component reads and writes.
Section sources
The identity layer spans Solidity contracts and a TypeScript SDK:
- Solidity core:
-
SigvaraIdentity.sol: deterministic DID derivation, Ed25519 public key anchoring, operator management, and status transitions. -
SigvaraReputation.sol: oracle-proposed, challenge-windowed, finalized reputation scores with maturity. -
SigvaraStaking.sol: stake bonds, unbonding, slash initiation/dispute/resolution, and execution.
-
- TypeScript SDK:
-
did.ts,agent.ts,keys.ts,challenge.ts,types.ts: DID formatting, Ed25519 key handling, A2A challenge-response, and shared types.
-
- Documentation and tests:
-
reputation-model.mddescribes scoring factors and lifecycle behavior. -
SigvaraIdentity.t.solexercises registration, status transitions, transfers, and storage layout.
-
graph TB
subgraph "On-chain"
ID["SigvaraIdentity<br/>DID + Ed25519 key + Status"]
REP["SigvaraReputation<br/>Computed Score"]
STK["SigvaraStaking<br/>Bond + Slash"]
E8004["ERC-8004<br/>Canonical Agent + Raw Feedback"]
end
subgraph "Off-chain"
SDK["TypeScript SDK<br/>DID / Keys / Challenge"]
ORACLE["Oracle Network<br/>Score Computation"]
end
SDK --> ID
ORACLE --> REP
STK --> ID
REP --> ID
REP -. reads .-> E8004
Diagram sources
- SigvaraIdentity.sol:22-107
- SigvaraReputation.sol:15-75
- SigvaraStaking.sol:31-45
- ADR 0001 — ERC-8004 as the identity layer:11-36
Section sources
- SigvaraIdentity.sol:22-107
- SigvaraReputation.sol:15-75
- SigvaraStaking.sol:31-45
- did.ts:1-28
- agent.ts
- keys.ts:1-125
- challenge.ts
- types.ts
-
SigvaraIdentity: Anchors each agent by a deterministic
didHash, stores the Ed25519 public key, tracks the operator, and enforces status transitions. It also exposes a stake view gate so returning to Active requires sufficient collateral. - SigvaraReputation: Stores oracle-computed six-factor scores, enforces a challenge window, and applies maturity so earned points become spendable gradually. It binds scores to registered, non-slashed, bonded agents.
- SigvaraStaking: Manages stake deposits, unbonding, slash proposals, disputes, and execution. Slashing marks the agent Slashed and zeros its reputation.
- SDK: Provides deterministic DID computation, Ed25519 key generation and encoding, and A2A challenge-response with audience binding.
Key responsibilities:
- Deterministic DID:
did:sigvara:<chainId>:<agentAddress>→keccak256(...). - Operator-controlled identity lifecycle and transfer.
- Off-chain cryptographic identity (Ed25519) anchored on-chain.
- Reputation computed off-chain but enforced on-chain via bonding and slashing.
Section sources
- SigvaraIdentity.sol:22-107
- SigvaraReputation.sol:15-75
- SigvaraStaking.sol:31-45
- did.ts:18-28
- agent.ts:27-124
- keys.ts:89-125
- challenge.ts:27-48
The identity layer is layered:
- ERC-8004 defines canonical agent identity and raw feedback.
- SigvaraIdentity extends identity with Ed25519 keys and slash state, plus operator control.
- SigvaraStaking enforces “bond before trust” and provides economic finality through slashing.
- SigvaraReputation computes and stores normalized reputation, gated by bond and identity checks.
sequenceDiagram
participant Client as "Client / SDK"
participant Registry as "SigvaraIdentity"
participant Staking as "SigvaraStaking"
participant Reputation as "SigvaraReputation"
participant Oracle as "Oracle"
participant E8004 as "ERC-8004"
Client->>Registry : registerAgent(agentAddress, ed25519PubKey, signature)
Registry-->>Client : didHash (PendingBond)
Client->>Staking : depositStake(didHash, amount)
alt amount >= minimumStake
Staking->>Registry : updateStatus(didHash, Active)
end
Oracle->>Reputation : proposeReputation(didHash, data, evidenceRoot)
Reputation->>Registry : check identity + stakeView
Reputation-->>Client : finalizeReputation(didHash) after window
Reputation-. reads .-> E8004 : external feedback
Diagram sources
- SigvaraIdentity.sol:295-321
- SigvaraStaking.sol:320-363
- SigvaraReputation.sol:378-448
- ADR 0001 — ERC-8004 as the identity layer:24-36
- DID format:
did:sigvara:<chainId>:<agentAddress>. - DID hash:
keccak256(abi.encodePacked("did:sigvara:", chainId, ":", agentAddress)). - Off-chain Ed25519 public key (raw 32 bytes) is stored in
SigvaraIdentityfor A2A challenge-response verification. - SDK helpers:
-
formatDid,computeDidHashmirror on-chain derivation. -
pubKeyToBytes32converts Ed25519 public key to bytes32 hex for registration. -
pubKeyToMultibaseproduces W3C DID-compatible multibase representation.
-
flowchart TD
Start(["Create Agent"]) --> GenKeys["Generate Ed25519 Keypair"]
GenKeys --> FormatDid["Format DID<br/>did:sigvara:<chainId>:<agentAddress>"]
FormatDid --> ComputeHash["Compute didHash<br/>keccak256(...)"]
ComputeHash --> Register["Register on SigvaraIdentity<br/>with signature"]
Register --> StoreKey["Store Ed25519 Public Key<br/>bytes32"]
Diagram sources
Section sources
- Registration digest binds:
- Chain ID and registry address (prevents replay across deployments).
- Agent address (claims ownership).
- Operator address (binds who controls the identity).
- Ed25519 public key (prevents key substitution).
- Verification uses
SignatureChecker, supporting EOAs and ERC-1271 contracts. - New identities start in
PendingBond; they are not immediately Active.
sequenceDiagram
participant Client as "Operator"
participant Registry as "SigvaraIdentity"
participant Wallet as "Agent Address"
Client->>Registry : registrationDigest(agentAddress, operator, ed25519PubKey)
Wallet->>Wallet : sign(EIP-191 digest)
Client->>Registry : registerAgent(agentAddress, ed25519PubKey, signature)
Registry->>Registry : verifyRegistration()
Registry-->>Client : didHash (status = PendingBond)
Diagram sources
Section sources
- Operator is the account controlling stake and status changes.
- Two-step transfer prevents accidental loss:
offerOperatorTransfer(didHash, newOperator)acceptOperatorTransfer(didHash)
- Transfers are blocked while slash is pending and require the agent to be bonded at handover.
- Transfer records:
-
operatorChangedAtrestarts reputation maturity. -
operatorTransferCountreports ownership history.
-
flowchart TD
Offer["offerOperatorTransfer(newOperator)"] --> CheckSlash{"Slash pending?"}
CheckSlash --> |Yes| Block["Revert"]
CheckSlash --> |No| Accept["acceptOperatorTransfer()"]
Accept --> CheckBond{"Has minimum stake?"}
CheckBond --> |No| Revert["Revert InsufficientCollateral"]
CheckBond --> |Yes| Update["Update operator,<br/>record changedAt,<br/>increment count"]
Diagram sources
Section sources
States:
-
PendingBond: Registered but not yet bonded. It cannot be scored until it is bonded, but any stake it has already posted can be slashed. -
Active: Bonded and operational. Can earn reputation. -
Suspended: Temporarily halted; may be self-suspended or slashed-initiated. -
Slashed: Terminal; cannot rotate keys or change status.
Transitions:
- Registration →
PendingBond. - Deposit ≥ minimumStake while
PendingBond→Active. - Operator ↔
Suspendedtoggle allowed; returning toActiverequires collateral. - Staking core sets
Slashed; no further transitions. - Slash suspension lock prevents operator from clearing staking-applied suspension mid-slash.
- When a slash proposal is dropped (committee cancel, admin veto or ruling,
expireDispute,expireSlash), the staking core returns the agent toActiveif its bond is still at leastminimumStake. Otherwise the agent staysSuspendedwith the lock cleared, and its operator re-bonds and reactivates it.
stateDiagram-v2
[*] --> PendingBond : "registerAgent"
PendingBond --> Active : "depositStake >= minimumStake"
Active --> Suspended : "updateStatus(operator)"
Suspended --> Active : "updateStatus(operator) if bonded"
Active --> Slashed : "stake.executeSlash()"
Suspended --> Slashed : "stake.executeSlash()"
Slashed --> [*] : "terminal"
Diagram sources
Section sources
- SigvaraIdentity.sol:56-64
- SigvaraIdentity.sol:344-397
- SigvaraStaking.sol:712-776
- SigvaraStaking.sol:683-701
- SigvaraIdentity.sol:537-548
- SigvaraIdentity.t.sol:55-132
- SDK generates Ed25519 keys and encodes them as bytes32 for on-chain storage.
-
SigvaraIdentitystores the raw 32-byte public key per agent. - A2A authentication uses challenge-response:
- Verifier issues a challenge with prover DID and audience.
- Prover signs the payload with its Ed25519 secret key.
- Verifier verifies against the on-chain public key.
sequenceDiagram
participant Verifier as "Verifier"
participant Prover as "Prover Agent"
participant Registry as "SigvaraIdentity"
Verifier->>Prover : issueChallenge(proverDid, audience)
Prover->>Prover : signChallengeFor(payload, audience)
Prover-->>Verifier : base58(signature)
Verifier->>Registry : getIdentity(didHash)
Registry-->>Verifier : ed25519PubKey
Verifier->>Verifier : verifyChallenge(payload, signature, publicKey)
Diagram sources
Section sources
- ERC-8004 provides canonical identity and raw feedback; Sigvara computes a normalized 6-factor score.
- Factors include fee activity, success rate, tenure, external trust (from ERC-8004), community flags, and propagation.
- Scores are proposed by oracles, challenged during a window, then finalized.
- Maturity ensures earned scores become spendable gradually; transfers restart maturity.
flowchart TD
Link["Link ERC-8004 agent id"] --> External["Read ERC-8004 feedback"]
Payments["Scan payments & attestations"] --> Factors["Compute 6 factors"]
External --> Factors
Factors --> Propose["proposeReputation(didHash, data, root)"]
Propose --> Window["Challenge window"]
Window --> Finalize["finalizeReputation()"]
Finalize --> Mature["Matured score over time"]
Diagram sources
Section sources
- reputation-model.md:7-17
- reputation-model.md:132-149
- SigvaraReputation.sol:378-504
- SigvaraReputation.sol:696-752
- Agent creation:
- Generate Ed25519 keypair.
- Compute DID and didHash.
- Sign registration digest.
- Call
registerAgent.
- Activation:
- Deposit stake ≥ minimumStake.
- Identity transitions to Active.
- Operation:
- Perform tasks; receive payments.
- Oracle proposes reputation; consumers check matured score.
- Recovery:
- Rotate Ed25519 key if compromised.
- Suspend and re-bond if needed.
- Exit or penalty:
- Initiate withdrawal; claim after unbonding.
- If slashed, identity becomes terminal; must register a new agent.
Section sources
- agent.ts:43-51
- SigvaraIdentity.sol:295-321
- SigvaraStaking.sol:320-363
- SigvaraIdentity.sol:328-336
- SigvaraStaking.sol:377-461
- SigvaraStaking.sol:712-776
-
SigvaraIdentitydepends on:- AccessControlUpgradeable and UUPSUpgradeable.
-
TimelockedGrants(lets the admin revoke upgrader-administered roles at once) andInflowGuard(the guardian’s pause on registrations), on main. - OpenZeppelin cryptography utilities for signature verification.
- The
IStakeViewinterface to check collateral for activation. It is wired after deployment: untilinitializeV2orsetStakeViewsets it, any move toActivereverts withStakeViewNotSet, and on mainsetStakeViewneedsUPGRADER_ROLE.
-
SigvaraReputationdepends on:-
SigvaraIdentityto validate scorable agents. - Optional
IOperatorSetto enforce bonded oracles.
-
-
SigvaraStakingdepends on:-
SigvaraIdentityfor status and operator checks. -
SigvaraReputationonly via a narrow interface to zero scores on slash.
-
graph LR
ID["SigvaraIdentity"] --> StakeView["IStakeView"]
REP["SigvaraReputation"] --> ID
REP --> OpSet["IOperatorSet"]
STK["SigvaraStaking"] --> ID
STK --> RepZero["IReputationZero"]
Diagram sources
- SigvaraIdentity.sol:4-7
- SigvaraIdentity.sol:18-20
- SigvaraReputation.sol:7-11
- SigvaraReputation.sol:12
- SigvaraStaking.sol:12-29
Section sources
- SigvaraIdentity.sol:4-7
- SigvaraIdentity.sol:18-20
- SigvaraReputation.sol:7-11
- SigvaraReputation.sol:12
- SigvaraStaking.sol:12-29
- Operator agent list removal was optimized from linear scan to constant-time swap-and-pop using a recorded index. Fallback scan remains for legacy entries.
- Paging functions (
getOperatorAgentsPaged) allow safe consumption without unbounded gas costs. - Reputation maturity is computed on read, avoiding frequent writes and allowing accrual even if oracles pause.
- Evidence roots enable off-chain verification without trusting oracle JSON files.
Common issues and resolutions:
- Registration fails due to bad signature:
- Ensure the agent address signs the exact
registrationDigest. - Verify chain ID and registry address are correct.
- Ensure the agent address signs the exact
- Cannot return to Active after suspension:
- Ensure minimum stake is posted; activation checks collateral.
- Slash suspension lock prevents reactivation:
- Only staking core can clear the lock, and it does so when the proposal is dropped: a committee cancel, an admin veto or ruling,
expireDispute14 days after a dispute, orexpireSlash14 days after the challenge deadline of an undisputed proposal. An executed slash leaves the agent Slashed, which is terminal.
- Only staking core can clear the lock, and it does so when the proposal is dropped: a committee cancel, an admin veto or ruling,
- Operator transfer blocked:
- Slash pending transfers are disallowed; ensure no active slash proposal.
- Agent must be bonded at handover.
- Reputation not scoring:
- Agent must be registered, not slashed, and bonded.
- Identity registry and stake view must be configured.
- Proposals are closed while a guardian pause is running.
- Registration reverts with
InflowsPausedUntil:- A guardian pause is running. It ends by itself within three days.
Section sources
- SigvaraIdentity.sol:295-321
- SigvaraIdentity.sol:344-397
- SigvaraIdentity.sol:410-468
- SigvaraReputation.sol:620-631
- SigvaraIdentity.t.sol:55-132
Sigvara’s identity layer positions ERC-8004 as the canonical foundation for agent identity and raw feedback, while Sigvara adds computed reputation and staked accountability. Deterministic DIDs anchor off-chain Ed25519 keys, operator control is explicit and secure, and the status machine enforces “bond before trust.” Slashing provides economic finality, ensuring reputation is meaningful because it can be destroyed. Together, these components form a robust, extensible identity and reputation system suitable for decentralized AI agent ecosystems.
- 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