问题描述
我是 solidity 的新手,我正在尝试按照 ERC-20 token standard 创建我的第一个智能合约。按照标准要求,我有一个 transfer
函数,如下所示:
function transfer(address _to,uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
// transfer the amount
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
// trigger a Transfer event
emit Transfer(msg.sender,_to,_value);
return true;
}
正如所见,我首先进行健全性检查,确保发件人有足够的金额与 require(balanceOf[msg.sender] >= _value)
执行交易。我现在想测试代码的特定部分,看看如果数量太大,它是否真的会抛出预期的错误。我正在使用 truffle
和有用的 truffle-assertions package:
const truffleAssert = require("truffle-assertions");
it("should revert transfer if the amount is larger than the sender's balance",() => {
return MyToken.deployed().then((instance) =>
truffleAssert.fails(
instance.transfer.call(accounts[1],10000000),truffleAssert.ErrorType.REVERT
)
);
});
这似乎按预期工作。但是,如果我从 require
函数中删除 transfer
部分,我希望测试失败,但测试以某种方式通过。来自 Java 背景,这让我怀疑我是否真正正确地测试了代码。在 solidity 中测试此类场景的正确且可靠的方法是什么?
解决方法
Solidity 在 0.8.0 版本中引入了整数上溢/下溢的自动异常。
算术运算在下溢和上溢时恢复。您可以使用 unchecked { ... }
来使用之前的包装行为。
来源:docs
如果您使用 Solidity ^0.8,它仍然会抛出 balanceOf[msg.sender] -= _value;
(假设 value
大于 balanceOf[msg.sender]
),否则 balanceOf[msg.sender]
值会下溢。
您会在许多来源中看到使用 require 语句进行的精确检查,因为它们要么是在 0.8 版之前创建的,要么它们的作者可能没有意识到这一新功能。或者他们可能想使用 require(false,'error message')
的第二个参数传递自定义错误消息(自动异常不提供任何消息)。但从 0.8 开始,不再需要它了。