[Ethereum] How to unpack/decode parameters encoded with web3.eth.abi.encodeParameters in Solidity

decodingencodingsolidityweb3js

My client app (nodejs) packs some arguments to pass to a smart contracts as bytes _data (similar to ERC223 calls with fallback). I pack the arguments in my JS client like this:

const packedArgs = web3.eth.abi.encodeParameters(['uint256', 'string'], ['123', 'Hello world']);`

When the solidity function gets that bytes argument, how does it unpack it back to uint256 and string?

Best Answer

Ok I have finally figured it out. web3.eth.abi.encodeParameters encodes each parameter as one or more 32 bit words, so to get each parameter we need to grab the next 32 bit from the bytes parameter's memory. Something like:

// Assume that _encodedParams is encoded from ([address, uint256])
function (bytes _encodedParam) public returns (address a, uint256 n) {
    uint256 btsptr;
    /* solium-disable-next-line security/no-inline-assembly */
    assembly {
        btsptr := add(_encodedParam, /*BYTES_HEADER_SIZE*/32)
        a := mload(btsptr)
        btsptr := add(_encodedParam, /*BYTES_HEADER_SIZE*/64)
        n := mload(btsptr)
    }
}

That's it really. I haven't figured out yet how to unpack a string, but probably you keep unpacking word by word and concatenating them bite-wise. Something for the next time.

Related Topic