Skip to content

代币权益证明系统

代币权益证明系统是一种基于代币持有量进行权益分配和验证的机制,用于实现去中心化的共识和治理。本教程将介绍如何实现一个安全可靠的权益证明系统。

功能特性

  • 质押机制
  • 验证者管理
  • 奖励分配
  • 惩罚机制
  • 委托机制

合约实现

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

/**
 * @title ProofOfStake
 * @dev 权益证明合约实现
 */
contract ProofOfStake is Ownable, ReentrancyGuard {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // 验证者信息
    struct Validator {
        uint256 stake;              // 质押数量
        uint256 rewards;            // 累计奖励
        uint256 lastRewardBlock;    // 上次领取奖励区块
        uint256 delegatedStake;     // 委托质押总量
        bool isActive;              // 是否激活
        bool isJailed;              // 是否被惩罚
    }

    // 委托信息
    struct Delegation {
        uint256 stake;              // 委托数量
        uint256 rewards;            // 累计奖励
        uint256 lastRewardBlock;    // 上次领取奖励区块
    }

    // 质押配置
    struct StakingConfig {
        uint256 minValidatorStake;   // 最小验证者质押量
        uint256 minDelegationStake;  // 最小委托质押量
        uint256 maxValidators;       // 最大验证者数量
        uint256 validatorCommission; // 验证者佣金比例
        uint256 unbondingTime;       // 解绑时间
        uint256 slashingRate;        // 惩罚比例
    }

    // 状态变量
    IERC20 public stakingToken;                          // 质押代币
    mapping(address => Validator) public validators;      // 验证者映射
    mapping(address => mapping(address => Delegation)) public delegations;  // 委托映射
    address[] public validatorSet;                       // 验证者集合
    StakingConfig public config;                         // 质押配置
    uint256 public totalStaked;                          // 总质押量
    uint256 public epochNumber;                          // 当前周期
    uint256 public epochBlocks;                          // 周期区块数
    uint256 public rewardPerBlock;                       // 每区块奖励

    // 解绑请求
    struct UnbondingRequest {
        uint256 amount;             // 解绑数量
        uint256 completionTime;     // 完成时间
    }
    mapping(address => UnbondingRequest[]) public unbondingRequests;

    // 事件
    event ValidatorRegistered(address indexed validator, uint256 stake);
    event ValidatorUpdated(address indexed validator, uint256 stake);
    event ValidatorRemoved(address indexed validator);
    event Delegated(address indexed delegator, address indexed validator, uint256 amount);
    event Undelegated(address indexed delegator, address indexed validator, uint256 amount);
    event RewardsClaimed(address indexed account, uint256 amount);
    event ValidatorSlashed(address indexed validator, uint256 amount);
    event EpochCompleted(uint256 indexed epochNumber);

    /**
     * @dev 构造函数
     */
    constructor(
        address _stakingToken,
        uint256 _epochBlocks,
        uint256 _rewardPerBlock,
        uint256 _minValidatorStake,
        uint256 _minDelegationStake,
        uint256 _maxValidators,
        uint256 _validatorCommission,
        uint256 _unbondingTime,
        uint256 _slashingRate
    ) {
        stakingToken = IERC20(_stakingToken);
        epochBlocks = _epochBlocks;
        rewardPerBlock = _rewardPerBlock;

        config = StakingConfig({
            minValidatorStake: _minValidatorStake,
            minDelegationStake: _minDelegationStake,
            maxValidators: _maxValidators,
            validatorCommission: _validatorCommission,
            unbondingTime: _unbondingTime,
            slashingRate: _slashingRate
        });
    }

    /**
     * @dev 注册成为验证者
     */
    function registerValidator(uint256 _stake) external nonReentrant {
        require(_stake >= config.minValidatorStake, "Stake too low");
        require(!validators[msg.sender].isActive, "Already registered");
        require(validatorSet.length < config.maxValidators, "Max validators reached");

        stakingToken.safeTransferFrom(msg.sender, address(this), _stake);

        validators[msg.sender] = Validator({
            stake: _stake,
            rewards: 0,
            lastRewardBlock: block.number,
            delegatedStake: 0,
            isActive: true,
            isJailed: false
        });

        validatorSet.push(msg.sender);
        totalStaked = totalStaked.add(_stake);

        emit ValidatorRegistered(msg.sender, _stake);
    }

    /**
     * @dev 增加验证者质押
     */
    function addValidatorStake(uint256 _amount) external nonReentrant {
        require(validators[msg.sender].isActive, "Not a validator");
        require(!validators[msg.sender].isJailed, "Validator jailed");

        stakingToken.safeTransferFrom(msg.sender, address(this), _amount);

        validators[msg.sender].stake = validators[msg.sender].stake.add(_amount);
        totalStaked = totalStaked.add(_amount);

        emit ValidatorUpdated(msg.sender, validators[msg.sender].stake);
    }

    /**
     * @dev 委托质押
     */
    function delegate(address _validator, uint256 _amount) external nonReentrant {
        require(validators[_validator].isActive, "Validator not active");
        require(!validators[_validator].isJailed, "Validator jailed");
        require(_amount >= config.minDelegationStake, "Stake too low");

        stakingToken.safeTransferFrom(msg.sender, address(this), _amount);

        Delegation storage delegation = delegations[msg.sender][_validator];
        if (delegation.stake == 0) {
            delegation.lastRewardBlock = block.number;
        }

        delegation.stake = delegation.stake.add(_amount);
        validators[_validator].delegatedStake = validators[_validator].delegatedStake.add(_amount);
        totalStaked = totalStaked.add(_amount);

        emit Delegated(msg.sender, _validator, _amount);
    }

    /**
     * @dev 请求解除委托
     */
    function undelegate(address _validator, uint256 _amount) external nonReentrant {
        Delegation storage delegation = delegations[msg.sender][_validator];
        require(delegation.stake >= _amount, "Insufficient stake");

        // 更新委托信息
        delegation.stake = delegation.stake.sub(_amount);
        validators[_validator].delegatedStake = validators[_validator].delegatedStake.sub(_amount);
        totalStaked = totalStaked.sub(_amount);

        // 创建解绑请求
        unbondingRequests[msg.sender].push(UnbondingRequest({
            amount: _amount,
            completionTime: block.timestamp.add(config.unbondingTime)
        }));

        emit Undelegated(msg.sender, _validator, _amount);
    }

    /**
     * @dev 完成解绑
     */
    function completeUnbonding() external nonReentrant {
        UnbondingRequest[] storage requests = unbondingRequests[msg.sender];
        uint256 totalAmount = 0;
        uint256 completedCount = 0;

        for (uint256 i = 0; i < requests.length; i++) {
            if (requests[i].completionTime <= block.timestamp) {
                totalAmount = totalAmount.add(requests[i].amount);
                completedCount++;
            } else {
                break;
            }
        }

        require(totalAmount > 0, "No completed unbonding");

        // 移除已完成的请求
        if (completedCount > 0) {
            for (uint256 i = completedCount; i < requests.length; i++) {
                requests[i - completedCount] = requests[i];
            }
            for (uint256 i = 0; i < completedCount; i++) {
                requests.pop();
            }
        }

        // 转账解绑的代币
        stakingToken.safeTransfer(msg.sender, totalAmount);
    }

    /**
     * @dev 计算待领取奖励
     */
    function calculateRewards(address _account, address _validator) public view returns (uint256) {
        Validator storage validator = validators[_validator];
        Delegation storage delegation = delegations[_account][_validator];

        if (delegation.stake == 0) {
            return 0;
        }

        uint256 blocksSinceLastReward = block.number.sub(delegation.lastRewardBlock);
        uint256 totalRewards = blocksSinceLastReward.mul(rewardPerBlock);
        
        uint256 validatorShare = totalRewards.mul(config.validatorCommission).div(100);
        uint256 delegatorShare = totalRewards.sub(validatorShare);
        
        return delegatorShare.mul(delegation.stake).div(validator.delegatedStake);
    }

    /**
     * @dev 领取奖励
     */
    function claimRewards(address _validator) external nonReentrant {
        require(validators[_validator].isActive, "Validator not active");
        
        uint256 rewards = calculateRewards(msg.sender, _validator);
        require(rewards > 0, "No rewards to claim");

        delegations[msg.sender][_validator].lastRewardBlock = block.number;
        delegations[msg.sender][_validator].rewards = delegations[msg.sender][_validator].rewards.add(rewards);

        stakingToken.safeTransfer(msg.sender, rewards);
        emit RewardsClaimed(msg.sender, rewards);
    }

    /**
     * @dev 批量领取奖励
     */
    function batchClaimRewards(address[] calldata _validators) external nonReentrant {
        uint256 totalRewards = 0;

        for (uint256 i = 0; i < _validators.length; i++) {
            address validator = _validators[i];
            if (validators[validator].isActive) {
                uint256 rewards = calculateRewards(msg.sender, validator);
                if (rewards > 0) {
                    delegations[msg.sender][validator].lastRewardBlock = block.number;
                    delegations[msg.sender][validator].rewards = delegations[msg.sender][validator].rewards.add(rewards);
                    totalRewards = totalRewards.add(rewards);
                }
            }
        }

        require(totalRewards > 0, "No rewards to claim");
        stakingToken.safeTransfer(msg.sender, totalRewards);
        emit RewardsClaimed(msg.sender, totalRewards);
    }

    /**
     * @dev 惩罚验证者
     */
    function slashValidator(address _validator) external onlyOwner {
        require(validators[_validator].isActive, "Validator not active");
        require(!validators[_validator].isJailed, "Already jailed");

        uint256 slashAmount = validators[_validator].stake.mul(config.slashingRate).div(100);
        validators[_validator].stake = validators[_validator].stake.sub(slashAmount);
        validators[_validator].isJailed = true;
        totalStaked = totalStaked.sub(slashAmount);

        emit ValidatorSlashed(_validator, slashAmount);
    }

    /**
     * @dev 解除验证者惩罚
     */
    function unjailValidator(address _validator) external onlyOwner {
        require(validators[_validator].isActive, "Validator not active");
        require(validators[_validator].isJailed, "Not jailed");
        validators[_validator].isJailed = false;
    }

    /**
     * @dev 移除验证者
     */
    function removeValidator(address _validator) external onlyOwner {
        require(validators[_validator].isActive, "Validator not active");

        uint256 totalAmount = validators[_validator].stake.add(validators[_validator].delegatedStake);
        validators[_validator].isActive = false;
        totalStaked = totalStaked.sub(totalAmount);

        // 移除验证者集合中的验证者
        for (uint256 i = 0; i < validatorSet.length; i++) {
            if (validatorSet[i] == _validator) {
                validatorSet[i] = validatorSet[validatorSet.length - 1];
                validatorSet.pop();
                break;
            }
        }

        emit ValidatorRemoved(_validator);
    }

    /**
     * @dev 更新质押配置
     */
    function updateConfig(
        uint256 _minValidatorStake,
        uint256 _minDelegationStake,
        uint256 _maxValidators,
        uint256 _validatorCommission,
        uint256 _unbondingTime,
        uint256 _slashingRate
    ) external onlyOwner {
        require(_validatorCommission <= 100, "Invalid commission");
        require(_slashingRate <= 100, "Invalid slashing rate");

        config.minValidatorStake = _minValidatorStake;
        config.minDelegationStake = _minDelegationStake;
        config.maxValidators = _maxValidators;
        config.validatorCommission = _validatorCommission;
        config.unbondingTime = _unbondingTime;
        config.slashingRate = _slashingRate;
    }

    /**
     * @dev 更新每区块奖励
     */
    function updateRewardPerBlock(uint256 _rewardPerBlock) external onlyOwner {
        rewardPerBlock = _rewardPerBlock;
    }

    /**
     * @dev 更新周期区块数
     */
    function updateEpochBlocks(uint256 _epochBlocks) external onlyOwner {
        epochBlocks = _epochBlocks;
    }

    /**
     * @dev 完成周期
     */
    function completeEpoch() external onlyOwner {
        epochNumber = epochNumber.add(1);
        emit EpochCompleted(epochNumber);
    }

    /**
     * @dev 获取验证者信息
     */
    function getValidatorInfo(address _validator) external view returns (
        uint256 stake,
        uint256 rewards,
        uint256 lastRewardBlock,
        uint256 delegatedStake,
        bool isActive,
        bool isJailed
    ) {
        Validator storage validator = validators[_validator];
        return (
            validator.stake,
            validator.rewards,
            validator.lastRewardBlock,
            validator.delegatedStake,
            validator.isActive,
            validator.isJailed
        );
    }

    /**
     * @dev 获取委托信息
     */
    function getDelegationInfo(address _delegator, address _validator) external view returns (
        uint256 stake,
        uint256 rewards,
        uint256 lastRewardBlock
    ) {
        Delegation storage delegation = delegations[_delegator][_validator];
        return (
            delegation.stake,
            delegation.rewards,
            delegation.lastRewardBlock
        );
    }

    /**
     * @dev 获取解绑请求
     */
    function getUnbondingRequests(address _account) external view returns (
        uint256[] memory amounts,
        uint256[] memory completionTimes
    ) {
        UnbondingRequest[] storage requests = unbondingRequests[_account];
        amounts = new uint256[](requests.length);
        completionTimes = new uint256[](requests.length);

        for (uint256 i = 0; i < requests.length; i++) {
            amounts[i] = requests[i].amount;
            completionTimes[i] = requests[i].completionTime;
        }

        return (amounts, completionTimes);
    }

    /**
     * @dev 紧急提取
     */
    function emergencyWithdraw(
        address _token,
        address _to,
        uint256 _amount
    ) external onlyOwner {
        require(_token != address(stakingToken), "Cannot withdraw staking token");
        require(_to != address(0), "Invalid recipient");
        IERC20(_token).safeTransfer(_to, _amount);
    }
}

