Dapp TokenFarm开发(5)---合约开发
2.4 空投代币
2.4.0 编写合约
给TokenFarm.sol 添加如下空投函数
// 3.空投代币
function issueTokens() public {
// 要求必须为合约拥有者才能空投代币
require(msg.sender == owner, "caller must be the owner");
// 给所有质押过的用户空投
for (uint256 i = 0; i < stackers.length; i++) {
address recipient = stackers[i];
uint balance = stakingBalance[recipient];
if (balance > 0){
dappToken.transfer(recipient, balance);
}
}
}
2.4.1 编写测试
继续编写,测试添加如下代码
// 空投代币
await tokenFarm.issueTokens({ from: owner })
// 检查用户余额
result = await dappToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor Dapp Tokens balance correst after staking')
// 确保只有拥有者能调用空投函数
await tokenFarm.issueTokens({ from: investor }).should.be.rejected;
2.4.2 测试
继续在终端修改,并测试
truffle migrate
truffle test
如下再度大成功!!!!!!!!!!!

2.5.3 封装空投代币函数
在根目录创建一个 scripts 文件夹在里面创建一个 issue-token.js
const TokenFarm = artifacts.require('TokenFarm')
module.exports =async function(callback) {
let tokenFarm = await TokenFarm.deployed()
await tokenFarm.issueTokens()
console.log("Tokens issued!")
callback()
};
继续在终端修改,获取uri,并测试
truffle compile
truffle migrate
truffle test
truffle exec scripts/issue-token.js
如下成功空投

