如何正确测试 Solidity 中的异常?
How to properly test exceptions in Solidity?
我是 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
)
);
});
这似乎按预期工作。但是,如果我要从我的 transfer
函数中删除 require
部分,我预计测试会失败,但测试会以某种方式通过。来自 Java 的背景,这让我怀疑我是否真的在正确地测试代码。在 Solidity 中测试此类场景的正确且可靠的方法是什么?
Solidity 在版本 0.8.0 中引入了整数 overflow/underflow 的自动异常。
Arithmetic operations revert on underflow and overflow. You can use unchecked { ... }
to use the previous wrapping behaviour.
来源:docs
如果您使用的是 Solidity ^0.8,它仍然会抛出 balanceOf[msg.sender] -= _value;
(假设 value
大于 balanceOf[msg.sender]
),否则 balanceOf[msg.sender]
值会下溢。
您会在许多来源中使用 require 语句看到这种精确检查,因为它们要么是在 0.8 版之前创建的,要么它们的作者可能没有意识到这一新功能。或者他们可能想使用 require(false, 'error message')
的第二个参数传递自定义错误消息(自动异常不提供任何消息)。但是从0.8开始就不需要了。
我是 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
)
);
});
这似乎按预期工作。但是,如果我要从我的 transfer
函数中删除 require
部分,我预计测试会失败,但测试会以某种方式通过。来自 Java 的背景,这让我怀疑我是否真的在正确地测试代码。在 Solidity 中测试此类场景的正确且可靠的方法是什么?
Solidity 在版本 0.8.0 中引入了整数 overflow/underflow 的自动异常。
Arithmetic operations revert on underflow and overflow. You can use
unchecked { ... }
to use the previous wrapping behaviour.
来源:docs
如果您使用的是 Solidity ^0.8,它仍然会抛出 balanceOf[msg.sender] -= _value;
(假设 value
大于 balanceOf[msg.sender]
),否则 balanceOf[msg.sender]
值会下溢。
您会在许多来源中使用 require 语句看到这种精确检查,因为它们要么是在 0.8 版之前创建的,要么它们的作者可能没有意识到这一新功能。或者他们可能想使用 require(false, 'error message')
的第二个参数传递自定义错误消息(自动异常不提供任何消息)。但是从0.8开始就不需要了。