Skip to content

Smart Contracts Reference

RunTimeAdmin edited this page Oct 30, 2026 · 20 revisions

Smart Contracts Reference

**Referenced Files in This Document** - [SigvaraIdentity.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraIdentity.sol) - [SigvaraStaking.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraStaking.sol) - [SigvaraReputation.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraReputation.sol) - [SigvaraOracleBond.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraOracleBond.sol) - [README.md](https://github.com/RunTimeAdmin/Sigvara/blob/main/README.md) - [TimelockedGrants.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/TimelockedGrants.sol) - [InflowGuard.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/InflowGuard.sol) - [SigvaraReader.sol](https://github.com/RunTimeAdmin/Sigvara/blob/main/src/SigvaraReader.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

This document is a comprehensive reference for Sigvara’s Solidity contracts: the identity registry, staking and slashing engine, reputation store, and oracle operator bond registry. It explains the contract hierarchy, upgradeable proxy pattern, access control, public interfaces, state transitions, events, error codes, gas optimizations, usage flows, security considerations, and upgrade/migration procedures.

The system anchors AI agent identities on-chain, enforces slashable bonds, stores computed reputation scores, and optionally gates oracle operators behind a performance bond. All contracts are upgradeable via UUPS proxies and use OpenZeppelin AccessControl roles to separate governance, upgrades, and protocol operations.

This page describes the contracts on main. The Arc testnet proxies have run these contracts since 26 October 2026, so the guardian pause, the admin ruling and veto on slashes, the lapse of an unexecuted proposal, the re-file cooldown, the period ceilings, the operator signer registry, the stored proposer and fixed review window on scores, the reporter check at slash execution, the fixed claim time for a queued withdrawal and the refusal of rejected evidence are live there. The one later contract change, the bound on upholding a dispute, is on main only and reaches them at their next upgrade. The role administrators were written by the September initialisation, so the timelocked role grants of the shared bases below do not apply to them.

Project Structure

The core protocol lives under src/:

  • SigvaraIdentity.sol — DID registration, Ed25519 key storage, operator transfer, status management, and stake-view wiring.
  • SigvaraStaking.sol — ERC-20 bond deposits, unbonding, slashing lifecycle, and reputation zeroing.
  • SigvaraReputation.sol — Oracle-proposed 6-factor score store with challenge windows, maturity, and evidence roots.
  • SigvaraOracleBond.sol — Operator admission, partial slashing, and unbonding for the oracle operator set.
  • TimelockedGrants.sol and InflowGuard.sol: two small abstract bases that the four registries inherit. Neither is deployed on its own.
  • SigvaraReader.sol: a stateless, non-upgradeable read helper for contracts that check an agent's standing. It is not a registry, holds nothing, and is not read by the protocol; it has not been deployed anywhere.
graph TB
ID["SigvaraIdentity<br/>Agent registry"] --> ST["SigvaraStaking<br/>Bonds + slashing"]
ST --> REP["SigvaraReputation<br/>Score store"]
ORB["SigvaraOracleBond<br/>Operator bond"] --> REP
REP --> CONSUMERS["On-chain consumers"]
Loading

Diagram sources

Section sources

Core Components

  • SigvaraIdentity: Base registry that computes deterministic DIDs, stores Ed25519 keys, manages operator ownership, and gates status transitions against collateral via a stake view.
  • SigvaraStaking: Manages SVR token bonds per agent, enforces minimum stake, unbonding, and committee-filed slashing with admin-ruled dispute resolution.
  • SigvaraReputation: Stores oracle-proposed 6-factor scores, exposes matured spendable scores, and supports evidence verification.
  • SigvaraOracleBond: Tracks bonded oracle operators, admits/removes them, slashes their performance bonds, and lets an operator name a signer.

Key design principles across all contracts:

  • Upgradeable via UUPS with an UPGRADER_ROLE, which administers itself so the admin cannot grant it.
  • Role-based access control using OpenZeppelin AccessControlUpgradeable, through TimelockedGrants in the four registries.
  • Append-only storage layout changes to preserve live proxy state.
  • Fail-closed initialization where unset dependencies block unsafe behavior.
  • Floors and ceilings on the periods, the window and the maturity rate, held in the initializers as well as the setters.
  • A guardian pause on new inflows (InflowGuard) that never covers exits, rulings or slash execution.

Section sources

Architecture Overview

The architecture layers ERC-8004 identity with Sigvara’s trust layer:

  • Identity is anchored by SigvaraIdentity, which also binds operator control and agent status.
  • Staking backs agents with SVR and enables slashing; it coordinates with identity and reputation.
  • Reputation stores computed scores from oracles and exposes threshold checks.
  • Oracle bond ensures only admitted, bonded operators can propose scores when configured.
sequenceDiagram
participant Op as "Operator"
participant ID as "SigvaraIdentity"
participant ST as "SigvaraStaking"
participant REP as "SigvaraReputation"
participant ORB as "SigvaraOracleBond"
Op->>ID : registerAgent(agentAddress, ed25519PubKey, signature)
ID-->>Op : AgentRegistered(didHash, operator, agentAddress, pubKey)
Op->>ST : depositStake(didHash, amount)
ST->>ID : updateStatus(didHash, Active)
Note over ST,ID : Agent becomes Active once minimumStake is met
ORB->>REP : (optional) admit operator if operatorBond is set
REP-->>ORB : isActiveOperator check
REP->>REP : proposeReputation(didHash, data, evidenceRoot)
REP-->>REP : finalizeReputation(didHash) after challenge window
Loading

Diagram sources

Detailed Component Analysis

Shared Bases: TimelockedGrants and InflowGuard

Identity, staking, reputation and the operator bond registry all inherit these two abstract contracts.

TimelockedGrants

  • Each registry makes UPGRADER_ROLE its own role admin, and administers the roles that can move bonded funds or change an agent's standing with it: SLASHING_COMMITTEE_ROLE (staking, reputation), STAKING_CORE_ROLE (identity, reputation) and SLASHER_ROLE (bond registry). Granting one therefore takes the timelock's delay.
  • It overrides revokeRole so that DEFAULT_ADMIN_ROLE can revoke at once any role the upgrader administers, except UPGRADER_ROLE. ORACLE_ROLE and GUARDIAN_ROLE stay with the admin.
  • It adds no storage.

InflowGuard

  • pauseInflows() is callable only by GUARDIAN_ROLE. It closes the entries marked whenInflowsOpen for PAUSE_DURATION (3 days): registerAgent, depositStake, proposeReputation, proposeIfEmpty and depositBond. Nothing else is covered.
  • The next pause cannot start until PAUSE_COOLDOWN (1 day) after the last one would have ended, counted from its start even if it was lifted early.
  • resumeInflows() lifts a pause early and is callable by the guardian or the admin. Views: inflowsPaused(), inflowsPausedUntil(), lastInflowPauseAt().
  • Events: InflowsPaused, InflowsResumed. Errors: InflowsPausedUntil, InflowsNotPaused, InflowsAlreadyPaused, PauseCooldownActive.
  • State lives in an ERC-7201 namespaced slot, so adding it to a live proxy shifts no existing variable.

Section sources

SigvaraIdentity

Base registry for agent identities and operator control.

Key responsibilities

  • Deterministic DID derivation and registration with signed proof of agent control.
  • Ed25519 public key storage and rotation.
  • Status transitions: PendingBond → Active ↔ Suspended → Slashed.
  • Two-step operator transfer with collateral checks.
  • Stake view integration to gate activation and transfers.

Public interface summary

  • registrationDigest(agentAddress, operator, ed25519PubKey) returns digest bytes32.
  • verifyRegistration(agentAddress, operator, ed25519PubKey, signature) returns bool.
  • registerAgent(agentAddress, ed25519PubKey, signature) returns didHash. Closed while a guardian pause is running.
  • rotatePublicKey(didHash, newEd25519PubKey).
  • updateStatus(didHash, newStatus).
  • offerOperatorTransfer(didHash, newOperator).
  • cancelOperatorTransfer(didHash).
  • acceptOperatorTransfer(didHash).
  • setStakeView(stakeView_), callable only by UPGRADER_ROLE (the timelock), because what it points at decides who counts as bonded.
  • clearSlashSuspension(didHash).
  • View functions: computeDidHash, getIdentity, isActive, getOperatorAgents, operatorAgentCount, getOperatorAgentsPaged.

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

Diagram sources

Events

  • AgentRegistered(didHash, operator, agentAddress, ed25519PubKey)
  • StakeViewSet(stakeView)
  • OperatorTransferOffered(didHash, from, to)
  • OperatorTransferCancelled(didHash, by)
  • OperatorTransferred(didHash, from, to)
  • AgentStatusUpdated(didHash, newStatus)
  • PublicKeyRotated(didHash, newEd25519PubKey)

Errors

  • AlreadyRegistered, NotRegistered, NotOperator, ZeroPubKey, ZeroAgentAddress, SlashedAgentImmutable, SlashSuspensionLocked, StakeViewNotSet, InsufficientCollateral, NoTransferOffered, NotOfferedOperator, TransferWhileSlashPending, SameOperator, CannotReturnToPendingBond, BadRegistrationSignature.

Gas and storage notes

  • Appended storage fields preserve proxy layout.
  • Constant-time removal from operator index via swap-and-pop with recorded positions.
  • Paged operator listing avoids unbounded reads for callers.

Section sources

SigvaraStaking

Manages agent bonds and slashing.

Key responsibilities

  • Deposit and track SVR token stakes per agent.
  • Enforce minimum stake and unbonding period.
  • Initiate slash proposals, handle disputes, execute slashes, and distribute proceeds.
  • Zero reputation upon slash.

Public interface summary

  • depositStake(didHash, amount). Closed while a guardian pause is running.
  • initiateWithdrawal(didHash, amount). Fixes the claim time when it queues.
  • claimWithdrawal(didHash). Honours the claim time fixed when the withdrawal was queued.
  • initiateSlash(didHash, victim, evidenceHash). Committee only; refused for one challenge period after the last dropped proposal against the agent, and refused for evidence the admin already rejected for the agent.
  • disputeSlash(didHash).
  • resolveDispute(didHash, uphold). Admin only; upholding waits for the challenge deadline and, on main, is refused once the dispute can be expired (DisputeResolutionExpired).
  • expireDispute(didHash). Permissionless once the dispute resolution period (14 days) has passed.
  • expireSlash(didHash). Permissionless once the execution period (14 days) has passed since the challenge deadline of a pending proposal.
  • cancelSlash(didHash). Committee only.
  • vetoSlash(didHash). Admin only; drops a pending or disputed proposal and records its evidence as rejected for the agent.
  • executeSlash(didHash). Permissionless once the challenge deadline has passed, as long as the reporter still holds the committee role.
  • claimSlashProceeds() returns amount.
  • Admin: setMinimumStake, setChallengePeriod, setUnbondingPeriod.
  • Views: getStake, hasMinimumStake, getPendingWithdrawal, getSlashProposal, lastDroppedAt, unbondingClaimableAt, evidenceRejected.

Slash lifecycle flow

flowchart TD
Start(["Initiate Slash"]) --> CheckRoles["Check SLASHING_COMMITTEE_ROLE"]
CheckRoles --> ValidateVictim{"Victim != Reporter?"}
ValidateVictim --> |No| RevertVictim["Revert VictimIsReporter"]
ValidateVictim --> |Yes| CheckStake{"Total stake > 0?"}
CheckStake --> |No| RevertNoStake["Revert NoStake"]
CheckStake --> WriteProposal["Write SlashProposal(Pending)"]
WriteProposal --> SuspendAgent["Update Identity to Suspended"]
SuspendAgent --> EmitInitiated["Emit SlashInitiated"]
EmitInitiated --> DisputePath{"Disputed within window?"}
DisputePath --> |Yes| Dispute["State=Disputed"]
Dispute --> Resolve["Admin rules: uphold or drop"]
Resolve --> Uphold["Settle Slash"]
Resolve --> Drop["Drop Proposal"]
DisputePath --> |No| Execute["Anyone executes after window"]
Execute --> Settle["Settle Slash"]
Settle --> Burn["Burn 50%"]
Settle --> PayVictim["Credit 25% to victim"]
Settle --> PayReporter["Credit 25% to reporter"]
Settle --> MarkSlashed["Mark Identity Slashed"]
Settle --> ZeroRep["Zero Reputation"]
Loading

Diagram sources

Events

  • StakeDeposited, WithdrawalInitiated, WithdrawalClaimed
  • SlashInitiated, SlashDisputed, SlashExecuted, SlashCancelled, SlashVetoed
  • SlashProceedsClaimed
  • MinimumStakeUpdated, ChallengePeriodUpdated, UnbondingPeriodUpdated

Errors

  • InsufficientStake, NoStake, AgentNotActive, SlashAlreadyPending, NoActivePendingSlash, ChallengePeriodActive, ChallengePeriodExpired, NotOperator, ZeroAddress, NoWithdrawalPending, WithdrawalAlreadyPending, UnbondingPeriodActive, VictimIsReporter, PeriodTooShort, PeriodTooLong, MinimumStakeZero, SlashNotDisputed, SlashCooldownActive, DisputeResolutionActive, DisputeResolutionExpired (on main), ExecutionPeriodActive, NothingClaimable.

Security and economic notes

  • Fee-on-transfer tokens are handled safely by measuring actual received amounts.
  • Rebasing tokens are unsupported due to fixed accounting.
  • Unbonding queue remains slashable until claimed.
  • Minimum and maximum challenge/unbonding periods (3 to 30 days and 1 to 90 days) enforced by the admin setters and by initialize; a zero minimum stake is refused.
  • The committee files and the admin rules, so no single key is accuser, judge and payee. A dispute cannot bring a slash forward, a proposal nobody executes can be lapsed by anyone, and a dropped proposal starts a re-file cooldown of one challenge period.

Section sources

SigvaraReputation

Stores oracle-proposed 6-factor reputation scores and exposes matured spendable values.

Key responsibilities

  • Accept oracle proposals with factor caps and evidence roots.
  • Challenge window with committee rejection.
  • Finalize scores and compute matured spendable totals.
  • Verify Merkle evidence leaves.
  • Optional operator bond gating via SigvaraOracleBond.

Public interface summary

  • proposeReputation(didHash, data, evidenceRoot). Closed while a guardian pause is running. The pending score records its proposer and finalizableAt, the time it can first be finalized, fixed when it is proposed.
  • proposeIfEmpty(didHash, data, evidenceRoot). Reverts instead of replacing a pending proposal, unless that proposal's proposer is no longer authorized.
  • finalizeReputation(didHash). Permissionless, but refuses a proposal whose proposer no longer holds ORACLE_ROLE or, with an operator registry configured, is no longer an active operator or signer.
  • rejectReputation(didHash). Committee only, within the window fixed at proposal time.
  • zeroReputation(didHash) (STAKING_CORE_ROLE).
  • Admin: initializeV2, initializeV3, initializeV4, setOperatorBond (UPGRADER_ROLE, the timelock's role), setMaturityRate (above 0, at most 100 points a day), setChallengeWindow (1 hour to 7 days).
  • Views: getReputation, getPendingScore, getTotalScore, verifyEvidence, getEarnedScore, meetsThreshold.

Score model

  • Six capped factors summing to 100: fee, success, age, external, community, propagation.
  • Matured score climbs toward earned score at a configurable rate per day.
  • Handover restarts maturity to prevent immediate spending of purchased identities.

Events

  • ScoreProposed, ReputationUpdated, ScoreRejected, ReputationZeroed
  • ChallengeWindowUpdated, IdentityRegistrySet, MaturityRateUpdated, OperatorBondSet

Errors

  • ScoreOutOfRange, NoScorePending, ScoreAlreadyPending, ChallengeWindowActive, ChallengeWindowExpired, IdentityRegistryNotSet, StakeViewNotSet, AgentNotRegistered, AgentSlashed, AgentNotBonded, MaturityRateZero, MaturityRateTooHigh, ChallengeWindowTooShort, ChallengeWindowTooLong, OracleNotBonded, ProposerNotAuthorized.

Evidence verification

  • verifyEvidence(didHash, leaf, proof) uses MerkleProof against stored root.

Section sources

SigvaraOracleBond

Performance-bond registry for oracle operators.

Key responsibilities

  • Deposit/top-up operator bonds.
  • Admit/remove operators.
  • Partial slashing with demotion below bondAmount.
  • Unbonding cooldown before withdrawal.

Public interface summary

  • depositBond(amount). Closed while a guardian pause is running, and refused for an address that is some operator's signer.
  • initiateUnbond().
  • withdrawBond(). Also releases the operator's signer.
  • setSigner(signer). Active operators only; names the key that signs for the operator, which must be an address nobody else uses in the registry.
  • clearSigner(). Any status; takes effect in the same block.
  • admit(operator).
  • removeOperator(operator). Does not release the operator's signer.
  • slash(operator, amount). SLASHER_ROLE, which is granted through the timelock; slashing to zero also releases the signer.
  • Admin: setBondAmount (above zero), setUnbondingPeriod (1 to 90 days), setSlashBeneficiary (UPGRADER_ROLE; refuses the zero address and any holder of the slasher role).
  • Views: isActiveOperator (a registered signer answers for its operator), bondOf, signerOf, operatorOfSigner.

Operator lifecycle

stateDiagram-v2
[*] --> Bonded : depositBond()
Bonded --> Active : admit() with bond >= bondAmount
Active --> Exiting : initiateUnbond() or removeOperator()
Bonded --> Exiting : initiateUnbond() or removeOperator()
Exiting --> None : withdrawBond() after cooldown
Active --> Bonded : slash() drops below bondAmount
Bonded --> None : slash() reduces bond to 0
Loading

Diagram sources

Events

  • BondDeposited, OperatorAdmitted, OperatorSlashed, UnbondInitiated, BondWithdrawn, OperatorRemoved
  • BondAmountUpdated, UnbondingPeriodUpdated, SlashBeneficiaryUpdated
  • SignerSet, SignerCleared

Errors

  • ZeroAddress, ZeroAmount, PeriodTooShort, PeriodTooLong, WrongStatus, InsufficientBond, SlashExceedsBond, UnbondingActive, NoBond, SignerNotFree, AlreadySigner, NoSigner, SlasherIsBeneficiary.

Section sources

Dependency Analysis

Contract-level dependencies:

  • SigvaraStaking imports SigvaraIdentity and uses a narrow interface to SigvaraReputation (IReputationZero).
  • SigvaraReputation imports SigvaraIdentity and uses a narrow interface to SigvaraOracleBond (IOperatorSet, in src/interfaces/IOperatorSet.sol, which the bond registry implements and SigvaraEpochFees uses too).
  • SigvaraIdentity declares a narrow interface IStakeView to avoid circular imports while checking collateral.
  • All four registries inherit TimelockedGrants and InflowGuard.
graph LR
ST["SigvaraStaking"] --> ID["SigvaraIdentity"]
ST -.-> REP["SigvaraReputation (interface IReputationZero)"]
REP --> ID
REP -.-> ORB["SigvaraOracleBond (interface IOperatorSet)"]
Loading

Diagram sources

Section sources

Performance Considerations

  • Fee-on-transfer safety: Both staking and oracle bond measure actual received amounts rather than trusting caller-supplied amounts.
  • Storage layout stability: New variables are appended to preserve live proxy state without renumbering mappings.
  • Constant-time operator index removal: Swap-and-pop with recorded positions avoids linear scans on hot paths.
  • Paged queries: Operator agent lists support pagination to avoid unbounded reads.
  • Fail-closed initialization: Missing stake view or identity registry blocks unsafe transitions.
  • Period guards: Challenge and unbonding periods have lower bounds to prevent liveness attacks and upper bounds so one value cannot lock every queued exit.

Troubleshooting Guide

Common issues and resolutions:

  • Registration fails with signature error: Ensure the agent address signs the unprefixed registrationDigest; wallets apply EIP-191 prefix automatically.
  • Activation fails with insufficient collateral: Confirm the agent holds at least minimumStake and that stakeView is set on identity.
  • Slash proposal reverts: Check that the victim is not the reporter, total stake is non-zero, no active slash exists, and no proposal against the agent was dropped less than one challenge period ago.
  • Dispute cannot be filed: Ensure the challenge window has not expired and the caller is the operator.
  • Finalization fails: Ensure the challenge window elapsed, a pending score exists, and its proposer is still authorized.
  • Operator cannot propose scores: If operatorBond is set, the caller must be an admitted, bonded operator in SigvaraOracleBond, or the signer one has named.
  • Registration, deposit, proposal or bond deposit reverts with InflowsPausedUntil: A guardian pause is running; it ends by itself after three days.

Section sources

Conclusion

Sigvara’s contracts form a cohesive trust layer over ERC-8004 identity: deterministic DID anchoring, slashable bonds, computed reputation with maturity, and optional operator bonding. The design emphasizes safe upgrades, role separation, fail-closed configuration, and robust economic incentives. Consumers should rely on getTotalScore and meetsThreshold for decisions, and integrate identity checks alongside reputation thresholds.

Appendices

Usage Examples

Agent Registration and Activation

  1. Compute registrationDigest(agentAddress, operator, ed25519PubKey).
  2. Have the agent address sign the digest.
  3. Call registerAgent(agentAddress, ed25519PubKey, signature) on SigvaraIdentity.
  4. Approve and call depositStake(didHash, amount) on SigvaraStaking.
  5. On first deposit reaching minimumStake, the agent becomes Active.

Section sources

Stake Management

  • Deposit: depositStake(didHash, amount).
  • Queue withdrawal: initiateWithdrawal(didHash, amount).
  • Claim withdrawal: claimWithdrawal(didHash) after unbonding period.
  • Query stake: getStake(didHash) and hasMinimumStake(didHash).

Section sources

Reputation Queries

  • Get earned score: getEarnedScore(didHash).
  • Get matured score: getTotalScore(didHash).
  • Threshold check: meetsThreshold(didHash, threshold).
  • Evidence verification: verifyEvidence(didHash, leaf, proof).

Section sources

Security Considerations

  • Token assumptions: Only exact-transfer ERC-20 tokens are fully supported; rebasing tokens are explicitly unsupported.
  • Role separation: Governance timelock targets mainnet; testnet currently uses single EOAs. On mainnet the roles that move funds are granted through the timelock, the admin rules on disputed slashes and can veto, and a guardian can pause new inflows only.
  • Upgrade safety: UUPS upgrades gated by UPGRADER_ROLE, which administers itself; initialize methods enforce fail-closed wiring.
  • Launch floors: On chain 5042 script/Deploy.s.sol refuses a minimum stake under 10,000 SVR and script/DeployOracleBond.s.sol a bond under 2,500,000 SVR, refuses periods outside the contracts' floors and ceilings, and requires a guardian that is not the deployer, oracle, committee or slasher.
  • Slash integrity: Total stake (active + queued) is checked to prevent evasion via unbonding.
  • Reputation gating: Scores require a bonded agent and valid identity; handover restarts maturity.

Section sources

Upgrade Procedures and Migration Strategies

  • Use UUPS proxies; proxy addresses are stable while the implementation behind them changes.
  • Deploy new implementation and call upgradeToAndCall with versioned initializers:
    • initializeV2 for setting stake view or unbonding periods.
    • initializeV3 for wiring identity registry in reputation.
    • initializeV4 for setting maturity rate.
  • Reinitializers are DEFAULT_ADMIN_ROLE-gated, and the timelock is not the admin, so behind a timelock the upgrade lands with empty data and the Safe calls the reinitializer in a second transaction.
  • Keep storage layout append-only to preserve live state.
  • Record implementations off-chain and verify against chain state.

Section sources

Overview

Clone this wiki locally