关键概念

质押机制

质押系统支持:

  • 验证者质押
  • 委托质押
  • 解绑机制
  • 奖励分配

验证者管理

管理功能包括:

  • 注册验证者
  • 更新质押
  • 惩罚机制
  • 解除惩罚

委托机制

委托功能包括:

  • 委托质押
  • 解除委托
  • 奖励计算
  • 奖励领取

安全考虑

  1. 质押安全

    • 最小质押限制
    • 解绑延迟
    • 惩罚机制
    • 权限验证
  2. 奖励安全

    • 奖励计算
    • 分配规则
    • 领取限制
    • 通胀控制
  3. 系统安全

    • 重入防护
    • 权限管理
    • 状态检查
    • 紧急控制
  4. 数据安全

    • 状态同步
    • 数据验证
    • 错误处理
    • 事件记录

最佳实践

  1. 质押管理

    • 合理的最小质押量
    • 适当的解绑期
    • 公平的分配机制
    • 有效的惩罚机制
  2. 验证者管理

    • 严格的准入条件
    • 完善的监控机制
    • 及时的惩罚措施
    • 合理的退出机制
  3. 委托管理

    • 灵活的委托机制
    • 透明的奖励计算
    • 便捷的操作流程
    • 完整的信息展示
  4. 系统维护

    • 定期检查
    • 参数优化
    • 安全审计
    • 升级预案

