0

I want to get the revert reason of a failed call and then use that revert reason in the same on-chain transaction. Is this possible?

1

I modified shanes answer:

function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
    // If the _res length is less than 68, then the transaction failed silently (without a revert message)
    if (_returnData.length < 68) return 'Transaction reverted silently';

    assembly {
        // Slice the sighash.
        _returnData := add(_returnData, 0x04)
    }
    return abi.decode(_returnData, (string)); // All that remains is the revert string
}

It seems to work and that way we dont need the extra library

| improve this answer | |
0

Yes, this is possible. In short, you can use the following code:

(bool success, bytes memory res) = _destination.call.gas(_gasLimit).value(_value)(_data);

// Get the revert message of the call and revert with it if the call failed
if (!success) {
    string memory _revertMsg = _getRevertMsg(res);
}
/// @dev Get the revert message from a call
/// @notice This is needed in order to get the human-readable revert message from a call
/// @param _res Response of the call
/// @return Revert message string
function _getRevertMsg(bytes memory _res) internal pure returns (string memory) {
    // If the _res length is less than 68, then the transaction failed silently (without a revert message)
    if (_res.length < 68) return 'Transaction reverted silently';
    bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes
    return abi.decode(revertData, (string)); // All that remains is the revert string
}

Breaking that down a little, all unsuccessful calls will return an erroneous response with the signature Error(string) (0x08c379a). With that in mind, you can simply treat it as any other signature.

if (_res.length < 68) return 'Transaction reverted silently';

The above line will look at the response and return Transaction reverted silently if there was no revert reason.

bytes memory revertData = _res.slice(4, _res.length - 4);

The above line will derive the revert reason string from the response in the format bytes format. As a note, the slice method is from this BytesLib.sol file.

return abi.decode(revertData, (string));

The above line will decode the data into a string, which is the desired output.

Note: For full disclsure, I am a cofounder of Authereum and those code blocks are from the Authereum contracts that I helped write.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.