I'm using the following to send eth to a contract using solidity 0.8.16:

(bool success, bytes memory data) = payable(msg.sender).call{value:someEth}("");

I've tried to get the info from the data variable, but without success.

Attempt 1: string memory b = string(data);

This returns an error with the following:

HardhatChaiMatchersDecodingError: There was an error decoding
'0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006408c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0000000000000000000000000000000000000000000000000000000000' as a string

If I decode the section with values, it's trying to describe the nonReentrant error. If I decode the whole thing, it flags an issue with the continuation byte.

Attempt 2: (string memory a) = abi.decode(data, (string));

This runs into a runtime error my ide (hardhat) can't parse:

Transaction reverted and Hardhat couldn't infer the reason.

How do I properly decode the data from this return?

  • 2
    What is that date supposed to be? When you do payable(msg.sender).call{value:someEth}("");, what is this supposed to return? Do you know what contract it is calling? To be able to decode the data you will need to know how that data looks, its type, the order in which those types were encoded before returning. If the returned data will change depending on which msg.sender calls, then it will be really hard to decode that data because you wouldn't have information about the data itself. Sep 29, 2022 at 14:32

2 Answers 2


You can take a look at this resource on how to decode return bytes from address.call. It hinges on using abi.encodeWithSignature('ADDRESS_OF_CONTRACT'):

Decoding return bytes from Solidity `address.call`


So the bytes being returned by the call to an address will end up hitting the fallback function (because it's not targeting any particular function).

I added this package in order to slice the byte array.
I skipped the first 68 bytes (4 bytes for the selector, 64 bytes for something else) and grabbed the rest of the array, casting it to a string using the openzeppelin Strings.sol extensions. It ends up being something like:

function parseError (bytes memory val) private pure returns (string memory)
    require(val.length>68, Strings.toString(val.length));
    return string(BytesLib.slice(val, 68,val.length-68));

I still don't know what the extra 64 bits is for, but might be from the calldata being passed to the fallback.

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.