ShukaGovernance

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/ShukaGovernance.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./ValidatorNetwork.sol";

/**
 * @title ShukaGovernance
 * @dev Decentralized governance for Shuka protocol decisions
 * @notice Enables community-driven protocol upgrades and parameter changes
 */
contract ShukaGovernance {
    
    // Proposal types
    enum ProposalType {
        PARAMETER_CHANGE,
        CONTRACT_UPGRADE,
        VALIDATOR_ADDITION,
        VALIDATOR_REMOVAL,
        FEE_ADJUSTMENT,
        EMERGENCY_ACTION
    }
    
    // Proposal status
    enum ProposalStatus {
        PENDING,
        ACTIVE,
        CANCELLED,
        DEFEATED,
        SUCCEEDED,
        QUEUED,
        EXPIRED,
        EXECUTED
    }
    
    // Proposal structure
    struct Proposal {
        uint256 id;
        address proposer;
        ProposalType proposalType;
        string description;
        address[] targets;
        uint256[] values;
        bytes[] calldatas;
        uint256 startBlock;
        uint256 endBlock;
        uint256 forVotes;
        uint256 againstVotes;
        uint256 abstainVotes;
        ProposalStatus status;
        mapping(address => Receipt) receipts;
        uint256 eta; // Execution time for timelock
        bool executed;
    }
    
    // Voting receipt
    struct Receipt {
        bool hasVoted;
        uint8 support; // 0 = Against, 1 = For, 2 = Abstain
        uint256 votes;
    }
    
    // Constants
    uint256 public constant VOTING_PERIOD = 3 days;
    uint256 public constant VOTING_DELAY = 1 days;
    uint256 public constant PROPOSAL_THRESHOLD = 0.01 ether; // Min stake to propose
    uint256 public constant QUORUM_PERCENTAGE = 4; // 4% of total stake
    uint256 public constant TIMELOCK_DELAY = 2 days;
    
    // State variables
    address public admin;
    address public validatorNetworkAddress;
    address public trustOracleAddress;
    address public licenseAnchorAddress;
    
    uint256 public proposalCount;
    mapping(uint256 => Proposal) public proposals;
    mapping(address => uint256) public latestProposalIds;
    
    // Governance token (voting power from validator stakes)
    mapping(address => uint256) public votingPower;
    uint256 public totalVotingPower;
    
    // Timelock
    mapping(bytes32 => bool) public queuedTransactions;
    
    // Events
    event ProposalCreated(
        uint256 id,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 startBlock,
        uint256 endBlock,
        string description
    );
    
    event VoteCast(
        address indexed voter,
        uint256 proposalId,
        uint8 support,
        uint256 votes,
        string reason
    );
    
    event ProposalCanceled(uint256 id);
    event ProposalQueued(uint256 id, uint256 eta);
    event ProposalExecuted(uint256 id);
    
    event VotingPowerUpdated(address indexed account, uint256 oldPower, uint256 newPower);
    
    // Modifiers
    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin");
        _;
    }
    
    modifier onlyValidatorNetwork() {
        require(msg.sender == validatorNetworkAddress, "Only validator network");
        _;
    }
    
    constructor(
        address _validatorNetwork,
        address _trustOracle,
        address _licenseAnchor
    ) {
        admin = msg.sender;
        validatorNetworkAddress = _validatorNetwork;
        trustOracleAddress = _trustOracle;
        licenseAnchorAddress = _licenseAnchor;
    }
    
    /**
     * @dev Update voting power based on validator stakes
     * @param _voter Address of the voter
     * @param _newPower New voting power
     */
    function updateVotingPower(address _voter, uint256 _newPower) external onlyValidatorNetwork {
        uint256 oldPower = votingPower[_voter];
        votingPower[_voter] = _newPower;
        
        totalVotingPower = totalVotingPower - oldPower + _newPower;
        
        emit VotingPowerUpdated(_voter, oldPower, _newPower);
    }
    
    /**
     * @dev Create a new proposal
     * @param _targets Target addresses for calls
     * @param _values ETH values for calls
     * @param _calldatas Encoded function calls
     * @param _description Proposal description
     */
    function propose(
        address[] memory _targets,
        uint256[] memory _values,
        bytes[] memory _calldatas,
        string memory _description,
        ProposalType _proposalType
    ) external returns (uint256) {
        require(
            votingPower[msg.sender] >= PROPOSAL_THRESHOLD,
            "Below proposal threshold"
        );
        require(
            _targets.length == _values.length && _targets.length == _calldatas.length,
            "Proposal function mismatch"
        );
        require(_targets.length > 0, "Must provide actions");
        
        uint256 proposalId = ++proposalCount;
        Proposal storage newProposal = proposals[proposalId];
        
        newProposal.id = proposalId;
        newProposal.proposer = msg.sender;
        newProposal.proposalType = _proposalType;
        newProposal.description = _description;
        newProposal.targets = _targets;
        newProposal.values = _values;
        newProposal.calldatas = _calldatas;
        newProposal.startBlock = block.number + VOTING_DELAY;
        newProposal.endBlock = newProposal.startBlock + VOTING_PERIOD;
        newProposal.status = ProposalStatus.PENDING;
        
        latestProposalIds[msg.sender] = proposalId;
        
        emit ProposalCreated(
            proposalId,
            msg.sender,
            _targets,
            _values,
            new string[](_targets.length), // Signatures not used in this version
            _calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            _description
        );
        
        return proposalId;
    }
    
    /**
     * @dev Cast a vote on a proposal
     * @param _proposalId ID of the proposal
     * @param _support Vote type (0=Against, 1=For, 2=Abstain)
     */
    function castVote(uint256 _proposalId, uint8 _support) external {
        return _castVote(msg.sender, _proposalId, _support, "");
    }
    
    /**
     * @dev Cast a vote with reason
     * @param _proposalId ID of the proposal
     * @param _support Vote type
     * @param _reason Reason for vote
     */
    function castVoteWithReason(
        uint256 _proposalId,
        uint8 _support,
        string calldata _reason
    ) external {
        return _castVote(msg.sender, _proposalId, _support, _reason);
    }
    
    /**
     * @dev Internal function to cast a vote
     */
    function _castVote(
        address _voter,
        uint256 _proposalId,
        uint8 _support,
        string memory _reason
    ) internal {
        require(state(_proposalId) == ProposalStatus.ACTIVE, "Voting closed");
        require(_support <= 2, "Invalid vote type");
        
        Proposal storage proposal = proposals[_proposalId];
        Receipt storage receipt = proposal.receipts[_voter];
        
        require(!receipt.hasVoted, "Already voted");
        
        uint256 votes = votingPower[_voter];
        require(votes > 0, "No voting power");
        
        if (_support == 0) {
            proposal.againstVotes += votes;
        } else if (_support == 1) {
            proposal.forVotes += votes;
        } else {
            proposal.abstainVotes += votes;
        }
        
        receipt.hasVoted = true;
        receipt.support = _support;
        receipt.votes = votes;
        
        emit VoteCast(_voter, _proposalId, _support, votes, _reason);
    }
    
    /**
     * @dev Get the state of a proposal
     * @param _proposalId ID of the proposal
     */
    function state(uint256 _proposalId) public view returns (ProposalStatus) {
        Proposal storage proposal = proposals[_proposalId];
        
        if (proposal.executed) {
            return ProposalStatus.EXECUTED;
        }
        
        if (proposal.status == ProposalStatus.CANCELLED) {
            return ProposalStatus.CANCELLED;
        }
        
        if (block.number <= proposal.startBlock) {
            return ProposalStatus.PENDING;
        }
        
        if (block.number <= proposal.endBlock) {
            return ProposalStatus.ACTIVE;
        }
        
        if (proposal.forVotes <= proposal.againstVotes || 
            proposal.forVotes < quorumVotes()) {
            return ProposalStatus.DEFEATED;
        }
        
        if (proposal.eta == 0) {
            return ProposalStatus.SUCCEEDED;
        }
        
        if (block.timestamp >= proposal.eta + TIMELOCK_DELAY) {
            return ProposalStatus.EXPIRED;
        }
        
        return ProposalStatus.QUEUED;
    }
    
    /**
     * @dev Queue a successful proposal for execution
     * @param _proposalId ID of the proposal
     */
    function queue(uint256 _proposalId) external {
        require(state(_proposalId) == ProposalStatus.SUCCEEDED, "Proposal not succeeded");
        
        Proposal storage proposal = proposals[_proposalId];
        uint256 eta = block.timestamp + TIMELOCK_DELAY;
        
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            bytes32 txHash = keccak256(
                abi.encode(
                    proposal.targets[i],
                    proposal.values[i],
                    proposal.calldatas[i],
                    eta
                )
            );
            queuedTransactions[txHash] = true;
        }
        
        proposal.eta = eta;
        emit ProposalQueued(_proposalId, eta);
    }
    
    /**
     * @dev Execute a queued proposal
     * @param _proposalId ID of the proposal
     */
    function execute(uint256 _proposalId) external payable {
        require(state(_proposalId) == ProposalStatus.QUEUED, "Proposal not queued");
        
        Proposal storage proposal = proposals[_proposalId];
        require(block.timestamp >= proposal.eta, "Still in timelock");
        require(block.timestamp <= proposal.eta + TIMELOCK_DELAY, "Execution window expired");
        
        proposal.executed = true;
        
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            bytes32 txHash = keccak256(
                abi.encode(
                    proposal.targets[i],
                    proposal.values[i],
                    proposal.calldatas[i],
                    proposal.eta
                )
            );
            require(queuedTransactions[txHash], "Transaction not queued");
            queuedTransactions[txHash] = false;
            
            (bool success,) = proposal.targets[i].call{value: proposal.values[i]}(
                proposal.calldatas[i]
            );
            require(success, "Transaction execution failed");
        }
        
        emit ProposalExecuted(_proposalId);
    }
    
    /**
     * @dev Cancel a proposal
     * @param _proposalId ID of the proposal
     */
    function cancel(uint256 _proposalId) external {
        Proposal storage proposal = proposals[_proposalId];
        require(
            msg.sender == proposal.proposer || msg.sender == admin,
            "Cannot cancel"
        );
        require(
            state(_proposalId) != ProposalStatus.EXECUTED,
            "Cannot cancel executed proposal"
        );
        
        proposal.status = ProposalStatus.CANCELLED;
        
        // Clear timelock if queued
        if (proposal.eta != 0) {
            for (uint256 i = 0; i < proposal.targets.length; i++) {
                bytes32 txHash = keccak256(
                    abi.encode(
                        proposal.targets[i],
                        proposal.values[i],
                        proposal.calldatas[i],
                        proposal.eta
                    )
                );
                queuedTransactions[txHash] = false;
            }
        }
        
        emit ProposalCanceled(_proposalId);
    }
    
    /**
     * @dev Get the required quorum votes
     */
    function quorumVotes() public view returns (uint256) {
        return (totalVotingPower * QUORUM_PERCENTAGE) / 100;
    }
    
    /**
     * @dev Get proposal details
     * @param _proposalId ID of the proposal
     */
    function getProposal(uint256 _proposalId) external view returns (
        address proposer,
        string memory description,
        uint256 forVotes,
        uint256 againstVotes,
        uint256 abstainVotes,
        uint256 startBlock,
        uint256 endBlock,
        ProposalStatus status
    ) {
        Proposal storage proposal = proposals[_proposalId];
        return (
            proposal.proposer,
            proposal.description,
            proposal.forVotes,
            proposal.againstVotes,
            proposal.abstainVotes,
            proposal.startBlock,
            proposal.endBlock,
            state(_proposalId)
        );
    }
    
    /**
     * @dev Get actions of a proposal
     * @param _proposalId ID of the proposal
     */
    function getActions(uint256 _proposalId) external view returns (
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas
    ) {
        Proposal storage proposal = proposals[_proposalId];
        return (proposal.targets, proposal.values, proposal.calldatas);
    }
    
    /**
     * @dev Get receipt of a voter for a proposal
     * @param _proposalId ID of the proposal
     * @param _voter Address of the voter
     */
    function getReceipt(uint256 _proposalId, address _voter) external view returns (
        bool hasVoted,
        uint8 support,
        uint256 votes
    ) {
        Receipt memory receipt = proposals[_proposalId].receipts[_voter];
        return (receipt.hasVoted, receipt.support, receipt.votes);
    }
    
    /**
     * @dev Emergency function to update contract addresses
     * @param _validatorNetwork New validator network address
     * @param _trustOracle New trust oracle address
     * @param _licenseAnchor New license anchor address
     */
    function updateContractAddresses(
        address _validatorNetwork,
        address _trustOracle,
        address _licenseAnchor
    ) external onlyAdmin {
        validatorNetworkAddress = _validatorNetwork;
        trustOracleAddress = _trustOracle;
        licenseAnchorAddress = _licenseAnchor;
    }
    
    /**
     * @dev Sync voting power with validator network
     */
    function syncVotingPower() external {
        ValidatorNetwork validator = ValidatorNetwork(validatorNetworkAddress);
        address[] memory validators = validator.getActiveValidators();
        
        uint256 newTotalPower = 0;
        for (uint256 i = 0; i < validators.length; i++) {
            (,uint256 stakedAmount,,,,,,,,,,) = validator.validators(validators[i]);
            votingPower[validators[i]] = stakedAmount;
            newTotalPower += stakedAmount;
        }
        
        totalVotingPower = newTotalPower;
    }
    
    /**
     * @dev Receive ETH for proposal execution
     */
    receive() external payable {}
}"
    },
    "contracts/ValidatorNetwork.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/**
 * @title ValidatorNetwork
 * @dev Decentralized validator network with Byzantine fault tolerance for Shuka
 * @notice Implements multi-validator consensus for trust verification
 */
contract ValidatorNetwork {
    
    // Validator states
    enum ValidatorStatus { INACTIVE, ACTIVE, SUSPENDED, SLASHED }
    
    // Consensus proposal states
    enum ProposalStatus { PENDING, APPROVED, REJECTED, EXECUTED, EXPIRED }
    
    // Validator information
    struct Validator {
        address validatorAddress;
        uint256 stakedAmount;
        uint256 reputationScore;
        ValidatorStatus status;
        uint256 totalValidations;
        uint256 successfulValidations;
        uint256 failedValidations;
        uint256 lastActiveBlock;
        uint256 slashingEvents;
        bool isAIAgent;
        string aiAgentId;
        uint256 joinedAt;
    }
    
    // Consensus proposal for validation
    struct ConsensusProposal {
        uint256 proposalId;
        address proposer;
        bytes32 dataHash;
        string proposalType;
        bytes proposalData;
        uint256 votesFor;
        uint256 votesAgainst;
        uint256 totalVotes;
        mapping(address => bool) hasVoted;
        mapping(address => bool) voteValue;
        ProposalStatus status;
        uint256 createdAt;
        uint256 executedAt;
        uint256 expiresAt;
    }
    
    // AI Agent validation record
    struct AIValidation {
        string agentId;
        address agentWallet;
        bytes32 validationHash;
        uint256 confidence;
        string validationType;
        uint256 timestamp;
        bool isValid;
    }
    
    // Constants for Byzantine fault tolerance
    uint256 public constant MINIMUM_VALIDATORS = 3;
    uint256 public constant BYZANTINE_THRESHOLD = 67; // 67% for Byzantine fault tolerance
    uint256 public constant MINIMUM_STAKE = 0.01 ether;
    uint256 public constant SLASHING_PENALTY = 10; // 10% of stake
    uint256 public constant PROPOSAL_DURATION = 1 hours;
    uint256 public constant VALIDATOR_TIMEOUT = 7 days;
    
    // State variables
    address public admin;
    address public trustOracleAddress;
    address public proofRegistryAddress;
    
    mapping(address => Validator) public validators;
    mapping(uint256 => ConsensusProposal) public proposals;
    mapping(string => AIValidation[]) public aiValidations;
    mapping(address => uint256) public pendingRewards;
    mapping(bytes32 => bool) public processedValidations;
    
    address[] public activeValidatorList;
    uint256 public proposalCounter;
    uint256 public totalStaked;
    uint256 public totalValidations;
    uint256 public rewardPool;
    
    // Events
    event ValidatorJoined(address indexed validator, uint256 stake, bool isAI);
    event ValidatorExited(address indexed validator, uint256 returnedStake);
    event ValidatorSlashed(address indexed validator, uint256 penalty, string reason);
    event ProposalCreated(uint256 indexed proposalId, address proposer, string proposalType);
    event VoteCast(uint256 indexed proposalId, address voter, bool support);
    event ProposalExecuted(uint256 indexed proposalId, bool approved);
    event ValidationRecorded(bytes32 validationHash, address validator, bool result);
    event RewardDistributed(address indexed validator, uint256 amount);
    event AIValidationRecorded(string agentId, bytes32 validationHash, uint256 confidence);
    
    // Modifiers
    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin");
        _;
    }
    
    modifier onlyActiveValidator() {
        require(validators[msg.sender].status == ValidatorStatus.ACTIVE, "Not active validator");
        _;
    }
    
    modifier validatorExists(address _validator) {
        require(validators[_validator].validatorAddress != address(0), "Validator not found");
        _;
    }
    
    constructor(address _trustOracle, address _proofRegistry) {
        admin = msg.sender;
        trustOracleAddress = _trustOracle;
        proofRegistryAddress = _proofRegistry;
    }
    
    /**
     * @dev Join as a validator by staking ETH
     * @param _isAIAgent Whether this is an AI agent validator
     * @param _aiAgentId ID of the AI agent (if applicable)
     */
    function joinAsValidator(bool _isAIAgent, string memory _aiAgentId) external payable {
        require(msg.value >= MINIMUM_STAKE, "Insufficient stake");
        require(validators[msg.sender].validatorAddress == address(0), "Already a validator");
        
        validators[msg.sender] = Validator({
            validatorAddress: msg.sender,
            stakedAmount: msg.value,
            reputationScore: 100,
            status: ValidatorStatus.ACTIVE,
            totalValidations: 0,
            successfulValidations: 0,
            failedValidations: 0,
            lastActiveBlock: block.number,
            slashingEvents: 0,
            isAIAgent: _isAIAgent,
            aiAgentId: _aiAgentId,
            joinedAt: block.timestamp
        });
        
        activeValidatorList.push(msg.sender);
        totalStaked += msg.value;
        
        emit ValidatorJoined(msg.sender, msg.value, _isAIAgent);
    }
    
    /**
     * @dev Create a consensus proposal for validation
     * @param _dataHash Hash of the data to validate
     * @param _proposalType Type of proposal
     * @param _proposalData Encoded proposal data
     */
    function createConsensusProposal(
        bytes32 _dataHash,
        string memory _proposalType,
        bytes memory _proposalData
    ) public onlyActiveValidator returns (uint256) {
        require(!processedValidations[_dataHash], "Already processed");
        
        uint256 proposalId = ++proposalCounter;
        
        ConsensusProposal storage proposal = proposals[proposalId];
        proposal.proposalId = proposalId;
        proposal.proposer = msg.sender;
        proposal.dataHash = _dataHash;
        proposal.proposalType = _proposalType;
        proposal.proposalData = _proposalData;
        proposal.status = ProposalStatus.PENDING;
        proposal.createdAt = block.timestamp;
        proposal.expiresAt = block.timestamp + PROPOSAL_DURATION;
        
        emit ProposalCreated(proposalId, msg.sender, _proposalType);
        
        return proposalId;
    }
    
    /**
     * @dev Vote on a consensus proposal
     * @param _proposalId ID of the proposal
     * @param _support Whether to support the proposal
     */
    function voteOnProposal(uint256 _proposalId, bool _support) external onlyActiveValidator {
        ConsensusProposal storage proposal = proposals[_proposalId];
        require(proposal.status == ProposalStatus.PENDING, "Proposal not pending");
        require(block.timestamp <= proposal.expiresAt, "Proposal expired");
        require(!proposal.hasVoted[msg.sender], "Already voted");
        
        proposal.hasVoted[msg.sender] = true;
        proposal.voteValue[msg.sender] = _support;
        proposal.totalVotes++;
        
        // Weight vote by stake
        uint256 voteWeight = validators[msg.sender].stakedAmount;
        
        if (_support) {
            proposal.votesFor += voteWeight;
        } else {
            proposal.votesAgainst += voteWeight;
        }
        
        emit VoteCast(_proposalId, msg.sender, _support);
        
        // Check if we have enough votes to execute
        _checkAndExecuteProposal(_proposalId);
    }
    
    /**
     * @dev Check if proposal has reached consensus and execute
     * @param _proposalId ID of the proposal
     */
    function _checkAndExecuteProposal(uint256 _proposalId) internal {
        ConsensusProposal storage proposal = proposals[_proposalId];
        
        // Need participation from at least 2/3 of validators
        uint256 requiredParticipation = (activeValidatorList.length * 2) / 3;
        if (proposal.totalVotes < requiredParticipation && proposal.totalVotes < MINIMUM_VALIDATORS) {
            return;
        }
        
        uint256 totalVoteWeight = proposal.votesFor + proposal.votesAgainst;
        if (totalVoteWeight == 0) return;
        
        uint256 approvalPercentage = (proposal.votesFor * 100) / totalVoteWeight;
        
        if (approvalPercentage >= BYZANTINE_THRESHOLD) {
            proposal.status = ProposalStatus.APPROVED;
            proposal.executedAt = block.timestamp;
            processedValidations[proposal.dataHash] = true;
            
            // Reward validators who voted correctly
            _distributeRewards(_proposalId, true);
            
            // Execute proposal action
            _executeProposalAction(proposal);
            
            emit ProposalExecuted(_proposalId, true);
        } else if (approvalPercentage < (100 - BYZANTINE_THRESHOLD)) {
            proposal.status = ProposalStatus.REJECTED;
            proposal.executedAt = block.timestamp;
            
            // Punish validators who voted incorrectly
            _distributeRewards(_proposalId, false);
            
            emit ProposalExecuted(_proposalId, false);
        }
    }
    
    /**
     * @dev Execute the action specified in an approved proposal
     * @param proposal The approved proposal
     */
    function _executeProposalAction(ConsensusProposal storage proposal) internal {
        // Decode and execute based on proposal type
        if (keccak256(bytes(proposal.proposalType)) == keccak256("TRUST_UPDATE")) {
            // Call TrustOracle to update trust score
            (bool success,) = trustOracleAddress.call(proposal.proposalData);
            require(success, "Trust update failed");
        } else if (keccak256(bytes(proposal.proposalType)) == keccak256("PROOF_VALIDATION")) {
            // Call ProofRegistry to validate proof
            (bool success,) = proofRegistryAddress.call(proposal.proposalData);
            require(success, "Proof validation failed");
        }
        
        emit ValidationRecorded(proposal.dataHash, proposal.proposer, true);
    }
    
    /**
     * @dev Distribute rewards to validators based on voting outcome
     * @param _proposalId ID of the proposal
     * @param _approvedOutcome Whether the proposal was approved
     */
    function _distributeRewards(uint256 _proposalId, bool _approvedOutcome) internal {
        ConsensusProposal storage proposal = proposals[_proposalId];
        uint256 rewardPerValidator = rewardPool / (proposal.totalVotes > 0 ? proposal.totalVotes : 1);
        
        for (uint256 i = 0; i < activeValidatorList.length; i++) {
            address validator = activeValidatorList[i];
            if (proposal.hasVoted[validator]) {
                bool votedCorrectly = proposal.voteValue[validator] == _approvedOutcome;
                
                if (votedCorrectly) {
                    // Reward for correct vote
                    pendingRewards[validator] += rewardPerValidator;
                    validators[validator].successfulValidations++;
                    validators[validator].reputationScore = min(100, validators[validator].reputationScore + 1);
                    
                    emit RewardDistributed(validator, rewardPerValidator);
                } else {
                    // Penalty for incorrect vote
                    validators[validator].failedValidations++;
                    validators[validator].reputationScore = validators[validator].reputationScore > 5 ? 
                        validators[validator].reputationScore - 5 : 0;
                    
                    // Slash if reputation too low
                    if (validators[validator].reputationScore < 20) {
                        _slashValidator(validator, "Low reputation");
                    }
                }
                
                validators[validator].totalValidations++;
            }
        }
    }
    
    /**
     * @dev Record validation from an AI agent
     * @param _agentId ID of the AI agent
     * @param _validationHash Hash of the validation
     * @param _confidence Confidence level (0-100)
     * @param _validationType Type of validation
     */
    function recordAIValidation(
        string memory _agentId,
        bytes32 _validationHash,
        uint256 _confidence,
        string memory _validationType
    ) external onlyActiveValidator {
        require(validators[msg.sender].isAIAgent, "Not an AI validator");
        require(_confidence <= 100, "Invalid confidence");
        
        AIValidation memory validation = AIValidation({
            agentId: _agentId,
            agentWallet: msg.sender,
            validationHash: _validationHash,
            confidence: _confidence,
            validationType: _validationType,
            timestamp: block.timestamp,
            isValid: true
        });
        
        aiValidations[_agentId].push(validation);
        
        // Update validator activity
        validators[msg.sender].lastActiveBlock = block.number;
        validators[msg.sender].totalValidations++;
        
        emit AIValidationRecorded(_agentId, _validationHash, _confidence);
        
        // If confidence is high enough, auto-create proposal
        if (_confidence >= 80) {
            bytes memory proposalData = abi.encode(msg.sender, _validationHash, _confidence);
            createConsensusProposal(_validationHash, _validationType, proposalData);
        }
    }
    
    /**
     * @dev Slash a validator for misbehavior
     * @param _validator Address of the validator to slash
     * @param _reason Reason for slashing
     */
    function _slashValidator(address _validator, string memory _reason) internal {
        Validator storage validator = validators[_validator];
        
        uint256 penalty = (validator.stakedAmount * SLASHING_PENALTY) / 100;
        validator.stakedAmount -= penalty;
        validator.slashingEvents++;
        rewardPool += penalty;
        
        if (validator.slashingEvents >= 3 || validator.stakedAmount < MINIMUM_STAKE) {
            validator.status = ValidatorStatus.SLASHED;
            _removeFromActiveList(_validator);
        } else {
            validator.status = ValidatorStatus.SUSPENDED;
        }
        
        emit ValidatorSlashed(_validator, penalty, _reason);
    }
    
    /**
     * @dev Exit as a validator and withdraw stake
     */
    function exitAsValidator() external validatorExists(msg.sender) {
        Validator storage validator = validators[msg.sender];
        require(validator.status != ValidatorStatus.SLASHED, "Validator is slashed");
        
        uint256 stakeToReturn = validator.stakedAmount;
        uint256 rewards = pendingRewards[msg.sender];
        uint256 totalReturn = stakeToReturn + rewards;
        
        validator.status = ValidatorStatus.INACTIVE;
        validator.stakedAmount = 0;
        pendingRewards[msg.sender] = 0;
        totalStaked -= stakeToReturn;
        
        _removeFromActiveList(msg.sender);
        
        (bool success,) = msg.sender.call{value: totalReturn}("");
        require(success, "Transfer failed");
        
        emit ValidatorExited(msg.sender, totalReturn);
    }
    
    /**
     * @dev Claim pending rewards
     */
    function claimRewards() external {
        uint256 rewards = pendingRewards[msg.sender];
        require(rewards > 0, "No rewards");
        
        pendingRewards[msg.sender] = 0;
        
        (bool success,) = msg.sender.call{value: rewards}("");
        require(success, "Transfer failed");
        
        emit RewardDistributed(msg.sender, rewards);
    }
    
    /**
     * @dev Check validator health and slash inactive ones
     */
    function checkValidatorHealth() external {
        for (uint256 i = 0; i < activeValidatorList.length; i++) {
            address validator = activeValidatorList[i];
            Validator storage v = validators[validator];
            
            if (block.number - v.lastActiveBlock > VALIDATOR_TIMEOUT) {
                _slashValidator(validator, "Inactivity");
            }
        }
    }
    
    /**
     * @dev Remove validator from active list
     * @param _validator Address to remove
     */
    function _removeFromActiveList(address _validator) internal {
        for (uint256 i = 0; i < activeValidatorList.length; i++) {
            if (activeValidatorList[i] == _validator) {
                activeValidatorList[i] = activeValidatorList[activeValidatorList.length - 1];
                activeValidatorList.pop();
                break;
            }
        }
    }
    
    /**
     * @dev Get active validator count
     */
    function getActiveValidatorCount() external view returns (uint256) {
        return activeValidatorList.length;
    }
    
    /**
     * @dev Get all active validators
     */
    function getActiveValidators() external view returns (address[] memory) {
        return activeValidatorList;
    }
    
    /**
     * @dev Check if consensus is possible
     */
    function isConsensusReady() external view returns (bool) {
        return activeValidatorList.length >= MINIMUM_VALIDATORS;
    }
    
    /**
     * @dev Get validator details
     */
    function getValidatorDetails(address _validator) external view returns (Validator memory) {
        return validators[_validator];
    }
    
    /**
     * @dev Fund reward pool
     */
    function fundRewardPool() external payable {
        rewardPool += msg.value;
    }
    
    /**
     * @dev Update contract addresses
     */
    function updateContractAddresses(address _trustOracle, address _proofRegistry) external onlyAdmin {
        trustOracleAddress = _trustOracle;
        proofRegistryAddress = _proofRegistry;
    }
    
    /**
     * @dev Min function
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
    
    /**
     * @dev Batch validator operations for gas optimization
     * @param _validators Array of validator addresses
     * @param _actions Array of actions (0=suspend, 1=reactivate, 2=slash)
     */
    function batchValidatorOperations(
        address[] memory _validators,
        uint256[] memory _actions
    ) external onlyAdmin {
        require(_validators.length == _actions.length, "Array mismatch");
        
        for (uint256 i = 0; i < _validators.length; i++) {
            Validator storage v = validators[_validators[i]];
            if (v.validatorAddress == address(0)) continue;
            
            if (_actions[i] == 0) {
                v.status = ValidatorStatus.SUSPENDED;
            } else if (_actions[i] == 1 && v.status == ValidatorStatus.SUSPENDED) {
                v.status = ValidatorStatus.ACTIVE;
            } else if (_actions[i] == 2) {
                _slashValidator(_validators[i], "Admin action");
            }
        }
    }
    
    /**
     * @dev Emergency pause for critical situations
     */
    bool public emergencyPause;
    
    modifier notPaused() {
        require(!emergencyPause, "Contract paused");
        _;
    }
    
    function toggleEmergencyPause() external onlyAdmin {
        emergencyPause = !emergencyPause;
    }
    
    /**
     * @dev Get proposal status
     */
    function getProposalStatus(uint256 _proposalId) external view returns (ProposalStatus) {
        return proposals[_proposalId].status;
    }
}"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "viaIR": true,
    "evmVersion": "paris",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
Multisig, Staking, Voting, Timelock, Multi-Signature, Factory, Oracle|addr:0x2eb3e7e07c99e351e87f0e992c4b7dfd838c479c|verified:true|block:23461348|tx:0x2bb988e5667fdd53d7c75178ea73e83dee5a3ee2685bc22f887aeb395ab4bf38|first_check:1759068165

Submitted on: 2025-09-28 16:02:45

Comments

Log in to comment.

No comments yet.