-
Notifications
You must be signed in to change notification settings - Fork 0
Deployment and Operations Deployment Guide
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Deployment Process
- UUPS Proxy Pattern Implementation
- Initialization Parameters
- Governance and Access Control
- Environment-Specific Deployment
- Address Management
- Migration Procedures
- Verification and Monitoring
- Rollback Procedures
- Troubleshooting Guide
- Conclusion
This document provides comprehensive deployment documentation for the Countersig Network smart contracts. Countersig Network implements on-chain identity, reputation, and staking infrastructure for autonomous AI agents using UUPS upgradeable proxies. The deployment process follows Foundry standards and includes complete initialization procedures for all protocol contracts.
The protocol consists of three core contracts:
- CountersigIdentity: Decentralized identity anchoring with Ed25519 public key storage
- CountersigReputation: 6-factor reputation scoring system
- CountersigStaking: $CSIG token bonding with slashing mechanism
The repository follows a standard Foundry project layout with the following key directories and files:
graph TB
subgraph "Root Directory"
A[script/] --> B[Deploy.s.sol]
C[src/] --> D[CountersigIdentity.sol]
C --> E[CountersigReputation.sol]
C --> F[CountersigStaking.sol]
C --> G[CSIGToken.sol]
H[deployments/] --> I[11155111.json]
J[broadcast/] --> K[Deploy.s.sol/11155111/]
L[foundry.toml] --> M[Configuration]
N[README.md] --> O[Documentation]
end
Diagram sources
- foundry.toml:1-21
- script/Deploy.s.sol:1-130
Section sources
- foundry.toml:1-21
- README.md:1-415
The Identity contract anchors AI agent identities on-chain using Deterministic Identity Documents (DIDs):
classDiagram
class CountersigIdentity {
+bytes32 STAKING_CORE_ROLE
+bytes32 UPGRADER_ROLE
+enum AgentStatus
+mapping(bytes32, AgentIdentity) identities
+mapping(address, bytes32[]) operatorAgents
+constructor()
+initialize(admin, stakingCore)
+registerAgent(agentAddress, ed25519PubKey)
+rotatePublicKey(didHash, newEd25519PubKey)
+updateStatus(didHash, newStatus)
+computeDidHash(agentAddress) bytes32
+_authorizeUpgrade(address)
}
class AgentIdentity {
+address operator
+address agentAddress
+bytes32 ed25519PubKey
+AgentStatus status
+uint256 registeredAt
}
CountersigIdentity --> AgentIdentity : "stores"
Diagram sources
- CountersigIdentity.sol:18-227
The Reputation contract manages 6-factor scoring system:
classDiagram
class CountersigReputation {
+bytes32 ORACLE_ROLE
+bytes32 STAKING_CORE_ROLE
+bytes32 UPGRADER_ROLE
+mapping(bytes32, ReputationData) reputations
+constructor()
+initialize(admin, oracle, stakingCore)
+updateReputation(didHash, data)
+zeroReputation(didHash)
+getTotalScore(didHash) uint8
+_authorizeUpgrade(address)
}
class ReputationData {
+uint8 feeScore
+uint8 successScore
+uint8 ageScore
+uint8 externalScore
+uint8 communityScore
+uint8 propagationScore
+uint256 lastUpdated
}
CountersigReputation --> ReputationData : "stores"
Diagram sources
- CountersigReputation.sol:24-181
The Staking contract manages $CSIG token bonding and slashing:
classDiagram
class CountersigStaking {
+bytes32 SLASHING_COMMITTEE_ROLE
+bytes32 UPGRADER_ROLE
+mapping(bytes32, Stake) stakes
+mapping(bytes32, SlashProposal) slashProposals
+IERC20 csigToken
+CountersigIdentity identityRegistry
+CountersigReputation reputationRegistry
+uint256 minimumStake
+uint256 challengePeriod
+constructor()
+initialize(admin, identityRegistry, reputationRegistry, csigToken, minimumStake, challengePeriod)
+depositStake(didHash, amount)
+withdrawStake(didHash, amount)
+initiateSlash(didHash, victim, evidenceHash)
+disputeSlash(didHash)
+executeSlash(didHash)
+setMinimumStake(newMinimum)
+setChallengePeriod(newPeriod)
+_authorizeUpgrade(address)
}
class Stake {
+uint256 amount
+uint256 lockedAt
}
class SlashProposal {
+bytes32 didHash
+address reporter
+address victim
+uint256 initiatedAt
+SlashState state
+bytes evidenceHash
}
CountersigStaking --> Stake : "manages"
CountersigStaking --> SlashProposal : "tracks"
Diagram sources
- CountersigStaking.sol:28-331
Section sources
- CountersigIdentity.sol:18-227
- CountersigReputation.sol:24-181
- CountersigStaking.sol:28-331
The Countersig Network follows a modular architecture with UUPS upgradeable proxies:
graph TB
subgraph "Protocol Architecture"
subgraph "Core Contracts"
A[CountersigIdentity<br/>Identity Anchoring]
B[CountersigReputation<br/>Reputation Scoring]
C[CountersigStaking<br/>Staking & Slashing]
end
subgraph "Supporting Contracts"
D[CSIGToken<br/>$CSIG Token]
E[ERC1967Proxy<br/>UUPS Proxy]
end
subgraph "External Systems"
F[Oracle Network<br/>Reputation Updates]
G[Agent Nodes<br/>Ed25519 Signatures]
end
D --> C
A --> C
B --> C
E --> A
E --> B
E --> C
F --> B
G --> A
end
Diagram sources
- Deploy.s.sol:31-106
- README.md:20-51
The architecture implements a hub-and-spoke model where Staking acts as the central coordinator, while Identity and Reputation provide complementary services.
Before deployment, ensure you have:
- Foundry installed: https://getfoundry.sh
- RPC endpoint: For target network (testnet/mainnet)
- Private key: For deployer account with sufficient funds
- Environment variables: As specified below
Required environment variables for deployment:
| Variable | Description | Default Value |
|---|---|---|
DEPLOYER_PRIVATE_KEY |
Deployer's private key for broadcasting transactions | Required |
ORACLE_ADDRESS |
Address authorized to update reputation scores | Deployer (optional) |
COMMITTEE_ADDRESS |
3-of-5 multisig address for slashing committee | Deployer (optional) |
MINIMUM_STAKE |
Minimum $CSIG stake in wei (default: 1,000 CSIG) | 1,000 CSIG |
CHALLENGE_PERIOD |
Slash challenge window in seconds (default: 7 days) | 604,800 seconds |
# Set up environment variables
export DEPLOYER_PRIVATE_KEY="your_private_key_here"
export ORACLE_ADDRESS="0x..." # Optional
export COMMITTEE_ADDRESS="0x..." # Optional
export MINIMUM_STAKE="1000000000000000000000" # 1000 CSIG in wei
export CHALLENGE_PERIOD="604800" # 7 days# Install dependencies
forge install
# Build contracts
forge build# Testnet deployment (Sepolia)
forge script script/Deploy.s.sol \
--rpc-url $SEPOLIA_RPC \
--broadcast \
--verify \
-vvvvThe deployment script logs all deployed addresses and parameters to console and writes them to deployments/{chainId}.json.
The deployment follows this strict order:
sequenceDiagram
participant Deployer as "Deployer"
participant Script as "Deploy.s.sol"
participant Token as "CSIGToken"
participant Identity as "CountersigIdentity"
participant Reputation as "CountersigReputation"
participant Staking as "CountersigStaking"
participant Proxy as "ERC1967Proxy"
Deployer->>Script : Run deployment
Script->>Token : Deploy CSIGToken
Script->>Identity : Deploy implementation
Script->>Proxy : Create Identity proxy
Script->>Reputation : Deploy implementation
Script->>Proxy : Create Reputation proxy
Script->>Staking : Deploy implementation
Script->>Proxy : Create Staking proxy
Script->>Identity : Grant roles
Script->>Reputation : Grant roles
Script->>Staking : Grant roles
Script->>Deployer : Log addresses
Script->>Deployer : Write deployments JSON
Diagram sources
- Deploy.s.sol:35-106
Section sources
- Deploy.s.sol:12-30
- Deploy.s.sol:35-106
Countersig Network uses OpenZeppelin's ERC1967Proxy pattern with UUPS upgradeability:
classDiagram
class ERC1967Proxy {
+address implementation
+bytes32 administrationSlot
+constructor(implementation, initData)
+fallback() delegatecall
}
class UUPSUpgradeable {
+_authorizeUpgrade(address)
+upgradeTo(address)
+upgradeToAndCall(address, bytes)
}
class AccessControlUpgradeable {
+DEFAULT_ADMIN_ROLE
+grantRole(bytes32, address)
+revokeRole(bytes32, address)
+hasRole(bytes32, address)
}
class CountersigIdentity {
+initialize(address, address)
+_authorizeUpgrade(address)
}
class CountersigReputation {
+initialize(address, address, address)
+_authorizeUpgrade(address)
}
class CountersigStaking {
+initialize(address, address, address, address, uint256, uint256)
+_authorizeUpgrade(address)
}
ERC1967Proxy --> UUPSUpgradeable : "delegates"
UUPSUpgradeable --> AccessControlUpgradeable : "extends"
CountersigIdentity --> UUPSUpgradeable : "extends"
CountersigReputation --> UUPSUpgradeable : "extends"
CountersigStaking --> UUPSUpgradeable : "extends"
Diagram sources
- Deploy.s.sol:5-10
- CountersigIdentity.sol:18
- CountersigReputation.sol:24
- CountersigStaking.sol:28
Each contract implements _authorizeUpgrade() with role-based access control:
- UPGRADER_ROLE: Authorized to perform upgrades
- DEFAULT_ADMIN_ROLE: Grants all roles including UPGRADER_ROLE
Proxies are initialized using abi.encodeCall() with constructor arguments:
ERC1967Proxy(
address(implementation),
abi.encodeCall(Implementation.initialize, (args...))
)Section sources
- Deploy.s.sol:51-75
- CountersigIdentity.sol:225
- CountersigReputation.sol:179
- CountersigStaking.sol:329
| Parameter | Type | Description | Example |
|---|---|---|---|
owner |
address | Token ownership (deployer) | Deployer address |
| Parameter | Type | Description | Example |
|---|---|---|---|
admin |
address | DEFAULT_ADMIN_ROLE + UPGRADER_ROLE | Governance timelock |
stakingCore |
address | STAKING_CORE_ROLE (can be zero) | Staking contract address |
| Parameter | Type | Description | Example |
|---|---|---|---|
admin |
address | DEFAULT_ADMIN_ROLE + UPGRADER_ROLE | Governance timelock |
oracle |
address | ORACLE_ROLE (can be zero) | Oracle consensus contract |
stakingCore |
address | STAKING_CORE_ROLE (can be zero) | Staking contract address |
| Parameter | Type | Description | Example |
|---|---|---|---|
admin |
address | DEFAULT_ADMIN_ROLE + UPGRADER_ROLE | Governance timelock |
identityRegistry |
address | CountersigIdentity proxy | Identity proxy address |
reputationRegistry |
address | CountersigReputation proxy | Reputation proxy address |
csigToken |
address | $CSIG token address | CSIG token address |
minimumStake |
uint256 | Minimum stake in wei | 1,000 CSIG |
challengePeriod |
uint256 | Challenge period in seconds | 7 days |
Section sources
- CSIGToken.sol:12-26
- CountersigIdentity.sol:92-101
- CountersigReputation.sol:86-94
- CountersigStaking.sol:121-142
| Role | Holder (Testnet) | Permissions |
|---|---|---|
DEFAULT_ADMIN_ROLE |
Governance timelock | Grant/revoke all roles |
UPGRADER_ROLE |
Governance timelock | Authorize UUPS upgrades |
STAKING_CORE_ROLE |
CountersigStaking |
Suspend / slash agents, zero reputation |
ORACLE_ROLE |
Oracle consensus contract | Write reputation scores |
SLASHING_COMMITTEE_ROLE |
3-of-5 multisig | Initiate slash proposals |
| Operator | Agent registrant | Register, suspend, reinstate, rotate key |
flowchart TD
Start([Deployment Start]) --> DeployContracts["Deploy all contracts"]
DeployContracts --> AssignRoles["Assign governance roles"]
AssignRoles --> Identity["Grant STAKING_CORE_ROLE to Staking"]
Identity --> Reputation["Grant STAKING_CORE_ROLE to Staking"]
Reputation --> Oracle["Grant ORACLE_ROLE to Oracle"]
Oracle --> Committee["Grant SLASHING_COMMITTEE_ROLE to multisig"]
Committee --> Complete([Deployment Complete])
Diagram sources
- Deploy.s.sol:77-81
Each contract extends AccessControlUpgradeable and implements role-based access control:
- Role Grants: Performed during initialization
- Role Revocation: Controlled by DEFAULT_ADMIN_ROLE holders
- Role Transfers: Restricted to prevent unauthorized access
Section sources
- Deploy.s.sol:77-81
- README.md:348-358
For testnet deployment, use the following command:
# Sepolia testnet deployment
forge script script/Deploy.s.sol \
--rpc-url $SEPOLIA_RPC \
--broadcast \
--verify \
-vvvvFor mainnet deployment, modify the environment variables:
export DEPLOYER_PRIVATE_KEY="your_mainnet_private_key"
export ORACLE_ADDRESS="0xOracleContractAddress"
export COMMITTEE_ADDRESS="0xMainnetCommitteeAddress"
export MINIMUM_STAKE="1000000000000000000000" # 1000 CSIG
export CHALLENGE_PERIOD="604800" # 7 daysThen execute the deployment script with mainnet RPC:
forge script script/Deploy.s.sol \
--rpc-url $MAINNET_RPC \
--broadcast \
--verify \
-vvvv| Aspect | Testnet | Mainnet |
|---|---|---|
| Slashing Committee | 3-of-5 multisig | UMA OptimisticOracleV3/Kleros |
| Oracle Consensus | Test oracle | Production oracle network |
| Token Supply | Mintable test token | Fixed supply token |
| Security Model | Lower security requirements | Enhanced security measures |
Section sources
- README.md:147-187
- README.md:350-357
The deployment script automatically writes contract addresses to deployments/{chainId}.json:
{
"chainId": 11155111,
"csigToken": "0x6d5E311e821c3e279dBe9833F8e33828f7716FA8",
"deployer": "0x713e36Be6F656158420eD940e4747DdB3A77f65c",
"identity": "0xD738A4cBe525d214f86059A8328786f072D6fbe1",
"reputation": "0x0613C561C5003D7948Ea09dE2C1895965A5c3F27",
"staking": "0x60347640d46B55E7dafFA8F385bc55eE2D77ee85"
}To programmatically access deployed addresses:
// Read deployment file
const fs = require('fs');
const deployment = JSON.parse(fs.readFileSync('./deployments/11155111.json', 'utf8'));
console.log('Staking contract:', deployment.staking);Verify addresses match expectations using the deployment log output:
# Check deployment log
forge script script/Deploy.s.sol --rpc-url $RPC_URL --broadcast -vvvvSection sources
- Deploy.s.sol:108-128
- deployments/11155111.json:1-1
To migrate from testnet to mainnet:
flowchart TD
Testnet([Testnet Deployment]) --> Export["Export testnet addresses"]
Export --> Verify["Verify testnet contracts"]
Verify --> Prepare["Prepare mainnet environment"]
Prepare --> DeployMainnet["Deploy mainnet contracts"]
DeployMainnet --> Configure["Configure mainnet roles"]
Configure --> VerifyMainnet["Verify mainnet deployment"]
VerifyMainnet --> MigrateData["Migrate on-chain data"]
MigrateData --> Complete([Migration Complete])
- Contract Addresses: Use exported testnet addresses as reference
- State Migration: Manual transfer of balances and registrations
- Role Configuration: Recreate governance roles on mainnet
- Oracle Integration: Connect to production oracle network
For failed migrations:
- Contract Rollback: Use UUPS upgrade to previous implementation
- State Restoration: Manual restoration of affected states
- Role Recovery: Restore governance roles from backup
- Emergency Procedures: Activate emergency multisig if available
Section sources
- Deploy.s.sol:108-128
Monitor deployment transactions using the broadcast logs:
# View deployment transactions
cat broadcast/Deploy.s.sol/11155111/run-latest.json | jq '.transactions[] | {hash: .hash, contractName: .contractName, contractAddress: .contractAddress}'- Contract Verification: Confirm proxy delegation works correctly
- Role Verification: Verify all roles assigned as expected
- Functionality Testing: Test core contract functions
- Integration Testing: Verify cross-contract interactions
Recommended monitoring approaches:
- Block Explorer: Track transaction confirmations
- RPC Providers: Monitor gas prices and network congestion
- Alerting: Set up alerts for critical failures
- Health Checks: Automated health verification scripts
Section sources
- broadcast/Deploy.s.sol/11155111/run-latest.json:217-727
In case of deployment failure:
flowchart TD
Failure([Deployment Failure]) --> Isolate["Isolate affected contracts"]
Isolate --> Backup["Backup current state"]
Backup --> Rollback["Execute rollback procedure"]
Rollback --> Verify["Verify rollback success"]
Verify --> Report["Report incident"]
Report --> Prevent["Implement preventive measures"]
-
UUPS Upgrade Rollback: Use
upgradeTo()with previous implementation - State Restoration: Manual restoration of affected states
- Role Recovery: Restore governance roles from secure backup
- Emergency Access: Utilize emergency multisig if configured
- Pre-deployment testing: Comprehensive testing on testnet
- Multi-signature approval: Require multiple approvals for critical changes
- Gradual rollout: Deploy in phases with monitoring
- Automated testing: Continuous integration with automated tests
Section sources
- CountersigStaking.sol:329
| Issue | Symptoms | Solution |
|---|---|---|
| Insufficient Funds | Transaction fails with "insufficient balance" | Fund deployer account with adequate ETH |
| RPC Connectivity | "Connection refused" errors | Verify RPC endpoint accessibility |
| Private Key Issues | "Invalid private key" errors | Validate private key format and permissions |
| Gas Limit Issues | Transactions stuck in mempool | Increase gas limit and gas price |
| Role Assignment Failures | Access control errors | Verify role assignments in deployment script |
- Check Environment Variables: Verify all required variables are set
- Review Logs: Examine deployment script output for errors
- Test Transactions: Run individual contract deployments
- Network Validation: Confirm network connectivity and RPC availability
- Transaction Recovery: Use replacement transactions with higher gas fees
- State Recovery: Manual restoration of affected states
- Contract Recovery: Re-deploy failed components
- Escalation: Contact support team for complex issues
Section sources
- Deploy.s.sol:12-30
The Countersig Network deployment process provides a robust foundation for deploying upgradeable smart contracts with proper governance and access control. The UUPS proxy pattern ensures future flexibility while maintaining security through role-based access control.
Key deployment considerations include:
- Security: Proper role assignment and access control
- Upgradeability: UUPS pattern enables future improvements
- Testing: Comprehensive testing on testnet before mainnet deployment
- Monitoring: Continuous monitoring and alerting systems
- Documentation: Clear documentation for all deployment steps
The deployment guide provides a complete framework for successful deployment across testnet and mainnet environments, with clear procedures for verification, monitoring, and rollback in case of issues.
Start Here
Core Concepts
Smart Contracts
Oracle System
Agent SDK
Integration Guides
Economic Model
Deployment & Ops
Advanced Topics