// ACC-Governance: 资产治理协议(Governance Protocol) // // NAC原生的资产治理标准,用于去中心化治理和投票 // 100% NAC原生协议,不是任何现有标准的实现 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 提案状态 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ProposalStatus { /// 草稿 Draft, /// 活跃(投票中) Active, /// 已通过 Passed, /// 已拒绝 Rejected, /// 已执行 Executed, /// 已取消 Cancelled, } /// 投票选项 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum VoteOption { /// 赞成 For, /// 反对 Against, /// 弃权 Abstain, } /// 提案类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ProposalType { /// 参数修改 ParameterChange, /// 资金分配 FundingAllocation, /// 协议升级 ProtocolUpgrade, /// 资产管理 AssetManagement, /// 其他 Other(String), } /// 治理提案 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GovernanceProposal { /// 提案ID pub proposal_id: String, /// 资产ID pub asset_id: String, /// 提案人地址 pub proposer: String, /// 提案类型 pub proposal_type: ProposalType, /// 提案标题 pub title: String, /// 提案描述 pub description: String, /// 提案状态 pub status: ProposalStatus, /// 创建时间 pub created_at: u64, /// 投票开始时间 pub voting_start: u64, /// 投票结束时间 pub voting_end: u64, /// 执行时间 pub executed_at: Option, /// 赞成票数 pub votes_for: u128, /// 反对票数 pub votes_against: u128, /// 弃权票数 pub votes_abstain: u128, /// 通过阈值(百分比,如5000表示50%) pub quorum_threshold: u16, /// 投票记录 (voter -> VoteOption) pub votes: HashMap, } /// 投票记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VoteRecord { /// 投票ID pub vote_id: String, /// 提案ID pub proposal_id: String, /// 投票人地址 pub voter: String, /// 投票选项 pub option: VoteOption, /// 投票权重 pub voting_power: u128, /// 投票时间 pub voted_at: u64, } /// 治理错误类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum GovernanceError { /// 提案不存在 ProposalNotFound, /// 提案已存在 ProposalAlreadyExists, /// 投票未开始 VotingNotStarted, /// 投票已结束 VotingEnded, /// 已投票 AlreadyVoted, /// 提案未通过 ProposalNotPassed, /// 提案已执行 ProposalAlreadyExecuted, /// 未授权操作 Unauthorized, /// 无效的投票权重 InvalidVotingPower, } /// 治理状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GovernanceState { /// 提案映射 (proposal_id -> GovernanceProposal) pub proposals: HashMap, /// 资产提案列表 (asset_id -> [proposal_ids]) pub asset_proposals: HashMap>, /// 提案人提案列表 (proposer -> [proposal_ids]) pub proposer_proposals: HashMap>, /// 投票记录 (vote_id -> VoteRecord) pub vote_records: HashMap, } /// ACC-Governance接口 pub trait ACCGovernance { /// 创建提案 fn create_proposal(&mut self, proposal: GovernanceProposal) -> Result<(), GovernanceError>; /// 获取提案 fn get_proposal(&self, proposal_id: &str) -> Result; /// 投票 fn vote( &mut self, proposal_id: &str, voter: &str, option: VoteOption, voting_power: u128, ) -> Result<(), GovernanceError>; /// 执行提案 fn execute_proposal(&mut self, proposal_id: &str) -> Result<(), GovernanceError>; /// 取消提案 fn cancel_proposal(&mut self, proposal_id: &str) -> Result<(), GovernanceError>; /// 获取提案结果 fn get_proposal_result(&self, proposal_id: &str) -> Result<(u128, u128, u128), GovernanceError>; /// 检查提案是否通过 fn is_proposal_passed(&self, proposal_id: &str) -> bool; /// 获取资产的提案列表 fn get_asset_proposals(&self, asset_id: &str) -> Vec; /// 获取提案人的提案列表 fn get_proposer_proposals(&self, proposer: &str) -> Vec; /// 获取投票记录 fn get_vote_record(&self, vote_id: &str) -> Result; /// 获取活跃提案列表 fn get_active_proposals(&self) -> Vec; /// 更新提案状态 fn update_proposal_status( &mut self, proposal_id: &str, status: ProposalStatus, ) -> Result<(), GovernanceError>; } /// ACC-Governance标准实现 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GovernanceToken { state: GovernanceState, } impl GovernanceToken { /// 创建新的治理管理器 pub fn new() -> Self { Self { state: GovernanceState { proposals: HashMap::new(), asset_proposals: HashMap::new(), proposer_proposals: HashMap::new(), vote_records: HashMap::new(), }, } } /// 获取状态的可变引用 pub fn state_mut(&mut self) -> &mut GovernanceState { &mut self.state } /// 获取状态的不可变引用 pub fn state(&self) -> &GovernanceState { &self.state } /// 检查投票是否有效 fn is_voting_active(&self, proposal: &GovernanceProposal) -> bool { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); now >= proposal.voting_start && now <= proposal.voting_end } } impl Default for GovernanceToken { fn default() -> Self { Self::new() } } impl ACCGovernance for GovernanceToken { fn create_proposal(&mut self, mut proposal: GovernanceProposal) -> Result<(), GovernanceError> { // 检查提案是否已存在 if self.state.proposals.contains_key(&proposal.proposal_id) { return Err(GovernanceError::ProposalAlreadyExists); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); proposal.created_at = now; proposal.status = ProposalStatus::Active; proposal.votes_for = 0; proposal.votes_against = 0; proposal.votes_abstain = 0; let proposal_id = proposal.proposal_id.clone(); let asset_id = proposal.asset_id.clone(); let proposer = proposal.proposer.clone(); // 保存提案 self.state .proposals .insert(proposal_id.clone(), proposal); // 更新资产提案列表 self.state .asset_proposals .entry(asset_id) .or_insert_with(Vec::new) .push(proposal_id.clone()); // 更新提案人提案列表 self.state .proposer_proposals .entry(proposer) .or_insert_with(Vec::new) .push(proposal_id); Ok(()) } fn get_proposal(&self, proposal_id: &str) -> Result { self.state .proposals .get(proposal_id) .cloned() .ok_or(GovernanceError::ProposalNotFound) } fn vote( &mut self, proposal_id: &str, voter: &str, option: VoteOption, voting_power: u128, ) -> Result<(), GovernanceError> { let mut proposal = self.get_proposal(proposal_id)?; // 检查投票是否有效 if !self.is_voting_active(&proposal) { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); if now < proposal.voting_start { return Err(GovernanceError::VotingNotStarted); } else { return Err(GovernanceError::VotingEnded); } } // 检查是否已投票 if proposal.votes.contains_key(voter) { return Err(GovernanceError::AlreadyVoted); } // 检查投票权重 if voting_power == 0 { return Err(GovernanceError::InvalidVotingPower); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); // 更新投票统计 match option { VoteOption::For => proposal.votes_for += voting_power, VoteOption::Against => proposal.votes_against += voting_power, VoteOption::Abstain => proposal.votes_abstain += voting_power, } // 记录投票 proposal.votes.insert(voter.to_string(), option.clone()); // 保存提案 self.state .proposals .insert(proposal_id.to_string(), proposal); // 创建投票记录 let vote_id = format!("{}_{}", proposal_id, voter); let vote_record = VoteRecord { vote_id: vote_id.clone(), proposal_id: proposal_id.to_string(), voter: voter.to_string(), option, voting_power, voted_at: now, }; self.state.vote_records.insert(vote_id, vote_record); Ok(()) } fn execute_proposal(&mut self, proposal_id: &str) -> Result<(), GovernanceError> { let mut proposal = self.get_proposal(proposal_id)?; // 检查提案是否通过 if !self.is_proposal_passed(proposal_id) { return Err(GovernanceError::ProposalNotPassed); } // 检查提案是否已执行 if proposal.status == ProposalStatus::Executed { return Err(GovernanceError::ProposalAlreadyExecuted); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); proposal.status = ProposalStatus::Executed; proposal.executed_at = Some(now); self.state .proposals .insert(proposal_id.to_string(), proposal); Ok(()) } fn cancel_proposal(&mut self, proposal_id: &str) -> Result<(), GovernanceError> { let mut proposal = self.get_proposal(proposal_id)?; if proposal.status == ProposalStatus::Executed { return Err(GovernanceError::ProposalAlreadyExecuted); } proposal.status = ProposalStatus::Cancelled; self.state .proposals .insert(proposal_id.to_string(), proposal); Ok(()) } fn get_proposal_result(&self, proposal_id: &str) -> Result<(u128, u128, u128), GovernanceError> { let proposal = self.get_proposal(proposal_id)?; Ok(( proposal.votes_for, proposal.votes_against, proposal.votes_abstain, )) } fn is_proposal_passed(&self, proposal_id: &str) -> bool { if let Ok(proposal) = self.get_proposal(proposal_id) { let total_votes = proposal.votes_for + proposal.votes_against + proposal.votes_abstain; if total_votes == 0 { return false; } let approval_rate = (proposal.votes_for * 10000 / total_votes) as u16; approval_rate >= proposal.quorum_threshold } else { false } } fn get_asset_proposals(&self, asset_id: &str) -> Vec { self.state .asset_proposals .get(asset_id) .map(|proposal_ids| { proposal_ids .iter() .filter_map(|id| self.state.proposals.get(id).cloned()) .collect() }) .unwrap_or_default() } fn get_proposer_proposals(&self, proposer: &str) -> Vec { self.state .proposer_proposals .get(proposer) .map(|proposal_ids| { proposal_ids .iter() .filter_map(|id| self.state.proposals.get(id).cloned()) .collect() }) .unwrap_or_default() } fn get_vote_record(&self, vote_id: &str) -> Result { self.state .vote_records .get(vote_id) .cloned() .ok_or(GovernanceError::ProposalNotFound) } fn get_active_proposals(&self) -> Vec { self.state .proposals .values() .filter(|proposal| proposal.status == ProposalStatus::Active) .cloned() .collect() } fn update_proposal_status( &mut self, proposal_id: &str, status: ProposalStatus, ) -> Result<(), GovernanceError> { let mut proposal = self.get_proposal(proposal_id)?; proposal.status = status; self.state .proposals .insert(proposal_id.to_string(), proposal); Ok(()) } } #[cfg(test)] mod tests { use super::*; fn create_test_proposal() -> GovernanceProposal { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); GovernanceProposal { proposal_id: "PROP-001".to_string(), asset_id: "RWA-001".to_string(), proposer: "alice".to_string(), proposal_type: ProposalType::ParameterChange, title: "Test Proposal".to_string(), description: "This is a test proposal".to_string(), status: ProposalStatus::Active, created_at: now, voting_start: now - 3600, // 1小时前开始 voting_end: now + 86400 * 7, // 7天后结束 executed_at: None, votes_for: 0, votes_against: 0, votes_abstain: 0, quorum_threshold: 5000, // 50% votes: HashMap::new(), } } #[test] fn test_create_proposal() { let mut governance = GovernanceToken::new(); let proposal = create_test_proposal(); assert!(governance.create_proposal(proposal).is_ok()); } #[test] fn test_vote() { let mut governance = GovernanceToken::new(); let proposal = create_test_proposal(); governance.create_proposal(proposal).unwrap(); assert!(governance .vote("PROP-001", "bob", VoteOption::For, 1000) .is_ok()); let (votes_for, _, _) = governance.get_proposal_result("PROP-001").unwrap(); assert_eq!(votes_for, 1000); } #[test] fn test_is_proposal_passed() { let mut governance = GovernanceToken::new(); let proposal = create_test_proposal(); governance.create_proposal(proposal).unwrap(); governance .vote("PROP-001", "bob", VoteOption::For, 6000) .unwrap(); governance .vote("PROP-001", "charlie", VoteOption::Against, 4000) .unwrap(); assert!(governance.is_proposal_passed("PROP-001")); } #[test] fn test_execute_proposal() { let mut governance = GovernanceToken::new(); let proposal = create_test_proposal(); governance.create_proposal(proposal).unwrap(); governance .vote("PROP-001", "bob", VoteOption::For, 6000) .unwrap(); governance .vote("PROP-001", "charlie", VoteOption::Against, 4000) .unwrap(); assert!(governance.execute_proposal("PROP-001").is_ok()); assert_eq!( governance.get_proposal("PROP-001").unwrap().status, ProposalStatus::Executed ); } #[test] fn test_cancel_proposal() { let mut governance = GovernanceToken::new(); let proposal = create_test_proposal(); governance.create_proposal(proposal).unwrap(); assert!(governance.cancel_proposal("PROP-001").is_ok()); assert_eq!( governance.get_proposal("PROP-001").unwrap().status, ProposalStatus::Cancelled ); } }