///! # 投票系统
///!
///! Voting System
///! 提供提案投票、权重计算和委托投票功能
///!
///! **版本**: v1.0
///! **模块**: charter-std/governance/voting.ch
use utils::math::{safe_add, safe_sub, safe_mul, safe_div};
use utils::crypto::sha3_384_hash;
// ============================================================================
// 投票枚举
// ============================================================================
/// 投票选项
pub enum VoteOption {
/// 赞成
For,
/// 反对
Against,
/// 弃权
Abstain
}
/// 投票状态
pub enum VoteStatus {
/// 待开始
Pending,
/// 进行中
Active,
/// 已结束
Ended,
/// 已取消
Cancelled
}
/// 投票结果
pub enum VoteResult {
/// 未决定
Undecided,
/// 通过
Passed,
/// 未通过
Failed,
/// 法定人数不足
QuorumNotReached
}
// ============================================================================
// 投票结构
// ============================================================================
/// 投票信息
struct Vote {
/// 投票ID
vote_id: Hash,
/// 提案ID
proposal_id: Hash,
/// 标题
title: String,
/// 描述
description: String,
/// 创建者
creator: Address,
/// 开始时间
start_time: Timestamp,
/// 结束时间
end_time: Timestamp,
/// 赞成票数
votes_for: u256,
/// 反对票数
votes_against: u256,
/// 弃权票数
votes_abstain: u256,
/// 总投票权重
total_weight: u256,
/// 法定人数(基点)
quorum: u16,
/// 通过阈值(基点)
threshold: u16,
/// 投票状态
status: VoteStatus,
/// 投票结果
result: VoteResult,
/// 是否允许委托
allow_delegation: bool
}
/// 投票记录
struct VoteRecord {
/// 投票者
voter: Address,
/// 投票ID
vote_id: Hash,
/// 投票选项
option: VoteOption,
/// 投票权重
weight: u256,
/// 投票时间
timestamp: Timestamp,
/// 是否通过委托
is_delegated: bool,
/// 委托人(如果是委托投票)
delegator: Option
}
/// 委托记录
struct Delegation {
/// 委托人
delegator: Address,
/// 被委托人
delegate: Address,
/// 委托权重
weight: u256,
/// 委托时间
delegated_at: Timestamp,
/// 过期时间(可选)
expires_at: Option
}
/// 投票权重快照
struct WeightSnapshot {
/// 地址
address: Address,
/// 权重
weight: u256,
/// 快照时间
snapshot_at: Timestamp
}
// ============================================================================
// 投票事件
// ============================================================================
/// 投票创建事件
event VoteCreated {
vote_id: Hash,
proposal_id: Hash,
title: String,
creator: Address,
start_time: Timestamp,
end_time: Timestamp,
quorum: u16,
threshold: u16
}
/// 投票提交事件
event VoteCast {
vote_id: Hash,
voter: Address,
option: VoteOption,
weight: u256,
timestamp: Timestamp
}
/// 投票结束事件
event VoteEnded {
vote_id: Hash,
result: VoteResult,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
timestamp: Timestamp
}
/// 委托事件
event DelegationCreated {
delegator: Address,
delegate: Address,
weight: u256,
timestamp: Timestamp
}
/// 取消委托事件
event DelegationRevoked {
delegator: Address,
delegate: Address,
timestamp: Timestamp
}
// ============================================================================
// 投票系统
// ============================================================================
/// 投票系统
certificate VotingSystem {
/// 投票 (vote_id => vote)
let _votes: Map;
/// 投票记录 (vote_id => voter => record)
let _vote_records: Map>;
/// 委托 (delegator => delegate => delegation)
let _delegations: Map>;
/// 权重快照 (vote_id => address => snapshot)
let _weight_snapshots: Map>;
/// 治理代币地址
let _governance_token: Address;
/// 管理员地址
let _admin: Address;
/// 默认法定人数(基点)
let _default_quorum: u16;
/// 默认通过阈值(基点)
let _default_threshold: u16;
/// 最小投票期限(秒)
let _min_voting_period: Duration;
/// 最大投票期限(秒)
let _max_voting_period: Duration;
// ========== 构造函数 ==========
constructor(
governance_token: Address,
default_quorum: u16,
default_threshold: u16,
min_period: Duration,
max_period: Duration
) {
require(!governance_token.is_zero(), "Invalid governance token");
require(default_quorum <= 10000, "Invalid quorum");
require(default_threshold <= 10000, "Invalid threshold");
require(min_period > 0, "Min period must be positive");
require(max_period > min_period, "Max period must be > min period");
self._governance_token = governance_token;
self._admin = msg.sender;
self._default_quorum = default_quorum;
self._default_threshold = default_threshold;
self._min_voting_period = min_period;
self._max_voting_period = max_period;
}
// ========== 投票管理 ==========
/// 创建投票
///
/// # 参数
/// - `proposal_id`: 提案ID
/// - `title`: 标题
/// - `description`: 描述
/// - `duration`: 投票期限(秒)
/// - `quorum`: 法定人数(基点,0表示使用默认值)
/// - `threshold`: 通过阈值(基点,0表示使用默认值)
/// - `allow_delegation`: 是否允许委托
///
/// # 返回
/// - `Hash`: 投票ID
pub fn create_vote(
proposal_id: Hash,
title: String,
description: String,
duration: Duration,
quorum: u16,
threshold: u16,
allow_delegation: bool
) -> Hash {
require(!title.is_empty(), "Title required");
require(duration >= self._min_voting_period, "Duration too short");
require(duration <= self._max_voting_period, "Duration too long");
let final_quorum = if quorum == 0 {
self._default_quorum
} else {
require(quorum <= 10000, "Invalid quorum");
quorum
};
let final_threshold = if threshold == 0 {
self._default_threshold
} else {
require(threshold <= 10000, "Invalid threshold");
threshold
};
// 生成投票ID
let vote_id = self._generate_vote_id(proposal_id, msg.sender);
let start_time = block.timestamp;
let end_time = block.timestamp + duration;
let vote = Vote {
vote_id: vote_id,
proposal_id: proposal_id,
title: title.clone(),
description: description,
creator: msg.sender,
start_time: start_time,
end_time: end_time,
votes_for: 0,
votes_against: 0,
votes_abstain: 0,
total_weight: 0,
quorum: final_quorum,
threshold: final_threshold,
status: VoteStatus::Active,
result: VoteResult::Undecided,
allow_delegation: allow_delegation
};
self._votes[vote_id] = vote;
emit VoteCreated {
vote_id: vote_id,
proposal_id: proposal_id,
title: title,
creator: msg.sender,
start_time: start_time,
end_time: end_time,
quorum: final_quorum,
threshold: final_threshold
};
return vote_id;
}
/// 投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `option`: 投票选项
///
/// # 返回
/// - `bool`: 是否成功
pub fn cast_vote(vote_id: Hash, option: VoteOption) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.start_time, "Vote not started");
require(block.timestamp < vote.end_time, "Vote ended");
// 检查是否已投票
if let Some(records) = self._vote_records.get(vote_id) {
require(!records.contains_key(msg.sender), "Already voted");
}
// 获取投票权重(实际需要查询治理代币余额)
let weight = self._get_voting_weight(msg.sender, vote_id);
require(weight > 0, "No voting power");
// 记录投票
let record = VoteRecord {
voter: msg.sender,
vote_id: vote_id,
option: option,
weight: weight,
timestamp: block.timestamp,
is_delegated: false,
delegator: None
};
if !self._vote_records.contains_key(vote_id) {
self._vote_records[vote_id] = Map::new();
}
self._vote_records[vote_id][msg.sender] = record;
// 更新投票统计
match option {
VoteOption::For => {
vote.votes_for = safe_add(vote.votes_for, weight);
},
VoteOption::Against => {
vote.votes_against = safe_add(vote.votes_against, weight);
},
VoteOption::Abstain => {
vote.votes_abstain = safe_add(vote.votes_abstain, weight);
}
}
vote.total_weight = safe_add(vote.total_weight, weight);
self._votes[vote_id] = vote;
emit VoteCast {
vote_id: vote_id,
voter: msg.sender,
option: option,
weight: weight,
timestamp: block.timestamp
};
return true;
}
/// 结束投票
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `VoteResult`: 投票结果
pub fn end_vote(vote_id: Hash) -> VoteResult {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.end_time, "Vote not ended yet");
// 计算结果
let result = self._calculate_result(vote_id);
vote.status = VoteStatus::Ended;
vote.result = result;
self._votes[vote_id] = vote;
emit VoteEnded {
vote_id: vote_id,
result: result,
votes_for: vote.votes_for,
votes_against: vote.votes_against,
votes_abstain: vote.votes_abstain,
timestamp: block.timestamp
};
return result;
}
/// 取消投票
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `bool`: 是否成功
pub fn cancel_vote(vote_id: Hash) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(
msg.sender == vote.creator || msg.sender == self._admin,
"Not authorized"
);
require(vote.status == VoteStatus::Active, "Vote not active");
vote.status = VoteStatus::Cancelled;
self._votes[vote_id] = vote;
return true;
}
// ========== 委托投票 ==========
/// 委托投票权
///
/// # 参数
/// - `delegate`: 被委托人
/// - `expires_at`: 过期时间(可选)
///
/// # 返回
/// - `bool`: 是否成功
pub fn delegate_vote(
delegate: Address,
expires_at: Option
) -> bool {
require(!delegate.is_zero(), "Invalid delegate");
require(delegate != msg.sender, "Cannot delegate to self");
if let Some(expiry) = expires_at {
require(expiry > block.timestamp, "Invalid expiry time");
}
// 获取委托权重(实际需要查询治理代币余额)
let weight = self._get_base_voting_weight(msg.sender);
require(weight > 0, "No voting power");
let delegation = Delegation {
delegator: msg.sender,
delegate: delegate,
weight: weight,
delegated_at: block.timestamp,
expires_at: expires_at
};
if !self._delegations.contains_key(msg.sender) {
self._delegations[msg.sender] = Map::new();
}
self._delegations[msg.sender][delegate] = delegation;
emit DelegationCreated {
delegator: msg.sender,
delegate: delegate,
weight: weight,
timestamp: block.timestamp
};
return true;
}
/// 撤销委托
///
/// # 参数
/// - `delegate`: 被委托人
///
/// # 返回
/// - `bool`: 是否成功
pub fn revoke_delegation(delegate: Address) -> bool {
require(self._delegations.contains_key(msg.sender), "No delegation");
require(
self._delegations[msg.sender].contains_key(delegate),
"Delegation not found"
);
self._delegations[msg.sender].remove(delegate);
emit DelegationRevoked {
delegator: msg.sender,
delegate: delegate,
timestamp: block.timestamp
};
return true;
}
/// 使用委托权投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `option`: 投票选项
/// - `delegator`: 委托人
///
/// # 返回
/// - `bool`: 是否成功
pub fn cast_delegated_vote(
vote_id: Hash,
option: VoteOption,
delegator: Address
) -> bool {
require(self._votes.contains_key(vote_id), "Vote not found");
let mut vote = self._votes[vote_id];
require(vote.allow_delegation, "Delegation not allowed");
require(vote.status == VoteStatus::Active, "Vote not active");
require(block.timestamp >= vote.start_time, "Vote not started");
require(block.timestamp < vote.end_time, "Vote ended");
// 检查委托
require(self._delegations.contains_key(delegator), "No delegation");
require(
self._delegations[delegator].contains_key(msg.sender),
"Not delegated to you"
);
let delegation = self._delegations[delegator][msg.sender];
// 检查是否过期
if let Some(expiry) = delegation.expires_at {
require(block.timestamp < expiry, "Delegation expired");
}
// 检查委托人是否已投票
if let Some(records) = self._vote_records.get(vote_id) {
require(!records.contains_key(delegator), "Delegator already voted");
}
let weight = delegation.weight;
// 记录投票
let record = VoteRecord {
voter: msg.sender,
vote_id: vote_id,
option: option,
weight: weight,
timestamp: block.timestamp,
is_delegated: true,
delegator: Some(delegator)
};
if !self._vote_records.contains_key(vote_id) {
self._vote_records[vote_id] = Map::new();
}
self._vote_records[vote_id][delegator] = record;
// 更新投票统计
match option {
VoteOption::For => {
vote.votes_for = safe_add(vote.votes_for, weight);
},
VoteOption::Against => {
vote.votes_against = safe_add(vote.votes_against, weight);
},
VoteOption::Abstain => {
vote.votes_abstain = safe_add(vote.votes_abstain, weight);
}
}
vote.total_weight = safe_add(vote.total_weight, weight);
self._votes[vote_id] = vote;
emit VoteCast {
vote_id: vote_id,
voter: delegator,
option: option,
weight: weight,
timestamp: block.timestamp
};
return true;
}
// ========== 查询函数 ==========
/// 获取投票信息
///
/// # 参数
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `Vote`: 投票信息
pub fn get_vote(vote_id: Hash) -> Vote {
require(self._votes.contains_key(vote_id), "Vote not found");
return self._votes[vote_id];
}
/// 获取投票记录
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `voter`: 投票者地址
///
/// # 返回
/// - `Option`: 投票记录
pub fn get_vote_record(vote_id: Hash, voter: Address) -> Option {
return self._vote_records.get(vote_id)
.and_then(|m| m.get(voter));
}
/// 获取委托信息
///
/// # 参数
/// - `delegator`: 委托人
/// - `delegate`: 被委托人
///
/// # 返回
/// - `Option`: 委托信息
pub fn get_delegation(
delegator: Address,
delegate: Address
) -> Option {
return self._delegations.get(delegator)
.and_then(|m| m.get(delegate));
}
/// 获取投票权重
///
/// # 参数
/// - `voter`: 投票者地址
/// - `vote_id`: 投票ID
///
/// # 返回
/// - `u256`: 投票权重
pub fn get_voting_weight(voter: Address, vote_id: Hash) -> u256 {
return self._get_voting_weight(voter, vote_id);
}
/// 检查是否已投票
///
/// # 参数
/// - `vote_id`: 投票ID
/// - `voter`: 投票者地址
///
/// # 返回
/// - `bool`: 是否已投票
pub fn has_voted(vote_id: Hash, voter: Address) -> bool {
return self._vote_records.get(vote_id)
.map(|m| m.contains_key(voter))
.unwrap_or(false);
}
// ========== 内部函数 ==========
/// 生成投票ID
fn _generate_vote_id(proposal_id: Hash, creator: Address) -> Hash {
let mut data = Bytes::new();
data.extend(proposal_id.as_bytes());
data.extend(creator.as_bytes());
data.extend(block.timestamp.to_bytes());
data.extend(tx.hash.as_bytes());
return sha3_384_hash(data);
}
/// 获取基础投票权重(不包括委托)
fn _get_base_voting_weight(voter: Address) -> u256 {
// 实际需要查询治理代币余额
// 这里简化处理
return 100;
}
/// 获取投票权重(包括委托)
fn _get_voting_weight(voter: Address, vote_id: Hash) -> u256 {
// 检查是否有快照
if let Some(snapshots) = self._weight_snapshots.get(vote_id) {
if let Some(snapshot) = snapshots.get(voter) {
return snapshot.weight;
}
}
// 获取基础权重
let base_weight = self._get_base_voting_weight(voter);
// 计算委托给该投票者的权重
let mut delegated_weight = 0u256;
// 实际需要遍历所有委托记录
// 这里简化处理
return safe_add(base_weight, delegated_weight);
}
/// 计算投票结果
fn _calculate_result(vote_id: Hash) -> VoteResult {
let vote = self._votes[vote_id];
// 检查法定人数
// 实际需要查询治理代币总供应量
let total_supply = 10000u256; // 简化
let participation = safe_mul(vote.total_weight, 10000) / total_supply;
if participation < vote.quorum as u256 {
return VoteResult::QuorumNotReached;
}
// 计算赞成票比例
let valid_votes = safe_add(vote.votes_for, vote.votes_against);
if valid_votes == 0 {
return VoteResult::Failed;
}
let approval_rate = safe_mul(vote.votes_for, 10000) / valid_votes;
if approval_rate >= vote.threshold as u256 {
return VoteResult::Passed;
} else {
return VoteResult::Failed;
}
}
// ========== 管理函数 ==========
/// 设置默认法定人数
pub fn set_default_quorum(quorum: u16) -> bool {
require(msg.sender == self._admin, "Only admin");
require(quorum <= 10000, "Invalid quorum");
self._default_quorum = quorum;
return true;
}
/// 设置默认通过阈值
pub fn set_default_threshold(threshold: u16) -> bool {
require(msg.sender == self._admin, "Only admin");
require(threshold <= 10000, "Invalid threshold");
self._default_threshold = threshold;
return true;
}
}