繁体   English   中英

如何运行一个成功的 Solidity 智能合约测试脚本?

[英]How To Run A Successful Solidity Smart Contract Test Script?

我一直在关注Dapp 大学Gregory 的这篇关于如何创建自己的 ERC20 代币以及一个众筹智能合约的教程 到目前为止,我已经成功了,但是我被困在需要使 buytokens() 函数工作的地方,以便可以将代币从众售合同的地址转移到买方的地址。 我即将展示的测试使用了 async/await 模式,与视频教程中的不同。 您可以在下面找到代码

  • 我的 ERC20 代币合约
  • 我的众筹合同及其测试脚本(特别是失败的部分)
  • 部署脚本
  • 最后是我运行测试时遇到的错误

谢谢你的帮助。

开发环境

Truffle v5.4.18 (core: 5.4.18)
Solidity - 0.8.9 (solc-js)
Node v16.1.0
Web3.js v1.5.3

众售合约

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;

import "./NzouaToken.sol";

contract NzouaTokenSale {

    address admin;
    NzouaToken public tokenContract;
    uint256 public tokenPrice;
    uint256 public tokensSold;

    event Sell(address _buyer, uint256 _amount);

    constructor(NzouaToken _tokenContract, uint256 _tokenPrice) {

        admin = msg.sender;
        tokenContract = _tokenContract;
        tokenPrice = _tokenPrice;
    }

    function multiply(uint x, uint y) internal pure returns(uint z){
        require(y == 0 || (z = x * y) / y == x);
    }

    function buyTokens(uint256 _numberOfTokens) public payable{
        require(msg.value == multiply(_numberOfTokens, tokenPrice));
        require(tokenContract.balanceOf(address(this)) >= _numberOfTokens);
        require(tokenContract.transfer(msg.sender, _numberOfTokens));

        tokensSold += _numberOfTokens;

        emit Sell(msg.sender, _numberOfTokens);

    }

}

ERC20 代币合约

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;

contract NzouaToken {

    string public name = "Nzouat Token";
    string public symbol = "NZT";
    uint256 public totalSupply;

    event Transfer(
        address indexed _from,
        address indexed _to,
        uint256 _value
    );

    event Approval(
      address indexed _owner, 
      address indexed _spender,
      uint256 _value
    );

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;


    constructor(uint256 _initialSupply) {
        balanceOf[msg.sender] = _initialSupply;
        totalSupply = _initialSupply;
    }

    function transfer(address _to, uint256 _value) public returns(bool success){
        require(balanceOf[msg.sender] >= _value, 'The account has low funds');

        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;

        emit Transfer(msg.sender, _to, _value);

        return true;
    }

    function approve(address _spender, uint256 _value) public returns(bool success) {

        allowance[msg.sender][_spender] = _value;

        emit Approval(msg.sender, _spender, _value);
        
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){

        require(_value <= balanceOf[_from]);
        require(_value <= allowance[_from][msg.sender]);

        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;

        allowance[_from][msg.sender] -= _value;

        emit Transfer(_from, _to, _value);

        return true;
    }
}

部署脚本

const NzouaToken = artifacts.require("NzouaToken");
const NzouaTokenSale = artifacts.require("NzouaTokenSale");

module.exports = async function (deployer, network, accounts) {

    await deployer.deploy(NzouaToken, 1000000); // 1000000 NZT tokens

    await deployer.deploy(NzouaTokenSale, NzouaToken.address, 1000000000000000);
};

使用 Mocha 进行单元测试(失败的众筹测试的一部分)

var NzouaToken = artifacts.require('./NzouaToken');
var NzouaTokenSale = artifacts.require('./NzouaTokenSale');

contract('NzouaTokenSale', async (accounts) => {
    let tokenSale;
    let token;
    let tokenPrice = 1000000000000000; // in wei
    const adminAccount = accounts[0];
    const buyerAccount = accounts[1];

    describe('Facilitates Token Buying', async () => {
        it('Required a successful Transfer of Tokens', async () => {
            token = await NzouaToken.deployed();
            tokenSale = await NzouaTokenSale.deployed();
            let tokenSaleBalance;
            let buyerBalance;

            const numberOfTokens = 10;


            const tokensAvailable = 750000;

            // try {
            let receipt = await token.transfer.call(tokenSale.address, tokensAvailable, {
                from: adminAccount
            })

            tokenSaleBalance = await token.balanceOf(tokenSale.address);
            assert.equal(tokenSaleBalance.toNumber(), tokensAvailable, 'Contract received funds.')

            await tokenSale.buyTokens(numberOfTokens, {
                from: buyerAccount,
                value: numberOfTokens * tokenPrice
            });

            // Grab the new balance of the buyerAccount
            buyerBalance = await token.balanceOf(buyerAccount);
            buyerBalance = buyerBalance.toNumber()
            assert.equal(tokenSaleBalance, numberOfTokens, 'Buyer Balance updated');

            // Grab the new balance of the Token Sale Contract
            tokenSaleBalance = await token.balanceOf(tokenSale.address);
            tokenSaleBalance = tokenSaleBalance.toNumber()
            assert.equal(tokenSaleBalance, tokensAvailable - numberOfTokens, 'Token Sale Balance updated');

            // } catch (error) {
            //     // console.log(error.message)
            //     assert(error.message.indexOf('revert') >= 0, 'Something went wrong while making the transfer');
            // }

        });
    });

});

如果我取消对try{}catch{}部分的注释,测试将通过,但这不是我期望的行为。

当我在 truffle 控制台内使用 truffle truffle test运行我的测试时,我的所有其他测试都通过了一个,并且我收到了这个还原错误

松露控制台错误消息

我在这里做错了什么?

您收到错误,因为您的transfer功能有此require

    require(balanceOf[msg.sender] >= _value, 'The account has low funds');

所以请确保您的转账金额小于msg.sender的余额

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM