Dapp TokenFarm开发(4)---合约开发
2.2 构造函数
2.2.0 添加合约属性
修改 TokenFarm.sol 合约
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; // 合约拥有着
// 构造函数 仅在代码部署的时候执行一次,部署完成无法再执行
constructor(DappToken _dappToken, DaiToken _daiToken) public {
dappToken = _dappToken; // 保存合约
daiToken = _daiToken; // 保存合约
owner = msg.sender; // 部署合约的时候记录交易发送者(即为拥有者)
// 该用户在合约中有一定的权限
}
}
2.2.1 修改部署参数
修改 migrations/2_deploy_contracts.js
const TokenFarm = artifacts.require("TokenFarm");
const DappToken = artifacts.require("DappToken");
const DaiToken = artifacts.require("DaiToken");
module.exports =async function(deployer,network,accounts) {
await deployer.deploy(DaiToken)
const daiToken = await DaiToken.deployed()
await deployer.deploy(DappToken)
const dappToken = await DappToken.deployed()
// 按照合约参数顺序dappToken.address,daiToken.address (传入构造函数需要的参数要放在 TokenFarm 后面)
await deployer.deploy(TokenFarm,dappToken.address,daiToken.address)
const tokenFarm = await TokenFarm.deployed()
// 发送 1000000 个 dappToken 给 TokenFarm
await dappToken.transfer(tokenFarm.address,'1000000000000000000000000')
// 发送 100 个 DAI 给 账号1(用户)
await daiToken.transfer(accounts[1],'100000000000000000000')
};
注意,这个accounts 为 Ganache 的地址列表
accounts[1] 为如下index1 账号 0x33e8......4f9d

2.2.2 测试
在测试中添加一个 ether -> wei 转换函数
1 ether === 10^18 wei
function tokens(n) {
// 用作数值转换 100 ether => 1*10^20 wei
// 1ether = 10^18
return web3.utils.toWei(n, 'Ether')
}
最终代码如下
注意 Token 部署合约中添加了地址参数
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'))
})
})
}
)
终端输入
truffle migrate
// 迁移合约
truffle test
// 测试
如下测试成功

2.3 质押代币
2.3.0 编写合约
继续编写 TokenFarm.sol 合约
如下添加质押代币所需的属性及属性及函数 stakeTokens()
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.3.1 编写测试
TokenFarm.test.js 添加如屑测试代码
// ... 省略代码
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')
})
})
2.3.2 测试
继续在终端修改,并测试
truffle migrate
truffle test
如下大成功!!!!!!!!!!!

浙公网安备 33010602011771号