代币治理系统
代币治理系统是去中心化项目的核心组件,用于实现基于代币的民主决策机制。本教程将介绍如何实现一个完整的代币治理系统。
功能特性
- 提案创建和管理
- 投票权重计算
- 投票委托机制
- 提案执行系统
- 时间锁定机制
合约实现
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
/**
* @title TokenGovernance
* @dev 代币治理合约实现
*/
contract TokenGovernance is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using Counters for Counters.Counter;
// 提案状态枚举
enum ProposalState {
Pending, // 等待中
Active, // 活跃
Canceled, // 已取消
Defeated, // 已失败
Succeeded, // 已成功
Queued, // 已排队
Expired, // 已过期
Executed // 已执行
}
// 提案结构
struct Proposal {
uint256 id; // 提案ID
address proposer; // 提案人
address[] targets; // 目标合约地址
uint256[] values; // 调用金额
bytes[] calldatas; // 调用数据
uint256 startBlock; // 开始区块
uint256 endBlock; // 结束区块
uint256 forVotes; // 赞成票
uint256 againstVotes; // 反对票
uint256 abstainVotes; // 弃权票
bool canceled; // 是否取消
bool executed; // 是否执行
mapping(address => Receipt) receipts; // 投票记录
}
// 投票记录结构
struct Receipt {
bool hasVoted; // 是否已投票
uint8 support; // 投票支持类型
uint256 votes; // 投票数量
}
// 投票配置
struct VotingConfig {
uint256 proposalThreshold; // 提案门槛
uint256 votingDelay; // 投票延迟
uint256 votingPeriod; // 投票期
uint256 quorumNumerator; // 法定人数比例
}
// 状态变量
IERC20 public token; // 治理代币
VotingConfig public config; // 投票配置
Counters.Counter private proposalCount; // 提案计数器
mapping(uint256 => Proposal) public proposals; // 提案映射
mapping(address => address) public delegates; // 委托映射
mapping(address => uint256) public checkpoints; // 投票权重检查点
// 事件
event ProposalCreated(
uint256 indexed proposalId,
address indexed proposer,
address[] targets,
uint256[] values,
bytes[] calldatas,
uint256 startBlock,
uint256 endBlock,
string description
);
event ProposalCanceled(uint256 indexed proposalId);
event ProposalExecuted(uint256 indexed proposalId);
event VoteCast(
address indexed voter,
uint256 indexed proposalId,
uint8 support,
uint256 weight,
string reason
);
event DelegateChanged(
address indexed delegator,
address indexed fromDelegate,
address indexed toDelegate
);
/**
* @dev 构造函数
*/
constructor(
address _token,
uint256 _proposalThreshold,
uint256 _votingDelay,
uint256 _votingPeriod,
uint256 _quorumNumerator
) {
require(_token != address(0), "Invalid token address");
require(_quorumNumerator <= 100, "Invalid quorum numerator");
token = IERC20(_token);
config = VotingConfig({
proposalThreshold: _proposalThreshold,
votingDelay: _votingDelay,
votingPeriod: _votingPeriod,
quorumNumerator: _quorumNumerator
});
}
/**
* @dev 创建提案
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) external returns (uint256) {
require(
getVotes(msg.sender) >= config.proposalThreshold,
"Insufficient votes"
);
require(
targets.length == values.length &&
targets.length == calldatas.length,
"Invalid proposal"
);
uint256 proposalId = proposalCount.current();
proposalCount.increment();
Proposal storage proposal = proposals[proposalId];
proposal.id = proposalId;
proposal.proposer = msg.sender;
proposal.targets = targets;
proposal.values = values;
proposal.calldatas = calldatas;
proposal.startBlock = block.number.add(config.votingDelay);
proposal.endBlock = proposal.startBlock.add(config.votingPeriod);
emit ProposalCreated(
proposalId,
msg.sender,
targets,
values,
calldatas,
proposal.startBlock,
proposal.endBlock,
description
);
return proposalId;
}
/**
* @dev 投票
*/
function castVote(
uint256 proposalId,
uint8 support,
string memory reason
) external {
require(state(proposalId) == ProposalState.Active, "Voting is closed");
require(support <= 2, "Invalid vote type");
Proposal storage proposal = proposals[proposalId];
Receipt storage receipt = proposal.receipts[msg.sender];
require(!receipt.hasVoted, "Already voted");
uint256 votes = getVotes(msg.sender);
receipt.hasVoted = true;
receipt.support = support;
receipt.votes = votes;
if (support == 0) {
proposal.againstVotes = proposal.againstVotes.add(votes);
} else if (support == 1) {
proposal.forVotes = proposal.forVotes.add(votes);
} else {
proposal.abstainVotes = proposal.abstainVotes.add(votes);
}
emit VoteCast(msg.sender, proposalId, support, votes, reason);
}
/**
* @dev 执行提案
*/
function execute(uint256 proposalId) external payable {
require(
state(proposalId) == ProposalState.Succeeded,
"Proposal not succeeded"
);
Proposal storage proposal = proposals[proposalId];
proposal.executed = true;
for (uint256 i = 0; i < proposal.targets.length; i++) {
(bool success, ) = proposal.targets[i].call{value: proposal.values[i]}(
proposal.calldatas[i]
);
require(success, "Proposal execution failed");
}
emit ProposalExecuted(proposalId);
}
/**
* @dev 取消提案
*/
function cancel(uint256 proposalId) external {
require(
state(proposalId) != ProposalState.Executed,
"Cannot cancel executed proposal"
);
Proposal storage proposal = proposals[proposalId];
require(
msg.sender == proposal.proposer ||
getVotes(proposal.proposer) < config.proposalThreshold,
"Cannot cancel"
);
proposal.canceled = true;
emit ProposalCanceled(proposalId);
}
/**
* @dev 委托投票权
*/
function delegate(address delegatee) external {
address currentDelegate = delegates[msg.sender];
delegates[msg.sender] = delegatee;
emit DelegateChanged(msg.sender, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, getVotes(msg.sender));
}
/**
* @dev 获取提案状态
*/
function state(uint256 proposalId) public view returns (ProposalState) {
Proposal storage proposal = proposals[proposalId];
if (proposal.canceled) {
return ProposalState.Canceled;
}
if (proposal.executed) {
return ProposalState.Executed;
}
uint256 currentBlock = block.number;
if (currentBlock < proposal.startBlock) {
return ProposalState.Pending;
}
if (currentBlock <= proposal.endBlock) {
return ProposalState.Active;
}
if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
return ProposalState.Succeeded;
}
return ProposalState.Defeated;
}
/**
* @dev 获取投票权重
*/
function getVotes(address account) public view returns (uint256) {
return token.balanceOf(account);
}
/**
* @dev 检查是否达到法定人数
*/
function _quorumReached(uint256 proposalId) internal view returns (bool) {
Proposal storage proposal = proposals[proposalId];
uint256 totalSupply = token.totalSupply();
uint256 quorum = totalSupply.mul(config.quorumNumerator).div(100);
return proposal.forVotes.add(proposal.againstVotes) >= quorum;
}
/**
* @dev 检查提案是否通过
*/
function _voteSucceeded(uint256 proposalId) internal view returns (bool) {
Proposal storage proposal = proposals[proposalId];
return proposal.forVotes > proposal.againstVotes;
}
/**
* @dev 移动委托投票权
*/
function _moveDelegates(
address srcRep,
address dstRep,
uint256 amount
) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
checkpoints[srcRep] = checkpoints[srcRep].sub(amount);
}
if (dstRep != address(0)) {
checkpoints[dstRep] = checkpoints[dstRep].add(amount);
}
}
}
/**
* @dev 更新投票配置(仅管理员)
*/
function updateVotingConfig(
uint256 _proposalThreshold,
uint256 _votingDelay,
uint256 _votingPeriod,
uint256 _quorumNumerator
) external onlyOwner {
require(_quorumNumerator <= 100, "Invalid quorum numerator");
config.proposalThreshold = _proposalThreshold;
config.votingDelay = _votingDelay;
config.votingPeriod = _votingPeriod;
config.quorumNumerator = _quorumNumerator;
}
}
关键概念
提案机制
提案系统支持:
- 提案创建
- 状态管理
- 执行机制
- 取消功能
投票机制
投票系统包括:
- 权重计算
- 委托投票
- 投票记录
- 结果统计
权限控制
权限管理:
- 提案权限
- 投票权限
- 执行权限
- 管理权限
安全考虑
提案安全
- 门槛验证
- 执行检查
- 时间控制
- 状态保护
投票安全
- 权重验证
- 重复投票检查
- 委托安全
- 结果计算
执行安全
- 权限验证
- 执行超时
- 回滚处理
- 状态同步
系统安全
- 参数限制
- 数据验证
- 异常处理
- 升级保护
最佳实践
提案管理
- 合理的门槛
- 充分的讨论期
- 适当的投票期
- 明确的执行机制
投票设计
- 公平的权重
- 灵活的委托
- 透明的记录
- 可靠的统计
系统维护
- 参数优化
- 数据监控
- 异常处理
- 升级规划
社区参与
- 提案引导
- 投票激励
- 结果公示
- 执行监督
扩展功能
- 多签名治理
- 分级投票权
- 提案激励
- 自动执行
- 治理代币
应用场景
协议治理
- 参数调整
- 升级决策
- 资金分配
- 战略规划
社区管理
- 提案管理
- 投票管理
- 执行监督
- 权益分配
项目发展
- 路线决策
- 资源分配
- 合作审批
- 风险控制
总结
代币治理系统是去中心化项目的重要基础。通过本教程,你可以:
- 实现民主决策机制
- 保障社区权益
- 促进有效治理
- 推动项目发展
常见问题解答(FAQ)
基础概念
Q: 什么是代币治理?
A: 代币治理是一种社区自治机制,主要特点包括:
- 社区参与决策
- 代币投票权重
- 提案管理系统
- 自动化执行
- 透明公平治理
Q: 治理机制有哪些类型?
A: 主要类型包括:
- 直接民主型
- 代表制型
- 混合治理型
- 分层治理型
- 专业委员会型
操作相关
Q: 如何参与代币治理?
A: 参与步骤包括:
- 持有治理代币
- 查看治理提案
- 参与投票表决
- 跟踪提案执行
- 监督治理过程
Q: 如何优化治理效果?
A: 优化方法包括:
- 完善提案机制
- 优化投票流程
- 提高参与度
- 加强透明度
- 保持社区活力
安全相关
Q: 治理机制有哪些风险?
A: 主要风险包括:
- 投票操纵
- 治理攻击
- 提案滥用
- 执行延迟
- 社区分裂
Q: 如何确保治理安全?
A: 安全措施包括:
- 多重签名控制
- 投票锁定机制
- 提案门槛设置
- 延迟执行期
- 紧急暂停机制