2.5 取出代币(最终代码)
2.5.0 编写合约
TokenFarm 添加如下函数
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm {
string public name = "Dapp Token Farm";
DappToken public dappToken; // 合约 A
DaiToken public daiToken; // 合约 B
address public owner; // 合约拥有者
address[] public stackers; // 质押过的名单(用于空投代币)
mapping(address => uint256) public stakingBalance; // 正在质押总量
mapping(address => bool) public hasStaked; // 已经质押过的地址
mapping(address => bool) public isStaking; // 正在质押的地址
// 构造函数 仅在代码部署的时候执行一次,部署完成无法再执行
constructor(DappToken _dappToken, DaiToken _daiToken) public {
dappToken = _dappToken; // 保存合约
daiToken = _daiToken; // 保存合约
owner = msg.sender; // 部署合约的时候设定拥有者
// 该用户在合约中有一定的权限
}
// 1.质押代币
function stakeTokens(uint _amount) public {
// 要求质押的代币大于0
require(_amount > 0,"amount cannot be 0");
daiToken.transferFrom(msg.sender, address(this), _amount);
// 更新质押数量
stakingBalance[msg.sender] += _amount;
// 更新已经质押过的名单
if(!hasStaked[msg.sender]){
stackers.push(msg.sender);
}
// 更新是否正在质押
hasStaked[msg.sender] = true;
isStaking[msg.sender] = true;
}
// 2.取出质押的代币
function unstakeTokens() public {
// 获取正在质押的总数
uint balance = stakingBalance[msg.sender];
// 要求正在质押总量大于0
require(balance > 0, "staking banlance cannot be 0");
// 将 DAI 发送回用户地址
daiToken.transfer(msg.sender,balance);
// 更新用户设置质押数量
stakingBalance[msg.sender] = 0;
// 更新用户质押状态
isStaking[msg.sender] = false;
}
// 3.空投代币
function issueTokens() public {
// 要求必须为合约拥有者才能空投代币
require(msg.sender == owner, "caller must be the owner");
// 给所有质押过的用户空投
for (uint256 i = 0; i < stackers.length; i++) {
address recipient = stackers[i];
uint balance = stakingBalance[recipient];
if (balance > 0){
dappToken.transfer(recipient, balance);
}
}
}
}
2.5.1 编写测试
添加 取出质押代币的测试
const { assert } = require('chai');
const TokenFarm = artifacts.require("TokenFarm");
const DappToken = artifacts.require("DappToken");
const DaiToken = artifacts.require("DaiToken");
require('chai').use(require('chai-as-promised')).should()
function tokens(n) {
// 用作数值转换 100 ether => 1*10^20 wei
// 1ether = 10^18
return web3.utils.toWei(n, 'Ether')
}
contract('TokenFarm', ([owner, investor]) => {
let daiToken, dappToken, tokenFarm
before(async () => {
// 加载合约
daiToken = await DaiToken.new()
dappToken = await DappToken.new()
tokenFarm = await TokenFarm.new(dappToken.address, daiToken.address)
// 把所有的代币发送给tokenFarm
await dappToken.transfer(tokenFarm.address, tokens('1000000'))
// 发送100 给代币到用户
await daiToken.transfer(investor, tokens('100'), { from: owner })
})
// 测试 daiToken 合约 name 属性 返回值是否为 'Mock DAI Token'
describe('Mock Dai deployment', async () => {
it('has a name', async () => {
const name = await daiToken.name()
assert.equal(name, 'Mock DAI Token')
})
})
// 测试 DappToken 合约 name 属性 返回值是否为 'Dapp Token'
describe('Dapp Token deployment', async () => {
it('has a name', async () => {
const name = await dappToken.name()
assert.equal(name, 'DApp Token')
})
})
// 测试 DappToken 合约 name 属性 返回值是否为 'Dapp Token Farm'
describe('Token Farm deployment', async () => {
it('has a name', async () => {
const name = await tokenFarm.name()
assert.equal(name, 'Dapp Token Farm')
})
// 测试tokenFarm 地址 是否有1000000*10^18 个 dappToken
it('contract has tokens', async () => {
let balance = await dappToken.balanceOf(tokenFarm.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
describe("Farming tokens", async () => {
it('rewards investors for staking mDai tokens', async () => {
let result
// 检查用户是否有100个 DAI
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor mDAI wallet balance correst before staking')
// 用户授权100个 DAI,并质押到 TokenFarm
await daiToken.approve(tokenFarm.address, tokens('100'), { from: investor })
await tokenFarm.stakeTokens(tokens('100'), { from: investor })
// 查询用户 DAI 余额是否为0
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('0'), 'investor mDAI wallet balance correst before staking')
// 检查 TokenFarm 地址是否有100个 DAI
result = await daiToken.balanceOf(tokenFarm.address)
assert.equal(result.toString(), tokens('100'), 'TokenFarm mDAI wallet balance correst before staking')
// 检查用户是否在 TokenFarm 质押 100 个 DAI
result = await tokenFarm.stakingBalance(investor)
assert.equal(result.toString(), tokens('100'), 'investor staking balance correst after staking')
// 检查用户是否在质押
result = await tokenFarm.isStaking(investor)
assert.equal(result.toString(), 'true', 'investor staking status correst after staking')
// 空投代币
await tokenFarm.issueTokens({ from: owner })
// 检查用户余额
result = await dappToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor Dapp Tokens balance correst after staking')
// 确保只有拥有者能调用空投函数
await tokenFarm.issueTokens({ from: investor }).should.be.rejected;
// 取出质押的代币 DAI
await tokenFarm.unstakeTokens({ from: investor })
// 检查用户 DAI 余额
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor Mock Dai balance correst after staking')
// 检查 TokenFarm 地址的 DAI 余额
result = await daiToken.balanceOf(tokenFarm.address)
assert.equal(result.toString(), tokens('0'), 'tokenFarm Mock Dai balance correst after staking')
// 检查用户正在质押的DAI 余额
result = await tokenFarm.stakingBalance(investor)
assert.equal(result.toString(), tokens('0'), 'tokenFarm Mock Dai balance correst after staking')
// 检查用户是否正在质押
result = await tokenFarm.isStaking(investor)
assert.equal(result.toString(), "false", 'tokenFarm status correst after staking')
})
})
})
2.5.2 测试
继续在终端修改,并测试
truffle migrate
truffle test
成功,我们的合约完成了

浙公网安备 33010602011771号