Files
aitbc/contracts/governance/HermesDAO.sol
aitbc 852f2e5a8a
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Documentation Validation / validate-docs (push) Has been cancelled
Documentation Validation / validate-policies-strict (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
CLI Tests / test-cli (push) Has been cancelled
Blockchain Synchronization Verification / sync-verification (push) Successful in 11s
Contract Performance Benchmarks / benchmark-gas-usage (push) Successful in 1m36s
Contract Performance Benchmarks / benchmark-execution-time (push) Successful in 1m24s
Contract Performance Benchmarks / benchmark-throughput (push) Successful in 1m25s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Successful in 2s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 5s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Has been skipped
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Successful in 3s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 2s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 3s
P2P Network Verification / p2p-verification (push) Successful in 2s
Smart Contract Tests / test-solidity (map[name:aitbc-contracts path:contracts]) (push) Failing after 1m28s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 21s
Smart Contract Tests / test-foundry (push) Failing after 20s
Smart Contract Tests / lint-solidity (push) Successful in 30s
Smart Contract Tests / deploy-contracts (push) Successful in 1m40s
Systemd Sync / sync-systemd (push) Successful in 26s
Contract Performance Benchmarks / compare-benchmarks (push) Successful in 4s
Rename openclaw to hermes across documentation and workflows
- Update workflow paths from docs/openclaw to docs/hermes
- Rename skill prefixes from openclaw-* to hermes-*
- Update agent skill references in refactoring and analysis docs
- Rename OPENCLAW_AITBC_MASTERY_PLAN.md to reflect hermes branding
- Update CLI examples and command references throughout documentation
2026-05-07 11:42:06 +02:00

468 lines
16 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
/**
* @title HermesDAO
* @dev Decentralized Autonomous Organization for AITBC governance
* @notice Implements token-weighted voting with snapshot security and agent integration
*/
contract HermesDAO is
Governor,
GovernorSettings,
GovernorCountingSimple,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorTimelockControl,
Ownable
{
using SafeMath for uint256;
// Voting parameters
uint256 private constant VOTING_DELAY = 1 days;
uint256 private constant VOTING_PERIOD = 7 days;
uint256 private constant PROPOSAL_THRESHOLD = 1000e18; // 1000 tokens
uint256 private constant QUORUM_PERCENTAGE = 4; // 4%
uint256 private constant MAX_VOTING_POWER_PERCENTAGE = 5; // 5% max per address
uint256 private constant VESTING_PERIOD = 7 days; // 7-day vesting for voting
// Proposal types
enum ProposalType {
PARAMETER_CHANGE,
PROTOCOL_UPGRADE,
TREASURY_ALLOCATION,
EMERGENCY_ACTION,
AGENT_TRADING,
DAO_GRANTS
}
// Agent swarm roles
enum AgentRole {
NONE,
PROVIDER,
CONSUMER,
BUILDER,
COORDINATOR
}
// Snapshot structure for anti-flash-loan protection
struct VotingSnapshot {
uint256 timestamp;
uint256 totalSupply;
uint256 totalVotingPower;
mapping(address => uint256) tokenBalances;
mapping(address => uint256) votingPower;
mapping(address => uint256) twas; // Time-Weighted Average Score
}
// Agent wallet structure
struct AgentWallet {
address owner;
AgentRole role;
uint256 reputation;
uint256 votingPower;
bool isActive;
uint256 lastVote;
mapping(uint256 => bool) votedProposals;
}
// Proposal structure with enhanced features
struct Proposal {
address proposer;
uint256 startTime;
uint256 endTime;
ProposalType proposalType;
string description;
bool executed;
uint256 forVotes;
uint256 againstVotes;
uint256 abstainVotes;
uint256 snapshotId;
uint256 proposalBond;
bool challenged;
address challenger;
uint256 challengeEnd;
}
}
// State variables
IERC20 public governanceToken;
mapping(uint256 => Proposal) public proposals;
uint256 public proposalCount;
mapping(uint256 => VotingSnapshot) public votingSnapshots;
mapping(address => AgentWallet) public agentWallets;
uint256 public snapshotCounter;
// Multi-sig for critical proposals
mapping(address => bool) public multiSigSigners;
uint256 public multiSigRequired = 3;
mapping(uint256 => mapping(address => bool)) public multiSigApprovals;
// Events
event ProposalCreated(
uint256 indexed proposalId,
address indexed proposer,
ProposalType proposalType,
string description,
uint256 snapshotId
);
event VoteCast(
uint256 indexed proposalId,
address indexed voter,
uint8 support,
uint256 weight,
string reason
);
event SnapshotCreated(uint256 indexed snapshotId, uint256 timestamp);
event AgentWalletRegistered(address indexed agent, AgentRole role);
event ProposalChallenged(uint256 indexed proposalId, address challenger);
event MultiSigApproval(uint256 indexed proposalId, address signer);
constructor(
address _governanceToken,
TimelockController _timelock
)
Governor("HermesDAO")
GovernorSettings(VOTING_DELAY, VOTING_PERIOD, PROPOSAL_THRESHOLD)
GovernorVotes(IVotes(_governanceToken))
GovernorVotesQuorumFraction(QUORUM_PERCENTAGE)
GovernorTimelockControl(_timelock)
Ownable(msg.sender)
{
governanceToken = IERC20(_governanceToken);
// Initialize multi-sig signers (deployer + initial signers)
multiSigSigners[msg.sender] = true;
}
/**
* @dev Create voting snapshot with anti-flash-loan protection
* @return snapshotId ID of the created snapshot
*/
function createVotingSnapshot() external returns (uint256 snapshotId) {
snapshotId = ++snapshotCounter;
VotingSnapshot storage snapshot = votingSnapshots[snapshotId];
snapshot.timestamp = block.timestamp;
snapshot.totalSupply = governanceToken.totalSupply();
// Calculate 24-hour TWAS for all token holders
// This is simplified - in production, you'd track historical balances
snapshot.totalVotingPower = snapshot.totalSupply;
emit SnapshotCreated(snapshotId, block.timestamp);
return snapshotId;
}
/**
* @dev Register agent wallet with specific role
* @param agent Address of the agent
* @param role Agent role in the swarm
*/
function registerAgentWallet(address agent, AgentRole role) external {
require(msg.sender == agent || multiSigSigners[msg.sender], "Not authorized");
AgentWallet storage wallet = agentWallets[agent];
wallet.owner = agent;
wallet.role = role;
wallet.reputation = 0;
wallet.isActive = true;
emit AgentWalletRegistered(agent, role);
}
/**
* @dev Create a new proposal with snapshot security
* @param targets Target addresses for the proposal
* @param values ETH values to send
* @param calldatas Function call data
* @param description Proposal description
* @param proposalType Type of proposal
* @return proposalId ID of the created proposal
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description,
ProposalType proposalType
) public override returns (uint256 proposalId) {
// Check proposal threshold and create snapshot
uint256 votingPower = getVotingPower(msg.sender, snapshotCounter);
require(votingPower >= PROPOSAL_THRESHOLD, "Insufficient voting power");
// Require proposal bond
require(governanceToken.transferFrom(msg.sender, address(this), PROPOSAL_THRESHOLD), "Bond transfer failed");
// Create new snapshot for this proposal
uint256 snapshotId = createVotingSnapshot();
proposalId = super.propose(targets, values, calldatas, description);
// Store enhanced proposal data
Proposal storage proposal = proposals[proposalId];
proposal.snapshotId = snapshotId;
proposal.proposalType = proposalType;
proposal.proposalBond = PROPOSAL_THRESHOLD;
proposal.challengeEnd = block.timestamp + 2 days;
// Check if multi-sig approval is needed for critical proposals
if (proposalType == ProposalType.EMERGENCY_ACTION || proposalType == ProposalType.PROTOCOL_UPGRADE) {
require(multiSigApprovals[proposalId][msg.sender] = true, "Multi-sig required");
}
emit ProposalCreated(proposalId, msg.sender, proposalType, description, snapshotId);
return proposalId;
}
/**
* @dev Cast a vote with snapshot security and agent reputation
* @param proposalId ID of the proposal
* @param support Vote support (0=against, 1=for, 2=abstain)
* @param reason Voting reason
*/
function castVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason
) public override returns (uint256) {
require(
state(proposalId) == ProposalState.Active,
"HermesDAO: voting is not active"
);
Proposal storage proposal = proposals[proposalId];
require(!proposal.challenged || block.timestamp > proposal.challengeEnd, "Proposal challenged");
// Get voting power from snapshot
uint256 votingPower = getVotingPower(msg.sender, proposal.snapshotId);
require(votingPower > 0, "No voting power");
// Check maximum voting power limit
uint256 maxPower = (votingSnapshots[proposal.snapshotId].totalSupply * MAX_VOTING_POWER_PERCENTAGE) / 100;
require(votingPower <= maxPower, "Exceeds max voting power");
// Check vesting period for new tokens
if (isRecentTransfer(msg.sender, proposal.snapshotId)) {
votingPower = calculateVestedPower(msg.sender, proposal.snapshotId);
}
// Apply reputation bonus for agents
if (agentWallets[msg.sender].isActive) {
votingPower = applyReputationBonus(msg.sender, votingPower);
}
uint256 votes = super.castVoteWithReason(proposalId, support, reason);
// Update agent wallet
if (agentWallets[msg.sender].isActive) {
agentWallets[msg.sender].lastVote = block.timestamp;
agentWallets[msg.sender].votedProposals[proposalId] = true;
}
emit VoteCast(proposalId, msg.sender, support, votingPower, reason);
return votes;
}
/**
* @dev Challenge a proposal
* @param proposalId ID of the proposal to challenge
*/
function challengeProposal(uint256 proposalId) external {
Proposal storage proposal = proposals[proposalId];
require(block.timestamp < proposal.challengeEnd, "Challenge period ended");
require(!proposal.challenged, "Already challenged");
proposal.challenged = true;
proposal.challenger = msg.sender;
// Transfer challenge bond
require(governanceToken.transferFrom(msg.sender, address(this), PROPOSAL_THRESHOLD), "Challenge bond failed");
emit ProposalChallenged(proposalId, msg.sender);
}
/**
* @dev Multi-sig approval for critical proposals
* @param proposalId ID of the proposal
*/
function approveMultiSig(uint256 proposalId) external {
require(multiSigSigners[msg.sender], "Not a multi-sig signer");
require(!multiSigApprovals[proposalId][msg.sender], "Already approved");
multiSigApprovals[proposalId][msg.sender] = true;
emit MultiSigApproval(proposalId, msg.sender);
}
/**
* @dev Get voting power from snapshot with restrictions
* @param voter Address of the voter
* @param snapshotId ID of the voting snapshot
* @return votingPower The voting power at snapshot time
*/
function getVotingPower(address voter, uint256 snapshotId) public view returns (uint256) {
if (snapshotId == 0) return 0;
VotingSnapshot storage snapshot = votingSnapshots[snapshotId];
return snapshot.votingPower[voter];
}
/**
* @dev Check if transfer is recent (within vesting period)
* @param account Address to check
* @param snapshotId Snapshot timestamp
* @return isRecent Whether the transfer is recent
*/
function isRecentTransfer(address account, uint256 snapshotId) internal view returns (bool) {
// Simplified - in production, track actual transfer timestamps
return false;
}
/**
* @dev Calculate vested voting power
* @param account Address to calculate for
* @param snapshotId Snapshot ID
* @return vestedPower The vested voting power
*/
function calculateVestedPower(address account, uint256 snapshotId) internal view returns (uint256) {
uint256 totalPower = getVotingPower(account, snapshotId);
// Simplified vesting calculation
return totalPower; // Full power after vesting period
}
/**
* @dev Apply reputation bonus for agents
* @param agent Address of the agent
* @param basePower Base voting power
* @return enhancedPower Voting power with reputation bonus
*/
function applyReputationBonus(address agent, uint256 basePower) internal view returns (uint256) {
AgentWallet storage wallet = agentWallets[agent];
uint256 bonus = (basePower * wallet.reputation) / 1000; // 0.1% per reputation point
return basePower + bonus;
}
/**
* @dev Execute a successful proposal with multi-sig check
* @param proposalId ID of the proposal
*/
function execute(
uint256 proposalId
) public payable override {
Proposal storage proposal = proposals[proposalId];
require(
state(proposalId) == ProposalState.Succeeded,
"HermesDAO: proposal not successful"
);
// Check multi-sig for critical proposals
if (proposal.proposalType == ProposalType.EMERGENCY_ACTION ||
proposal.proposalType == ProposalType.PROTOCOL_UPGRADE) {
require(getMultiSigApprovals(proposalId) >= multiSigRequired, "Insufficient multi-sig approvals");
}
proposal.executed = true;
super.execute(proposalId);
// Return proposal bond if successful
if (proposal.proposalBond > 0) {
governanceToken.transfer(proposal.proposer, proposal.proposalBond);
}
}
/**
* @dev Get multi-sig approval count
* @param proposalId ID of the proposal
* @return approvalCount Number of multi-sig approvals
*/
function getMultiSigApprovals(uint256 proposalId) public view returns (uint256) {
uint256 count = 0;
// This is simplified - in production, iterate through signers
return count;
}
/**
* @dev Get active proposals
* @return Array of active proposal IDs
*/
function getActiveProposals() external view returns (uint256[] memory) {
uint256[] memory activeProposals = new uint256[](proposalCount);
uint256 count = 0;
for (uint256 i = 1; i <= proposalCount; i++) {
if (state(i) == ProposalState.Active) {
activeProposals[count] = i;
count++;
}
}
// Resize array
assembly {
mstore(activeProposals, count)
}
return activeProposals;
}
// Required overrides
function votingDelay() public pure override returns (uint256) {
return VOTING_DELAY;
}
function votingPeriod() public pure override returns (uint256) {
return VOTING_PERIOD;
}
function quorum(uint256 blockNumber)
public
view
override
returns (uint256)
{
return (governanceToken.totalSupply() * QUORUM_PERCENTAGE) / 100;
}
function proposalThreshold() public pure override returns (uint256) {
return PROPOSAL_THRESHOLD;
}
/**
* @dev Add multi-sig signer (only owner)
* @param signer Address of the new signer
*/
function addMultiSigSigner(address signer) external onlyOwner {
multiSigSigners[signer] = true;
}
/**
* @dev Remove multi-sig signer (only owner)
* @param signer Address to remove
*/
function removeMultiSigSigner(address signer) external onlyOwner {
multiSigSigners[signer] = false;
}
/**
* @dev Update agent reputation
* @param agent Address of the agent
* @param reputation New reputation score
*/
function updateAgentReputation(address agent, uint256 reputation) external {
require(multiSigSigners[msg.sender], "Not authorized");
agentWallets[agent].reputation = reputation;
}
}