Hardhat测试问题.稳固契约错误?



我是加密的新手,只是在探索solid语言。我尝试制作一个具有一些基本功能的简单的固化令牌合约。它应该转移令牌并更新余额。然而,当我运行应该尝试添加平衡功能的测试时,我得到这个错误:

npx hardhat test   
No need to generate any newer typings.

MyERC20Contract
when I transfer 10 tokens
1) sould transfer tokens correctly

0 passing (728ms)
1 failing
1) MyERC20Contract
when I transfer 10 tokens
sould transfer tokens correctly:
Error: VM Exception while processing transaction: reverted with reason string 'ERC20: transfer amount exceeds balance'
at ERC20._transfer (contracts/ERC20.sol:49)
at ERC20.transfer (contracts/ERC20.sol:25)
at async HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1773:23)
at async HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:466:16)
at async EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1504:18)
at async HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
at async EthersProviderWrapper.send (node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)

我是否犯了一些我没有意识到的错误?

测试文件:

import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { ERC20 } from "../typechain";
describe("MyERC20Contract", function() {
let MyERC20Contract: ERC20;
let someAddress: SignerWithAddress;
let someOtherAddress: SignerWithAddress;
beforeEach(async function() {
const ERC20ContractFactory = await ethers.getContractFactory("ERC20");
MyERC20Contract = await ERC20ContractFactory.deploy("Hello","SYM");
await MyERC20Contract.deployed();
someAddress = (await ethers.getSigners())[1];
someOtherAddress = (await ethers.getSigners())[2];
});
describe("When I have 10 tokens", function() {
beforeEach(async function() {
await MyERC20Contract.transfer(someAddress.address, 10);
});
});
describe("when I transfer 10 tokens",  function() {
it("sould transfer tokens correctly", async function() {
await MyERC20Contract
.connect(someAddress)
.transfer(someOtherAddress.address, 10);

expect(
await MyERC20Contract.balanceOf(someOtherAddress.address)
).to.equal(10);
});

});

});

my .sol contract:

//SPDX-License-Identifier: Unlicense: MIT
pragma solidity ^0.8.0;
contract ERC20 {
uint256 public totalSupply;
string public name;
string public symbol;

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

constructor(string memory name_, string memory symbol_) {
name = name_;
symbol = symbol_;
_mint(msg.sender, 100e18);
} 
function decimals() external pure returns (uint8) {
return 18;
}
function transfer(address recipient, uint256 amount) external returns (bool) {
return _transfer(msg.sender, recipient, amount);

}
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {
uint256 currentAllowance = allowance[sender][msg.sender];
require(currentAllowance >= amount, "ERC20: Transfer amount exceeds allowance" ) ;
allowance[sender][msg.sender] = currentAllowance - amount;
return _transfer(sender, recipient, amount);

}
function approve(address spender, uint256 amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
return true;
}
function _transfer(address sender, address recipient, uint256 amount) private returns (bool) {
require(recipient != address(0), "ERC20: transfer to zero address");
uint256 senderBalance = balanceOf[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
balanceOf[sender] = senderBalance - amount;
balanceOf[recipient] += amount;
return true;

}
function _mint(address to, uint256 amount) internal {
require(recipient != address(0), "ERC20: transfer to zero address");
totalSupply += amount;
balanceOf[to] +=amount;
}

}
MyERC20Contract = await ERC20ContractFactory.deploy("Hello","SYM");

由于您的代码片段没有指定从哪个地址部署事务,因此契约从第一个地址(索引0)部署。

第0个地址接收构造函数的令牌,其他地址没有令牌。

constructor(string memory name_, string memory symbol_) {
name = name_;
symbol = symbol_;
_mint(msg.sender, 100e18);
}

但是你的代码片段试图从第二个地址(索引1)发送令牌。

someAddress = (await ethers.getSigners())[1];
it("sould transfer tokens correctly", async function() {
await MyERC20Contract
.connect(someAddress)
.transfer(someOtherAddress.address, 10);

由于someAddress不拥有任何令牌,因此交易失败。

解决方案:要么在你的Solidity代码中为someAddress提供资金,要么从部署者地址(目前唯一一个拥有非零代币余额的地址)发送代币。

编辑:

在你的When I have 10 tokens块中有一个beforeEach(),但它只应用于这个特定的块-而不是执行失败传输的when I transfer 10 tokens块。

所以另一个解决方案是将这个特定的beforeEach()移动到when I transfer块,但是,基于上下文中,这似乎不是一个非常干净的方法。一个好的实践是使用尽可能少的测试用例,而不相互影响。

最新更新