1

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.

  • What have you tried so far, and where specifically did you get stuck? – smarx Mar 18 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 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. – Mikhail Vladimirov Mar 19 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 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. – Mikhail Vladimirov Mar 19 at 9:15
1
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
  }
}
  • Thank you. This does not solve my problem completely but from here I can get what I need. – Jaime Mar 19 at 9:25

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.