javascript - 如何运行成功的 Solidity 智能合约测试脚本?
问题描述
我一直在关注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
的所有其他测试都通过了,但只有一个,我得到了这个revert错误
我在这里做错了什么?
解决方案
你收到错误是因为你的transfer
函数有这个require
require(balanceOf[msg.sender] >= _value, 'The account has low funds');
所以请确保您的转账金额小于msg.sender
余额
推荐阅读
- sql - 基于另一个字段的案例陈述结果
- python - 寻找一个正则表达式来匹配以下
- asp.net-mvc - 如果未关闭,则自动关闭或自动格式化 razor 动态内容中的 html 标记
- java - 如何处理java servlet中的多个查询
- html - 谷歌自动完成地图搜索
- android-layout - 如何以编程方式创建具有圆角半径的波纹?
- python - 在 matplotlib 中重复相同的子图
- javascript - 如何使用 jQuery 获取每个元素的索引号
- docker - 在docker中以supervisord作为CMD运行Lucee(tomcat),奇怪的路径问题
- android - Trying to create a PDF from a listview