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

如下大成功!!!!!!!!!!!

posted @ 2022-05-26 16:56  Jerrvis  阅读(72)  评论(0)    收藏  举报