3

I want to exract n bytes from a given bytes data.

 //this function extract the first uint8 from a byte data
function extractSelector (bytes data) public constant returns (uint8) {
        uint8 sel = uint8(data[0]);
        return sel;
    }

and the second will extract a web3 signature (65 bytes) from the rest of bytes

 function extractSig (bytes data, uint8 from, uint8 n) public constant returns(bytes) {
      bytes memory returnValue = new bytes(n);
      for (uint8 i = from; i < n; i++) {
        returnValue[i] = data[i];
      }
      return returnValue;
    }

I have this data:

data = "0x0436ee02530753fcaecf730e793c2e66791723c6c6a52e385d8200f2dfc1406a6325bba49a98373c9793fa07f82f69c7a1701cbc0cb379b957d5e96d398f1ca1e600"

//extractSelector(data) retruns 4 => it's okay!

but:

extractSig(data,1,65) returns "0x0036ee02530753fcaecf730e793c2e66791723c6c6a52e385d8200f2dfc1406a6325bba49a98373c9793fa07f82f69c7a1701cbc0cb379b957d5e96d398f1ca1e6"

//it seems like the two last "0" jump at the bigining of bytes. 

what shall I do to conserve the same data ?

2 Answers 2

2

You were filling returnValue from position from (in your case 1) and that caused the offset of zeroes at th ebeginning of your result. You need to either :

  • Start the loop from 0 and add the offset in the data like data[i + from]
function extractSig (bytes data, uint8 from, uint8 n) public constant returns(bytes) {
      bytes memory returnValue = new bytes(n);
      for (uint8 i = 0; i < n + from; i++) {
        returnValue[i] = data[i + from]; 
      }
      return returnValue;
    }
  • Or just substract the offset from the return value index (returnValue[i - from]) like this:
function extractSig (bytes data, uint8 from, uint8 n) public constant returns(bytes) {
      bytes memory returnValue = new bytes(n);
      for (uint8 i = from; i < n; i++) {
        returnValue[i - from] = data[i + from]; 
      }
      return returnValue;
}
1
  • It works thanks ! I made a kind of stupid error :p
    – maroodb
    Jun 20, 2018 at 11:52
1

Use inline assembly :

function parseMsgData() public view returns (bytes32 _address){
bytes32 _address;

assembly {
        calldatacopy(0x0, 4, 36)
        _address := mload(0x0)
}

return _address;
}

Basically what I am doing here is, I am parsing the msg.data from byte4 to byte36 to get the first input parameter. Each input parameter is of 32 bytes.

If you are wondering why doesn't the first parameter exist from 0 to 32. It is because from 0-4 bytes info about the function name in stored.

So if a function is like :

function yoyoBombastic(address _address, uint ohyEAH) public {}

Then the msg.data would be :

0-4 bytes => data about function name

4-36 bytes => _address

36-72 bytes => ohyEAH

Also in the calldatacopy(0x0, 4, 36) the 0x0 signifies where you are storing the parameter. Over here I am storing it at 0x0

You can then convert bytes to appropriate data form that you want.

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.