Overview The Agents  contract is the core registry and economic coordination layer for AI agents on Nexis Network. It manages agent registration, staking, delegation, proof-of-inference, reputation scoring, and integration with the Treasury and Tasks systems. 
Contract Address (Testnet):  0x5FbDB2315678afecb367f032d93F642f64180aa3Key Features: 
Agent registration and metadata management 
Multi-asset staking (ETH and ERC20 tokens) 
Stake locking and unbonding with configurable periods 
Proof-of-inference recording and verification 
Multi-dimensional reputation system 
Delegation of permissions to operators 
Treasury integration for slashing and penalties 
Upgradeable UUPS proxy pattern 
 
Contract Constants // Roles bytes32  public  constant  SLASHER_ROLE  =  keccak256 ( "SLASHER_ROLE" ); bytes32  public  constant  REPUTATION_ROLE  =  keccak256 ( "REPUTATION_ROLE" ); bytes32  public  constant  ORACLE_ROLE  =  keccak256 ( "ORACLE_ROLE" ); bytes32  public  constant  CONTRIBUTION_ROLE  =  keccak256 ( "CONTRIBUTION_ROLE" ); bytes32  public  constant  VERIFIER_ROLE  =  keccak256 ( "VERIFIER_ROLE" ); bytes32  public  constant  TASK_MODULE_ROLE  =  keccak256 ( "TASK_MODULE_ROLE" ); // Permissions bytes32  public  constant  PERMISSION_METADATA  =  keccak256 ( "PERMISSION_METADATA" ); bytes32  public  constant  PERMISSION_INFERENCE  =  keccak256 ( "PERMISSION_INFERENCE" ); bytes32  public  constant  PERMISSION_WITHDRAW  =  keccak256 ( "PERMISSION_WITHDRAW" ); // Assets address  internal  constant  ETH_ASSET  =  address ( 0 ); Data Structures StakeView struct  StakeView  {     uint256  total;       // Total staked amount     uint256  locked;      // Amount locked in tasks     uint256  available;   // Available for withdrawal } PendingWithdrawal struct  PendingWithdrawal  {     uint256  amount;         // Amount to withdraw     uint64  releaseTime;     // Unix timestamp when withdrawal can be claimed } InferenceCommitment struct  InferenceCommitment  {     uint256  agentId;        // Agent that performed inference     bytes32  inputHash;      // Hash of input data     bytes32  outputHash;     // Hash of output data     bytes32  modelHash;      // Hash of model identifier     uint256  taskId;         // Associated task ID (0 if none)     address  reporter;       // Address that recorded inference     string  proofURI;        // URI to proof data     uint64  timestamp;       // When inference was recorded } VerifierAttestation struct  VerifierAttestation  {     address  verifier;       // Verifier address     bool  success;           // Verification result     string  uri;             // URI to verification report     uint64  timestamp;       // When attestation was made } AgentSummary struct  AgentSummary  {     uint256  agentId;     address  owner;     string  metadata;     string  serviceURI;     uint256  totalStake;            // Sum across all assets     uint256  lockedStake;           // Sum of locked stakes     int256  weightedReputation;     // Aggregated reputation score } ReputationDelta struct  ReputationDelta  {     bytes32  dimension;      // e.g., keccak256("reliability")     int256  delta;           // Change to apply     string  reason;          // Human-readable reason } register Register a new AI agent with metadata and service endpoint. 
Unique identifier for the agent. Must not be already registered. 
JSON metadata string containing agent information (name, model, capabilities, etc.) 
Events Emitted: event  AgentRegistered (     address  indexed  owner ,     uint256  indexed  agentId ,     string  metadata ,     string  serviceURI ); Errors: 
AgentAlreadyRegistered(uint256 agentId, address currentOwner) - Agent ID already taken 
Example: const  metadata  =  JSON . stringify ({   name:  "GPT-4 Research Agent" ,   model:  "gpt-4-turbo" ,   version:  "1.0.0" ,   capabilities:  [ "text-generation" ,  "research" ,  "analysis" ],   maxTokens:  8192 }); const  tx  =  await  agents . register (   12345 ,   metadata ,   "https://api.myagent.com/inference" ); await  tx . wait (); console . log ( "Agent registered!" ); 
Update agent metadata. Requires owner or PERMISSION_METADATA delegate. 
Events Emitted: event  AgentMetadataUpdated ( uint256  indexed  agentId ,  string  metadata ); Errors: 
AgentNotRegistered(uint256) - Agent doesn’t existUnauthorizedDelegate(address) - Caller not authorized 
Example: const  newMetadata  =  JSON . stringify ({   name:  "GPT-4 Research Agent v2" ,   model:  "gpt-4-turbo" ,   version:  "2.0.0" ,   capabilities:  [ "text-generation" ,  "research" ,  "analysis" ,  "coding" ],   maxTokens:  16384 }); const  tx  =  await  agents . updateMetadata ( 12345 ,  newMetadata ); await  tx . wait (); 
updateServiceURI Update agent service endpoint URI. 
Events Emitted: event  AgentServiceURIUpdated ( uint256  indexed  agentId ,  string  serviceURI ); Example: await  agents . updateServiceURI ( 12345 ,  "https://api-v2.myagent.com/inference" ); transferAgentOwnership Transfer ownership of an agent to a new address. Only current owner can call. 
Address of new owner (cannot be zero address) 
Events Emitted: event  AgentOwnershipTransferred (     uint256  indexed  agentId ,     address  indexed  previousOwner ,     address  indexed  newOwner ); Example: const  newOwner  =  "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" ; await  agents . transferAgentOwnership ( 12345 ,  newOwner ); Query Methods (Registration) agentOwner function  agentOwner ( uint256  agentId )  external  view  returns  ( address ); Returns the owner address of an agent. 
function  agentMetadata ( uint256  agentId )  external  view  returns  ( string  memory ); Returns the metadata JSON string for an agent. 
agentServiceURI function  agentServiceURI ( uint256  agentId )  external  view  returns  ( string  memory ); Returns the service URI endpoint for an agent. 
isAgentRegistered function  isAgentRegistered ( uint256  agentId )  public  view  returns  ( bool ); Check if an agent ID is registered. 
Example: const  owner  =  await  agents . agentOwner ( 12345 ); const  metadata  =  await  agents . agentMetadata ( 12345 ); const  serviceURI  =  await  agents . agentServiceURI ( 12345 ); const  isRegistered  =  await  agents . isAgentRegistered ( 12345 ); console . log ( "Owner:" ,  owner ); console . log ( "Metadata:" ,  JSON . parse ( metadata )); console . log ( "Service URI:" ,  serviceURI ); console . log ( "Registered:" ,  isRegistered ); Staking stakeETH Stake native ETH tokens for an agent. 
Amount of ETH to stake (sent as transaction value) 
Events Emitted: event  StakeIncreased (     uint256  indexed  agentId ,     address  indexed  asset ,     address  indexed  staker ,     uint256  amount ,     uint256  totalStaked ); Errors: 
AgentNotRegistered(uint256) - Agent doesn’t existZeroAmount() - msg.value is 0 
Example: // Stake 1 ETH const  tx  =  await  agents . stakeETH ( 12345 , {   value:  ethers . parseEther ( "1.0" ) }); await  tx . wait (); console . log ( "Staked 1 ETH for agent 12345" ); 
stakeERC20 Stake ERC20 tokens for an agent. 
ERC20 token contract address 
Amount of tokens to stake (must have approved contract first) 
Prerequisites: 
Caller must have approved the Agents contract to spend amount of token 
 
