交易失败但调用合约会认为它成功了吗?
Can transaction fail but the calling contract will think it was successful?
进行 ERC20 转账时,标准做法是将其包装在 require 语句中,因此如果失败,tx 将像这样恢复:
require(token.transfer(...));
如果我调用的外部合约不是 return 布尔值并且交易失败怎么办。
是否有可能 tx 会失败(不恢复)但调用该函数的合约会认为它是成功的?
谢谢。如果问题不清楚,我很乐意提供更多背景信息。
当您使用外部函数调用时,如您的示例所示,任何 sub-call 还原都会传播并还原主事务。
示例:
function foo() public {
// if `transfer()` reverts, `foo()` reverts as well
token.transfer(recipient, amount);
}
如果您使用 low-level .call()
方法,sub-call 还原不会传播到您的主函数。相反,它将 return false
作为第一个 return 值。
function foo() public {
// if `transfer()` reverts,
// `success` returns `false` and `foo()` does NOT revert
(bool success, bytes memory returnedData) = address(token).call(
abi.encodeWithSignature(
"transfer(address,uint256)",
recipient,
amount
)
);
}
如果您用 try/catch
捕获 sub-call 恢复,那也不会恢复主事务。
function foo() public {
// if `transfer()` reverts,
// the `catch` block is invoked and `foo()` does NOT revert
try token.transfer(recipient, amount) returns (bool) {
} catch Error (string memory reason) {
}
}
进行 ERC20 转账时,标准做法是将其包装在 require 语句中,因此如果失败,tx 将像这样恢复:
require(token.transfer(...));
如果我调用的外部合约不是 return 布尔值并且交易失败怎么办。
是否有可能 tx 会失败(不恢复)但调用该函数的合约会认为它是成功的?
谢谢。如果问题不清楚,我很乐意提供更多背景信息。
当您使用外部函数调用时,如您的示例所示,任何 sub-call 还原都会传播并还原主事务。
示例:
function foo() public {
// if `transfer()` reverts, `foo()` reverts as well
token.transfer(recipient, amount);
}
如果您使用 low-level .call()
方法,sub-call 还原不会传播到您的主函数。相反,它将 return false
作为第一个 return 值。
function foo() public {
// if `transfer()` reverts,
// `success` returns `false` and `foo()` does NOT revert
(bool success, bytes memory returnedData) = address(token).call(
abi.encodeWithSignature(
"transfer(address,uint256)",
recipient,
amount
)
);
}
如果您用 try/catch
捕获 sub-call 恢复,那也不会恢复主事务。
function foo() public {
// if `transfer()` reverts,
// the `catch` block is invoked and `foo()` does NOT revert
try token.transfer(recipient, amount) returns (bool) {
} catch Error (string memory reason) {
}
}