# solidity教程:从零开始写质押挖矿合约（一）:需求整理

By [daxiong](https://paragraph.com/@daxiong) · 2022-02-12

---

> 质押合约的算法，之前的文章已经推到过，本文在此基础上进行开发。
> 
> 本文使用truffle框架进行开发，truffle的基础用法不再赘述，可以查阅官方文档。

在着手开始编写一个智能合约之前，首先要了解需求，进行合约开发设计。

Step1：了解需求，明白该合约要实现哪些功能。
------------------------

1、将token转入合约进行质押；

2、解除质押并且token转出合约；

3、计算挖矿收益，挖矿算法是：没分钟产出10个奖励；

4、奖励提现；

5、查看某个地址的质押份额；

所以梳理出以下方法：

1、stake(uint256 \_amount)：质押,【外部调用/所有人/不需要支付/读写状态】

2、unStake(uint256 \_amount)：解除质押，提取token,【外部调用/所有人/不需要支付/读写状态】

3、getReward()：获取挖矿收益,【内部调用/合约创建者/不需要支付/只读】

4、withdraw(uint256 \_amount)：提现收益,【外部调用/所有人/不需要支付/读写】

5、getShare(address \_addr)：获取某地址质押份额,【外部调用/所有人/不需要支付/只读】

Step2：根据合约和方法的业务逻辑梳理出属性：
------------------------

1、质押合约基础属性：质押代币地址、质押奖励token的地址、每分钟产出奖励数量

2、getShare方法，需要获取每个地址的质押份额

3、withdraw方法，需要存储每个地址已经提现的奖励

4、挖矿算法，需要记录每个地址最近一次的每份额累计奖励 以及 每个地址最近一次的累计收益 以及 每份额累计总奖励

5、总挖矿奖励数量

所以梳理出以下属性：

质押代币地址：address stakeTokenAddr 【公共】

质押奖励token地址：address rewardTokenAddr 【公共】

每分钟产出奖励数量：uint256 rewardPerMin 【公共】

每个地址的质押份额：mapping(address => uint256) shares【私有】

每个地址已经提现的奖励：mapping(address => uint256) withdrawdReward【私有】

每个地址最近一次的每份额累计奖励：mapping(address => uint256) lastAddUpRewardPerShare【私有】

每个地址最近一次的累计总奖励：mapping(address => uint256) lastAddUpReward【私有】

每份额累计奖励：uint256 addUpRewardPerShare【公共】

总挖矿奖励数量：totalReward【公共】

Step3：综上所属，当前合约代码为：
-------------------

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    import "@openzeppelin/contracts/access/Ownable.sol";
    
    contract Pool  is Ownable {
    
        //质押代币地址
        address stakeTokenAddr;
        //质押奖励token地址
        address rewardTokenAddr;
        //每分钟产出奖励数量
        uint256 rewardPerMin;
        //每个地址的质押份额
        mapping(address => uint256) private shares;
        //每个地址已经提现的奖励
        mapping(address => uint256) private withdrawdReward;
        //每个地址最近一次的每份额累计奖励
        mapping(address => uint256) private lastAddUpRewardPerShare;
        //每个地址最近一次的累计总奖励
        mapping(address => uint256) private lastAddUpReward;
        //每份额累计奖励
        uint256 addUpRewardPerShare;
        //总挖矿奖励数量
        uint256 totalReward;
    
        //质押,【外部调用/所有人/不需要支付/读写状态】
        function stake(uint256 _amount) external {} 
    
        //解除质押，提取token,【外部调用/所有人/不需要支付/读写状态】
        function unStake(uint256 _amount) external {}
    
        //获取挖矿收益,【内部调用/合约创建者/不需要支付/只读】
        function getReward() internal view onlyOwner {}
    
        //提现收益,【外部调用/所有人/不需要支付/读写】
        function withdraw(uint256 _amount) external {}
    
        //获取某地址质押份额,【外部调用/所有人/不需要支付/只读】
        function getShare(address _addr) external view {}
    
    }

---

*Originally published on [daxiong](https://paragraph.com/@daxiong/solidity-3)*
