Overview The Treasury  contract manages the economic pools of the Nexis Network. It receives inflows from agent slashing and early withdrawal penalties, distributes them across three pools (treasury, insurance, rewards), and enables authorized distribution of rewards to agents. 
Contract Address (Testnet):  0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0Key Features: 
Three-pool system: Treasury, Insurance, Rewards 
Configurable distribution ratios 
Handles slashed stakes and early exit penalties 
Reward distribution to agents with REWARDS_ROLE authorization 
Pool withdrawal with WITHDRAW_ROLE authorization 
Multi-asset support (ETH and ERC20 tokens) 
Upgradeable UUPS proxy pattern 
 
Contract Constants // Roles bytes32  public  constant  REWARDS_ROLE  =  keccak256 ( "REWARDS_ROLE" ); bytes32  public  constant  WITHDRAW_ROLE  =  keccak256 ( "WITHDRAW_ROLE" ); bytes32  public  constant  INFLOW_ROLE  =  keccak256 ( "INFLOW_ROLE" ); // Constants uint16  internal  constant  BPS_DENOMINATOR  =  10_000 ;  // 100% = 10,000 basis points address  internal  constant  ETH_ASSET  =  address ( 0 ); Data Structures DistributionConfig struct  DistributionConfig  {     uint16  treasuryBps;    // Treasury share in basis points (0-10000)     uint16  insuranceBps;   // Insurance share in basis points     uint16  rewardsBps;     // Rewards share in basis points } //  Note : treasuryBps + insuranceBps + rewardsBps must equal 10,000 Default Distribution: 
Treasury: 40% (4,000 bps) 
Insurance: 30% (3,000 bps) 
Rewards: 30% (3,000 bps) 
 
