2

Take the following low-level call written in Solidity:

(bool success, bytes memory response) =
          address(proxy).call(abi.encodeWithSelector(plugins.reverter.withReasonString.selector));

I know that this call will revert because I wrote the plugins.reverter contract (this is a test):

contract TargetReverter {
    function withReasonString() external pure {
        revert("You shall not pass");
    }
}

I want to ABI decode the response into a string, but I cannot make it work. The following code does not work:

abi.decode(response, (string));

I imagine that this is because response starts with a 4-byte function selector:

0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012596f75207368616c6c206e6f7420706173730000000000000000000000000000

How can I turn the bytes above into a string?

2 Answers 2

2

Just found another solution that is much more gas efficient, as it uses a native Error function to parse the response:

{
    (bool success, bytes memory response) = address(proxy).call(abi.encodeWithSelector(plugins.reverter.withReasonString.selector));

    /// Signature for "Error(string)"
    bytes4 errorSignature = 0x08c379a0;

    /// Make sure the response is from a standard revert()
    if (!success && bytes4(response) == errorSignature) {
        (bool success2, bytes memory response2) = address(this).call(response);

        string errorText = abi.decode(response2, (string));

        return errorText;
    }
}

And following this we define the function that can parse the revert() encoded data

function Error(string memory text) public pure returns(string memory) {
    return text;
}
1

abi.decode() needs to receive ABI-encoded data without signatures, but revert() returns a standard Error(string), resulting in ABI-encoded signature+data.

So, you just need to remove the signature before decoding:

if (!success) {
    for (uint256 i; i < response.length-4;) {
        response[i] = response[i+4];
        unchecked{ ++i; }
    }
    
    string memory errorMessage = abi.decode(response, (string));

    return errorMessage;
}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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