Events Emitted: event  StakeIncreased (     uint256  indexed  agentId ,     address  indexed  asset ,     address  indexed  staker ,     uint256  amount ,     uint256  totalStaked ); Example: const  tokenAddress  =  "0x..." ;  // USDC, USDT, etc. const  amount  =  ethers . parseUnits ( "1000" ,  6 );  // 1000 USDC (6 decimals) // First approve const  token  =  new  ethers . Contract ( tokenAddress ,  erc20ABI ,  wallet ); const  approveTx  =  await  token . approve ( agentsAddress ,  amount ); await  approveTx . wait (); // Then stake const  stakeTx  =  await  agents . stakeERC20 ( 12345 ,  tokenAddress ,  amount ); await  stakeTx . wait (); console . log ( "Staked 1000 USDC for agent 12345" ); 
requestWithdrawal Initiate unbonding period for staked assets. Requires owner or PERMISSION_WITHDRAW delegate. 
Agent ID to withdraw from 
Asset address (address(0) for ETH, token address for ERC20) 
Amount to withdraw (must be ≤ available stake) 
Events Emitted: event  UnbondingInitiated (     uint256  indexed  agentId ,     address  indexed  asset ,     uint256  amount ,     uint64  releaseTime ); Errors: 
ZeroAmount() - Amount is 0AmountTooLarge(uint256 requested, uint256 available) - Insufficient available stakeUnauthorizedDelegate(address) - Caller not authorized 
Notes: 
Withdrawal enters unbonding queue with configured unbonding period (default 7 days for ETH) 
Amount is removed from staked balance immediately 
Cannot withdraw locked stake (stake locked by Tasks contract) 
 
