3

Assume I am passing a variable bytes (memory) to a function. This variable corresponds to A concatenated with B where A is of size 32 and B is 96 bytes, how can I return A (bytes32) and B (bytes).

function readData(bytes memory data) public returns (bytes32, bytes memory){
    bytes32 A;
    bytes memory B;
    assembly{
        A:= mload(add(data,0x20))
        calldatacopy(B,0x45,0xA0) // not sure about this
    }
    return (A,B);
}

Edit

knowing the length of B make things easy but the things is that B size can change, therefore hardcoding a sequence of mload (one per word of data) won't do. this could be solved with an assembly loop but I wonder if there is a more efficient way to do it.

8
  • What have you tried so far, and where specifically did you get stuck?
    – user19510
    Mar 18, 2019 at 23:52
  • I just updated the question, I can get A (first 32 bytes). I think I could get B using a loop but looks dirty. I tried to get the call data but doesn't work (remix crashes), any ideas? is there a way to this directly on the input variable data?
    – Jaime
    Mar 19, 2019 at 7:54
  • In public functions, you should not assume call data to contain function arguments, because call data is basically the same as msg.data, i.e. it refers to parameters of the whole smart contract call rather than particular function call. Mar 19, 2019 at 8:58
  • the only thing to take into account in msg.data will be the 4bytes of the function selector, no?
    – Jaime
    Mar 19, 2019 at 9:00
  • No, public function (in contrast to external functions) could be called from another function of the same contract with arguments that are completely different from what is in msg.data. Mar 19, 2019 at 9:15

1 Answer 1

4
function readData (bytes memory data)
public pure returns (bytes32 a, bytes memory b) {
  require (data.length == 0x80);
  assembly {
    a := mload (add (data, 0x20)) // A
    b := mload (0x40) // Free memory pointer
    mstore (0x40, add (b, 0x80)) // Advance free memory pointer
    mstore (b, 0x60) // B length
    mstore (add (b, 0x20), mload (add (data, 0x40))) // First word of B
    mstore (add (b, 0x40), mload (add (data, 0x60))) // Second word of B
    mstore (add (b, 0x60), mload (add (data, 0x80))) // Third word of B
  }
}
1
  • Thank you. This does not solve my problem completely but from here I can get what I need.
    – Jaime
    Mar 19, 2019 at 9:25

Your Answer

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

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