AllJs
AllJs

Reputation: 1810

How To Run A Successful Solidity Smart Contract Test Script?

I have been following this tutorial by Gregory from Dapp University on how to create your own ERC20 token along with a crowd-sale smart contract. I have been successful so far, but I am stuck where I need to make the buytokens() function work so a transfer of tokens from the address of the crowd-sale contract to the buyer's can take place. The test I am about to show makes use of the async/await pattern, different from what is on the video tutorial. Below you can find the code of

Thanks for your help.

Development Environment

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

Crowd-sale Contract

// 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 Token Contract

// 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;
    }
}

Deployment Script

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);
};

Unit Testing With Mocha (Part of the crowd-sale test that is failing)

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');
            // }

        });
    });

});

If I uncomment the try{}catch{} section, the test will pass but it is not the behavior I am expecting.

When I run my test using truffle truffle test inside the truffle console, All my other tests pass but one, and I get this revert error

Truffle console Error Message

What am I doing wrong here?

Upvotes: 0

Views: 273

Answers (1)

Yilmaz
Yilmaz

Reputation: 49709

You are getting error because your transfer function has this require

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

so make sure your transfer amount is less than msg.sender's balance

Upvotes: 0

Related Questions