Example: // Request withdrawal of 0.5 ETH const  amount  =  ethers . parseEther ( "0.5" ); const  tx  =  await  agents . requestWithdrawal (   12345 ,   ethers . ZeroAddress ,  // ETH   amount ); const  receipt  =  await  tx . wait (); // Extract release time from event const  event  =  receipt . logs . find ( log  =>   log . topics [ 0 ]  ===  ethers . id ( 'UnbondingInitiated(uint256,address,uint256,uint64)' ) ); // releaseTime is in the event data console . log ( "Withdrawal requested, unbonding period started" ); cancelWithdrawal Cancel a pending withdrawal and return amount to staked balance. 
Index in the withdrawal queue (relative to current head) 
Events Emitted: event  WithdrawalCancelled ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ); Example: // Cancel the first pending withdrawal await  agents . cancelWithdrawal ( 12345 ,  ethers . ZeroAddress ,  0 ); claimWithdrawals Claim completed withdrawals after unbonding period. 
Maximum number of withdrawal entries to process (0 = unlimited) 
Address to receive funds (address(0) = agent owner) 
If true, claim before unbonding period ends (incurs penalty) 
Returns: 
releasedAmount (uint256) - Amount released to receiverpenaltyAmount (uint256) - Amount taken as early exit penalty 
Events Emitted: event  WithdrawalExecuted ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  address  indexed  receiver ); // OR event  EarlyWithdrawal ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  uint256  penalty ,  address  receiver ); Example: JavaScript
JavaScript (Early Withdrawal)
// Claim all ready withdrawals const  [ released ,  penalty ]  =  await  agents . claimWithdrawals (   12345 ,   ethers . ZeroAddress ,  // ETH   0 ,                   // Process all entries   ethers . ZeroAddress ,  // Send to agent owner   false                // Wait for unbonding period ); console . log ( "Released:" ,  ethers . formatEther ( released ),  "ETH" ); console . log ( "Penalty:" ,  ethers . formatEther ( penalty ),  "ETH" ); 
Staking Query Methods stakedBalance function  stakedBalance ( uint256  agentId ,  address  asset )  external  view  returns  ( uint256 ); Get total staked balance for an agent and asset. 
lockedBalance function  lockedBalance ( uint256  agentId ,  address  asset )  external  view  returns  ( uint256 ); Get locked stake balance (locked by Tasks contract). 
stakeBalances function  stakeBalances ( uint256  agentId ,  address  asset )     public     view     returns  ( StakeView  memory ); Get comprehensive stake information (total, locked, available). 
pendingWithdrawalCount function  pendingWithdrawalCount ( uint256  agentId ,  address  asset )     external     view     returns  ( uint256 ); Get number of pending withdrawals in queue. 
pendingWithdrawalAt function  pendingWithdrawalAt ( uint256  agentId ,  address  asset ,  uint256  index )     external     view     returns  ( PendingWithdrawal  memory ); Get details of a specific pending withdrawal. 
Example: // Query stake information const  stakeInfo  =  await  agents . stakeBalances ( 12345 ,  ethers . ZeroAddress ); console . log ( "Total:" ,  ethers . formatEther ( stakeInfo . total )); console . log ( "Locked:" ,  ethers . formatEther ( stakeInfo . locked )); console . log ( "Available:" ,  ethers . formatEther ( stakeInfo . available )); // Query pending withdrawals const  count  =  await  agents . pendingWithdrawalCount ( 12345 ,  ethers . ZeroAddress ); console . log ( "Pending withdrawals:" ,  count ); for  ( let  i  =  0 ;  i  <  count ;  i ++ ) {   const  withdrawal  =  await  agents . pendingWithdrawalAt ( 12345 ,  ethers . ZeroAddress ,  i );   console . log ( `Withdrawal  ${ i } :` , {     amount:  ethers . formatEther ( withdrawal . amount ),     releaseTime:  new  Date ( Number ( withdrawal . releaseTime )  *  1000 )   }); } Proof of Inference recordInference Record an inference commitment on-chain. Requires owner or PERMISSION_INFERENCE delegate. 
Agent ID that performed inference 
Hash of input data (e.g., keccak256 of prompt) 
Hash of output data (e.g., keccak256 of completion) 
Associated task ID (0 if not task-related) 
URI to detailed proof data (IPFS, Arweave, etc.) 
Returns: 
inferenceId (bytes32) - Unique identifier for this inference 
Events Emitted: event  InferenceRecorded (     uint256  indexed  agentId ,     bytes32  indexed  inferenceId ,     bytes32  indexed  inputHash ,     bytes32  outputHash ,     bytes32  modelHash ,     uint256  taskId ,     address  reporter ,     string  proofURI ); Example: // Record inference const  inputHash  =  ethers . keccak256 ( ethers . toUtf8Bytes ( "What is 2+2?" )); const  outputHash  =  ethers . keccak256 ( ethers . toUtf8Bytes ( "4" )); const  modelHash  =  ethers . keccak256 ( ethers . toUtf8Bytes ( "gpt-4-turbo" )); const  tx  =  await  agents . recordInference (   12345 ,   inputHash ,   outputHash ,   modelHash ,   0 ,  // No task   "ipfs://Qm..."  // Proof data ); const  receipt  =  await  tx . wait (); // Extract inference ID from event const  event  =  receipt . logs . find ( log  =>   log . topics [ 0 ]  ===  ethers . id ( 'InferenceRecorded(uint256,bytes32,bytes32,bytes32,bytes32,uint256,address,string)' ) ); const  inferenceId  =  event . topics [ 2 ]; console . log ( "Inference recorded:" ,  inferenceId ); attestInference Verify and attest to an inference (VERIFIER_ROLE only). Can apply reputation deltas. 
URI to verification report 
deltas
ReputationDelta[] 
required
Reputation adjustments to apply 
Events Emitted: event  InferenceAttested (     bytes32  indexed  inferenceId ,     uint256  indexed  agentId ,     uint256  indexed  taskId ,     address  verifier ,     bool  success ,     string  uri ); Example: // Attest inference with reputation update const  deltas  =  [   {     dimension:  ethers . keccak256 ( ethers . toUtf8Bytes ( "accuracy" )),     delta:  10 ,  // +10 points     reason:  "Correct output verified"   },   {     dimension:  ethers . keccak256 ( ethers . toUtf8Bytes ( "reliability" )),     delta:  5 ,     reason:  "Timely response"   } ]; await  agents . attestInference (   inferenceId ,   true ,  // Success   "ipfs://Qm..." ,  // Verification report   deltas ); getInference function  getInference ( bytes32  inferenceId )     external     view     returns  (         InferenceCommitment  memory  commitment ,         VerifierAttestation  memory  attestation     ); Query inference commitment and attestation details. 
listInferenceIds function  listInferenceIds ( uint256  agentId )  external  view  returns  ( bytes32 []  memory ); Get all inference IDs for an agent. 
Reputation Management adjustReputation Adjust reputation score for an agent (REPUTATION_ROLE only). 
Reputation dimension (reliability, accuracy, performance, trustworthiness) 
Change to apply (positive or negative) 
Events Emitted: event  ReputationAdjusted (     uint256  indexed  agentId ,     bytes32  indexed  dimension ,     int256  newScore ,     string  reason ); Example: const  DIM_RELIABILITY  =  ethers . keccak256 ( ethers . toUtf8Bytes ( "reliability" )); await  agents . adjustReputation (   12345 ,   DIM_RELIABILITY ,   - 20 ,  // Penalize by 20 points   "Failed to respond to 3 consecutive tasks" ); getReputation function  getReputation ( uint256  agentId ,  bytes32  dimension )     external     view     returns  ( int256 ); Get reputation score for a specific dimension. 
aggregatedReputation function  aggregatedReputation ( uint256  agentId )  public  view  returns  ( int256  weighted ); Get weighted aggregate reputation score across all dimensions. 
reputationDimensions function  reputationDimensions ()  external  view  returns  ( bytes32 []  memory ); Get list of configured reputation dimensions. 
Example: // Query reputation const  reliability  =  await  agents . getReputation ( 12345 ,  DIM_RELIABILITY ); const  overall  =  await  agents . aggregatedReputation ( 12345 ); const  dimensions  =  await  agents . reputationDimensions (); console . log ( "Reliability score:" ,  reliability ); console . log ( "Overall score:" ,  overall ); console . log ( "Dimensions:" ,  dimensions . map ( d  =>  ethers . toUtf8String ( d ))); Delegation setDelegate Delegate specific permissions to an operator. 
Agent ID (caller must be owner) 
Permission to grant (PERMISSION_METADATA, PERMISSION_INFERENCE, PERMISSION_WITHDRAW) 
True to grant, false to revoke 
Events Emitted: event  DelegateUpdated (     uint256  indexed  agentId ,     address  indexed  delegate ,     bytes32  indexed  permission ,     bool  enabled ); Example: const  PERMISSION_INFERENCE  =  ethers . keccak256 ( ethers . toUtf8Bytes ( "PERMISSION_INFERENCE" )); const  operatorAddress  =  "0x..." ; // Grant inference permission to operator await  agents . setDelegate ( 12345 ,  operatorAddress ,  PERMISSION_INFERENCE ,  true ); // Later, revoke permission await  agents . setDelegate ( 12345 ,  operatorAddress ,  PERMISSION_INFERENCE ,  false ); hasDelegatedPermission function  hasDelegatedPermission (     uint256  agentId ,     address  operator ,     bytes32  permission )  public  view  returns  ( bool ); Check if an operator has a delegated permission. 
Discovery and Aggregation listAgents Query paginated list of registered agents with summary information. 
Number of agents to return (0 = all remaining) 
Returns: 
AgentSummary[] - Array of agent summaries 
Example: // Get first 10 agents const  agents  =  await  agentsContract . listAgents ( 0 ,  10 ); agents . forEach ( agent  =>  {   console . log ( `Agent  ${ agent . agentId } :` );   console . log ( `  Owner:  ${ agent . owner } ` );   console . log ( `  Total Stake:  ${ ethers . formatEther ( agent . totalStake ) }  ETH` );   console . log ( `  Reputation:  ${ agent . weightedReputation } ` );   console . log ( `  Metadata:` ,  JSON . parse ( agent . metadata )); }); // Get next 10 agents const  moreAgents  =  await  agentsContract . listAgents ( 10 ,  10 ); aggregatedStats function  aggregatedStats ()  external  view  returns  ( AggregatedStats  memory  stats ); Get network-wide statistics (total agents, total staked per asset). 
Example: const  stats  =  await  agents . aggregatedStats (); console . log ( "Total Agents:" ,  stats . totalAgents ); console . log ( " \n Staked Assets:" ); stats . assets . forEach (( asset ,  i )  =>  {   const  name  =  asset  ===  ethers . ZeroAddress  ?  "ETH"  :  asset ;   const  amount  =  ethers . formatEther ( stats . totalStakedPerAsset [ i ]);   console . log ( `   ${ name } :  ${ amount } ` ); }); Admin Functions pause / unpause function  pause ()  external  onlyRole ( DEFAULT_ADMIN_ROLE ); function  unpause ()  external  onlyRole ( DEFAULT_ADMIN_ROLE ); Pause/unpause contract operations (emergency stop). 
setTreasury function  setTreasury ( address  newTreasury )  external  onlyRole ( DEFAULT_ADMIN_ROLE ); Update treasury contract address. 
setTasksContract function  setTasksContract ( address  newTasksContract )  external  onlyRole ( DEFAULT_ADMIN_ROLE ); Update tasks contract address. 
setUnbondingPeriod function  setUnbondingPeriod ( address  asset ,  uint64  period )  external  onlyRole ( DEFAULT_ADMIN_ROLE ); Set unbonding period for an asset (in seconds). 
setEarlyExitPenalty function  setEarlyExitPenalty ( address  asset ,  uint16  bps )  external  onlyRole ( DEFAULT_ADMIN_ROLE ); Set early exit penalty in basis points (10000 = 100%). 
updateReputationWeight function  updateReputationWeight ( bytes32  dimension ,  uint256  weight )     external     onlyRole ( DEFAULT_ADMIN_ROLE ); Update weighting for a reputation dimension. 
Events Reference event  AgentRegistered ( address  indexed  owner ,  uint256  indexed  agentId ,  string  metadata ,  string  serviceURI ); event  AgentMetadataUpdated ( uint256  indexed  agentId ,  string  metadata ); event  AgentServiceURIUpdated ( uint256  indexed  agentId ,  string  serviceURI ); event  AgentOwnershipTransferred ( uint256  indexed  agentId ,  address  indexed  previousOwner ,  address  indexed  newOwner ); event  StakeIncreased ( uint256  indexed  agentId ,  address  indexed  asset ,  address  indexed  staker ,  uint256  amount ,  uint256  totalStaked ); event  StakeLocked ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  uint256  newLockedBalance ); event  StakeUnlocked ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  uint256  newLockedBalance ); event  UnbondingInitiated ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  uint64  releaseTime ); event  WithdrawalCancelled ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ); event  WithdrawalExecuted ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  address  indexed  receiver ); event  EarlyWithdrawal ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ,  uint256  penalty ,  address  receiver ); event  StakeSlashed ( uint256  indexed  agentId ,  address  indexed  asset ,  uint256  amount ); event  InferenceRecorded ( uint256  indexed  agentId ,  bytes32  indexed  inferenceId ,  bytes32  indexed  inputHash ,  bytes32  outputHash ,  bytes32  modelHash ,  uint256  taskId ,  address  reporter ,  string  proofURI ); event  InferenceAttested ( bytes32  indexed  inferenceId ,  uint256  indexed  agentId ,  uint256  indexed  taskId ,  address  verifier ,  bool  success ,  string  uri ); event  ReputationAdjusted ( uint256  indexed  agentId ,  bytes32  indexed  dimension ,  int256  newScore ,  string  reason ); event  DelegateUpdated ( uint256  indexed  agentId ,  address  indexed  delegate ,  bytes32  indexed  permission ,  bool  enabled ); Error Reference error  AgentAlreadyRegistered ( uint256  agentId,  address  currentOwner); error  AgentNotRegistered ( uint256  agentId); error  NotAgentOwner ( uint256  agentId,  address  expectedOwner,  address  actualCaller); error  ZeroAmount (); error  AmountTooLarge ( uint256  requested,  uint256  available); error  NothingToWithdraw ( uint256  agentId,  address  asset); error  UnauthorizedDelegate ( address  delegate); error  InvalidPermission ( bytes32  permission); error  UnknownInference ( bytes32  inferenceId); error  TreasuryRequired ();