扩展功能

  1. 动态验证者集
  2. 多层委托机制
  3. 治理投票权重
  4. 自动复投机制
  5. 跨链质押

应用场景

  1. 网络共识

    • 区块验证
    • 交易确认
    • 网络安全
    • 共识达成
  2. 治理参与

    • 提案投票
    • 参数调整
    • 协议升级
    • 社区决策
  3. 经济激励

    • 质押收益
    • 通胀分配
    • 生态建设
    • 长期发展

总结

权益证明系统是区块链网络的重要组成部分。通过本教程,你可以:

  • 实现完整的质押机制
  • 确保系统安全性
  • 优化用户体验
  • 促进网络发展

常见问题解答(FAQ)

基础概念

Q: 什么是权益证明(PoS)?

A: 权益证明是一种共识机制,主要特点包括:

  • 基于代币质押
  • 验证者选举
  • 奖励分配
  • 惩罚机制
  • 委托机制

Q: 验证者和委托者有什么区别?

A: 主要区别包括:

  • 验证者运行节点,委托者只需质押
  • 验证者需满足最小质押要求
  • 验证者承担更多责任和风险
  • 验证者可获得佣金收入
  • 委托者门槛较低

操作相关

Q: 如何成为验证者?

A: 成为验证者的步骤包括:

  • 准备足够质押代币
  • 部署验证节点
  • 注册验证者身份
  • 等待激活确认
  • 开始验证工作

Q: 如何进行委托质押?

A: 委托质押步骤包括:

  • 选择可靠验证者
  • 准备质押代币
  • 授权合约使用
  • 执行委托操作
  • 等待确认生效

安全相关

Q: PoS系统有哪些风险?

A: 主要风险包括:

  • 验证者作恶
  • 网络攻击
  • 代币价格波动
  • 质押代币锁定
  • 惩罚损失

Q: 如何确保系统安全?

A: 安全措施包括:

  • 多重验证机制
  • 惩罚机制
  • 锁定期设置
  • 权益分散
  • 监控预警

Released under the MIT License by Vogeb.