PoolBalances struct  PoolBalances  {     uint256  treasury;    // Treasury pool balance     uint256  insurance;   // Insurance pool balance     uint256  rewards;     // Rewards pool balance } Pool Management poolBalances Query pool balances for a specific asset. 
Asset address (address(0) for ETH, token address for ERC20) 
Returns: 
PoolBalances - Struct containing balances for all three pools 
Example: import  {  ethers  }  from  'ethers' ; // Query ETH pool balances const  ethBalances  =  await  treasury . poolBalances ( ethers . ZeroAddress ); console . log ( "ETH Pool Balances:" ); console . log ( "  Treasury:" ,  ethers . formatEther ( ethBalances . treasury ),  "ETH" ); console . log ( "  Insurance:" ,  ethers . formatEther ( ethBalances . insurance ),  "ETH" ); console . log ( "  Rewards:" ,  ethers . formatEther ( ethBalances . rewards ),  "ETH" ); // Query ERC20 token pool balances const  usdcAddress  =  "0x..." ; const  usdcBalances  =  await  treasury . poolBalances ( usdcAddress ); console . log ( " \n USDC Pool Balances:" ); console . log ( "  Treasury:" ,  ethers . formatUnits ( usdcBalances . treasury ,  6 ),  "USDC" ); console . log ( "  Insurance:" ,  ethers . formatUnits ( usdcBalances . insurance ,  6 ),  "USDC" ); console . log ( "  Rewards:" ,  ethers . formatUnits ( usdcBalances . rewards ,  6 ),  "USDC" ); 
rewardsBalance Query available rewards balance for a specific asset. 
Returns: 
uint256 - Available rewards balance 
Example: const  rewardsETH  =  await  treasury . rewardsBalance ( ethers . ZeroAddress ); console . log ( "Available rewards:" ,  ethers . formatEther ( rewardsETH ),  "ETH" ); function  rewardsBalance ( address  asset )  external  view  returns  ( uint256 ); Inflow Handling These methods are called automatically by the Agents contract when stakes are slashed or early exit penalties are collected. 
handleSlash Process slashed stake from an agent. Only callable by addresses with INFLOW_ROLE (typically the Agents contract). 
Agent ID that was slashed 
For ETH, must equal amount; for ERC20, must be 0 
Distribution: 
Splits amount according to configured distribution ratios across three pools.Events Emitted: event  SlashHandled (     uint256  indexed  agentId ,     address  indexed  asset ,     uint256  amount ,     uint256  treasuryShare ,     uint256  insuranceShare ,     uint256  rewardsShare ); Example: // This is typically called by Agents contract, not directly // But can be called by any address with INFLOW_ROLE // For ETH await  treasury . handleSlash (   agentId ,   ethers . ZeroAddress ,   ethers . parseEther ( "1.0" ),   {  value:  ethers . parseEther ( "1.0" ) } ); // For ERC20 (token must be transferred first) const  token  =  new  ethers . Contract ( tokenAddress ,  erc20ABI ,  signer ); await  token . transfer ( treasuryAddress ,  amount ); await  treasury . handleSlash ( agentId ,  tokenAddress ,  amount ); function  handleSlash (     uint256  agentId ,     address  asset ,     uint256  amount )  external  payable  onlyRole ( INFLOW_ROLE ); handleEarlyExitPenalty Process early withdrawal penalty from an agent. Only callable by INFLOW_ROLE. 
Agent ID that paid penalty 
Events Emitted: event  EarlyExitHandled (     uint256  indexed  agentId ,     address  indexed  asset ,     uint256  amount ,     uint256  treasuryShare ,     uint256  insuranceShare ,     uint256  rewardsShare ); Example: // Called by Agents contract when agent forces early withdrawal await  treasury . handleEarlyExitPenalty (   agentId ,   ethers . ZeroAddress ,   penaltyAmount ,   {  value:  penaltyAmount  } ); function  handleEarlyExitPenalty (     uint256  agentId ,     address  asset ,     uint256  amount )  external  payable  onlyRole ( INFLOW_ROLE ); recordRewardDeposit Record a direct deposit to the rewards pool (e.g., from Tasks contract or external contributions). 
For ETH, must equal amount; for ERC20, tokens must be transferred before calling 
Events Emitted: event  RewardsDeposited (     address  indexed  source ,     address  indexed  asset ,     uint256  amount ); Example: JavaScript (ETH)
JavaScript (ERC20)
Python (ETH)
Solidity
// Anyone can deposit rewards const  depositAmount  =  ethers . parseEther ( "10.0" ); const  tx  =  await  treasury . recordRewardDeposit (   ethers . ZeroAddress ,   depositAmount ,   {  value:  depositAmount  } ); await  tx . wait (); console . log ( "Deposited 10 ETH to rewards pool" ); 
Reward Distribution distributeReward Distribute rewards from rewards pool to an agent. Only callable by REWARDS_ROLE. 
Amount to distribute (must be ≤ rewards balance) 
Address to send rewards (address(0) = agent owner) 
Human-readable reason for distribution 
Requirements: 
Agent must be registered 
Sufficient balance in rewards pool 
Caller must have REWARDS_ROLE 
 
Events Emitted: event  RewardPaid (     uint256  indexed  agentId ,     address  indexed  asset ,     address  indexed  recipient ,     uint256  amount ,     string  reason ); Errors: 
AgentNotKnown(uint256) - Agent not registeredInsufficientRewards(address asset, uint256 requested, uint256 available) - Not enough rewards 
Example: // Distribute rewards to agent owner await  treasury . distributeReward (   agentId ,   ethers . ZeroAddress ,  // ETH   ethers . parseEther ( "0.5" ),   ethers . ZeroAddress ,  // Send to agent owner   "Monthly performance bonus for high-quality inferences" ); // Distribute to specific address await  treasury . distributeReward (   agentId ,   tokenAddress ,   ethers . parseUnits ( "100" ,  6 ),  // 100 USDC   "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" ,   "Reward for completing 1000 verified tasks" ); 
Pool Withdrawals withdrawTreasury Withdraw from treasury pool. Only callable by WITHDRAW_ROLE. 
Amount to withdraw (must be ≤ treasury balance) 
Recipient address (cannot be zero address) 
Events Emitted: event  PoolWithdrawn (     bytes32  indexed  pool ,     address  indexed  asset ,     address  indexed  to ,     uint256  amount ); Example: // Withdraw ETH from treasury pool await  treasury . withdrawTreasury (   ethers . ZeroAddress ,   ethers . parseEther ( "100.0" ),   treasuryMultisigAddress ); // Withdraw USDC from treasury pool await  treasury . withdrawTreasury (   usdcAddress ,   ethers . parseUnits ( "50000" ,  6 ),   treasuryMultisigAddress ); function  withdrawTreasury (     address  asset ,     uint256  amount ,     address  to )  external  nonReentrant  onlyRole ( WITHDRAW_ROLE ); withdrawInsurance Withdraw from insurance pool. Only callable by WITHDRAW_ROLE. 
Amount to withdraw (must be ≤ insurance balance) 
Events Emitted: event  PoolWithdrawn (     bytes32  indexed  pool ,     address  indexed  asset ,     address  indexed  to ,     uint256  amount ); Example: // Withdraw from insurance pool for coverage payout await  treasury . withdrawInsurance (   ethers . ZeroAddress ,   ethers . parseEther ( "10.0" ),   insuranceClaimantAddress ); function  withdrawInsurance (     address  asset ,     uint256  amount ,     address  to )  external  nonReentrant  onlyRole ( WITHDRAW_ROLE ); Configuration setDistribution Update pool distribution ratios. Only callable by DEFAULT_ADMIN_ROLE. 
Treasury share in basis points (0-10000) 
Insurance share in basis points (0-10000) 
Rewards share in basis points (0-10000) 
Requirements: 
Sum must equal 10,000 (100%) 
 
Events Emitted: event  DistributionUpdated (     uint16  treasuryBps ,     uint16  insuranceBps ,     uint16  rewardsBps ); Errors: 
InvalidBps() - Sum does not equal 10,000 
Example: // Update distribution to: // - Treasury: 50% // - Insurance: 25% // - Rewards: 25% await  treasury . setDistribution (   5000 ,   // 50%   2500 ,   // 25%   2500    // 25% ); console . log ( "Distribution updated" ); 
setAgents Update Agents contract address. Only callable by DEFAULT_ADMIN_ROLE. 
New Agents contract address (cannot be zero) 
Example: await  treasury . setAgents ( newAgentsAddress ); function  setAgents ( address  newAgents )     external     onlyRole ( DEFAULT_ADMIN_ROLE ); Query Methods distribution DistributionConfig  public  distribution; Get current distribution configuration. 
Example: const  dist  =  await  treasury . distribution (); console . log ( "Distribution:" ); console . log ( "  Treasury:" ,  dist . treasuryBps  /  100 ,  "%" ); console . log ( "  Insurance:" ,  dist . insuranceBps  /  100 ,  "%" ); console . log ( "  Rewards:" ,  dist . rewardsBps  /  100 ,  "%" ); agents IAgentsRegistry  public  agents; Get Agents contract address. 
Complete Example: Reward Distribution Campaign Here’s a complete example of distributing rewards to top-performing agents: 
import  {  ethers  }  from  'ethers' ; // Setup const  provider  =  new  ethers . JsonRpcProvider ( 'https://testnet-rpc.nex-t1.ai' ); const  rewardsManager  =  new  ethers . Wallet ( privateKey ,  provider ); const  treasuryAddress  =  '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0' ; const  agentsAddress  =  '0x5FbDB2315678afecb367f032d93F642f64180aa3' ; const  treasury  =  new  ethers . Contract ( treasuryAddress ,  treasuryABI ,  rewardsManager ); const  agents  =  new  ethers . Contract ( agentsAddress ,  agentsABI ,  rewardsManager ); // ======================================== // Step 1: Check available rewards // ======================================== console . log ( "Step 1: Checking available rewards..." ); const  availableRewards  =  await  treasury . rewardsBalance ( ethers . ZeroAddress ); console . log ( "Available ETH rewards:" ,  ethers . formatEther ( availableRewards )); if  ( availableRewards  <  ethers . parseEther ( "10.0" )) {   console . log ( "Insufficient rewards, depositing more..." );   await  treasury . recordRewardDeposit (     ethers . ZeroAddress ,     ethers . parseEther ( "50.0" ),     {  value:  ethers . parseEther ( "50.0" ) }   ); } // ======================================== // Step 2: Get top agents by reputation // ======================================== console . log ( " \n Step 2: Identifying top agents..." ); const  agentCount  =  100 ; const  agentList  =  await  agents . listAgents ( 0 ,  agentCount ); // Sort by reputation const  topAgents  =  agentList   . sort (( a ,  b )  =>  Number ( b . weightedReputation )  -  Number ( a . weightedReputation ))   . slice ( 0 ,  10 ); console . log ( "Top 10 agents by reputation:" ); topAgents . forEach (( agent ,  i )  =>  {   console . log ( `   ${ i  +  1 } . Agent  ${ agent . agentId }  - Reputation:  ${ agent . weightedReputation } ` ); }); // ======================================== // Step 3: Calculate reward distribution // ======================================== console . log ( " \n Step 3: Calculating rewards..." ); const  totalRewardPool  =  ethers . parseEther ( "10.0" );  // 10 ETH total const  reputationSum  =  topAgents . reduce (( sum ,  agent )  =>   sum  +  Number ( agent . weightedReputation ),  0 ); const  distributions  =  topAgents . map ( agent  =>  ({   agentId:  agent . agentId ,   owner:  agent . owner ,   reputation:  agent . weightedReputation ,   reward:  ( totalRewardPool  *  BigInt ( agent . weightedReputation ))  /  BigInt ( reputationSum ) })); // ======================================== // Step 4: Distribute rewards // ======================================== console . log ( " \n Step 4: Distributing rewards..." ); for  ( const  dist  of  distributions ) {   console . log ( ` \n Distributing to agent  ${ dist . agentId } ...` );   console . log ( `  Owner:  ${ dist . owner } ` );   console . log ( `  Reputation:  ${ dist . reputation } ` );   console . log ( `  Reward:  ${ ethers . formatEther ( dist . reward ) }  ETH` );   const  tx  =  await  treasury . distributeReward (     dist . agentId ,     ethers . ZeroAddress ,     dist . reward ,     ethers . ZeroAddress ,  // Send to agent owner     `Q1 2024 Performance Reward - Top 10 by reputation`   );   await  tx . wait ();   console . log ( `  ✓ Distributed!` ); } // ======================================== // Step 5: Verify final balances // ======================================== console . log ( " \n\n Step 5: Verifying final state..." ); const  finalRewards  =  await  treasury . rewardsBalance ( ethers . ZeroAddress ); console . log ( "Remaining rewards:" ,  ethers . formatEther ( finalRewards ),  "ETH" ); const  pools  =  await  treasury . poolBalances ( ethers . ZeroAddress ); console . log ( " \n Pool balances:" ); console . log ( "  Treasury:" ,  ethers . formatEther ( pools . treasury ),  "ETH" ); console . log ( "  Insurance:" ,  ethers . formatEther ( pools . insurance ),  "ETH" ); console . log ( "  Rewards:" ,  ethers . formatEther ( pools . rewards ),  "ETH" ); console . log ( " \n ✅ Reward distribution complete!" ); 
Events Reference event  DistributionUpdated (     uint16  treasuryBps ,     uint16  insuranceBps ,     uint16  rewardsBps ); event  SlashHandled (     uint256  indexed  agentId ,     address  indexed  asset ,     uint256  amount ,     uint256  treasuryShare ,     uint256  insuranceShare ,     uint256  rewardsShare ); event  EarlyExitHandled (     uint256  indexed  agentId ,     address  indexed  asset ,     uint256  amount ,     uint256  treasuryShare ,     uint256  insuranceShare ,     uint256  rewardsShare ); event  RewardsDeposited (     address  indexed  source ,     address  indexed  asset ,     uint256  amount ); event  RewardPaid (     uint256  indexed  agentId ,     address  indexed  asset ,     address  indexed  recipient ,     uint256  amount ,     string  reason ); event  PoolWithdrawn (     bytes32  indexed  pool ,     address  indexed  asset ,     address  indexed  to ,     uint256  amount ); Error Reference error  InvalidBps (); error  InvalidAddress (); error  InsufficientRewards ( address  asset,  uint256  requested,  uint256  available); error  AgentNotKnown ( uint256  agentId); Treasury Economics Pool Purpose 
Treasury Pool Protocol development, operations, grants, and strategic initiatives 
Insurance Pool Coverage for black swan events, protocol bugs, or agent failures 
Rewards Pool Performance incentives, bounties, and community rewards 
Inflow Sources Source Default Distribution Notes Slashed Stakes 40% / 30% / 30% From agent misbehavior Early Exit Penalties 40% / 30% / 30% From early withdrawals Direct Deposits 0% / 0% / 100% Goes entirely to rewards Task Refunds 0% / 0% / 100% Disputed tasks 
Best Practices 
Adjust based on protocol needs and growth stage 
Early stage: Higher rewards % for agent adoption 
Mature stage: Higher treasury % for sustainability 
Always maintain adequate insurance reserves 
 
Document clear criteria for rewards 
Use transparent, objective metrics (reputation, tasks completed) 
Consider time-based campaigns (monthly, quarterly) 
Batch distributions to save gas costs 
 
Monitor pool balances regularly 
Set thresholds for pool withdrawals 
Use multi-sig for WITHDRAW_ROLE 
Document all withdrawal purposes 
 Integration with Other Contracts The Treasury contract is called by: 
Agents Contract :
handleSlash() - When stakes are slashedhandleEarlyExitPenalty() - When early withdrawals occur 
 
Tasks Contract :
recordRewardDeposit() - When disputed tasks are resolved without refund 
 
External Contributors :
recordRewardDeposit() - For direct reward contributions