交易失败但调用合约会认为它成功了吗?

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) {

    }
}