29

Is msg.data equal to {from: addr1, data:something}?

How to handle the data 'something'?

when execution this code:

web3.eth.sendTransaction({from: ..., to: addressOfE, data: something}); 

how to read the "data: something " ? For example: data: web3.toHex('something')

thank you!

update 4, 7 2017

demo: I put a event function in sendCoin function.

"event LogMsgData(bytes calldata);" 
when i call this, 
meta.sendCoin(receiver, amount, {from: account, data:web3.toHex('test'), gas:500000});

the LogMsgData print this:

//"0x90b98a11     -> MethodID
//000000000000000000000000f178589cf1ef5af554863d8cef601c9fc02ca2ed   -> receiver address 
//0000000000000000000000000000000000000000000000000000000000000002"  -> the amount

and where is {from: account,data:web3.toHex('test'),gas:500000} ?

2

3 Answers 3

30

I had to dig a little deeper into the contents of msg.data for this feature.

I thought it would be worth noting that variable length parameters like arrays, bytes and strings produce a more complex structured msg.data.

Given the following method:

function getMsgData(
  address _address,
  bytes _bytes,
  uint _int,
  uint[] _array,
  string _string
 )
  external
  returns (bytes)
 {
   return msg.data;
 }

If we call this method the following params:

contract.getMsgData(
 someAddress,
 web3.toHex('my bytes'),
 12,
 [1, 4, 412],
 'thisislargerthanthirtytwobytesstring'
);

The response would be broken down like this:

0x
d1621754 // (1) methodId
000000000000000000000000c6e012db5298275a4c11b3e07d2caba88473fce1 // (2) "_address"
00000000000000000000000000000000000000000000000000000000000000a0 // (3) location of start of "_bytes" data (item 7) = 160 bytes
000000000000000000000000000000000000000000000000000000000000000c // (4) "_val" = 12
00000000000000000000000000000000000000000000000000000000000000e0 // (5) location of start of "_array" data (item 9) = 224 bytes
0000000000000000000000000000000000000000000000000000000000000160 // (6) location of start of "_string" data (item 13) = 352 bytes
0000000000000000000000000000000000000000000000000000000000000008 // (7) size of "_bytes" data in bytes (32 bytes)
6d79206279746573000000000000000000000000000000000000000000000000 // (8) "_bytes" data padded to 32 bytes
0000000000000000000000000000000000000000000000000000000000000003 // (9) length of "_array" data = 3
0000000000000000000000000000000000000000000000000000000000000001 // (10) _array[0] value = 1
0000000000000000000000000000000000000000000000000000000000000004 // (11) _array[2] value = 4
000000000000000000000000000000000000000000000000000000000000019c // (12) _array[3] value = 412
0000000000000000000000000000000000000000000000000000000000000024 // (13) size of "_string" data in bytes (64 bytes)
7468697369736c61726765727468616e74686972747974776f6279746573737472696e670..0 // (14) "_string" data padded to 64 bytes

You can see that strings, bytes and arrays all have their data size and data appended to the end of msg.data. In place of where the parameters data would normally appear you have a 32 byte interger which describes the location of the params data.

2
  • 3
    Good first post! Jun 6, 2018 at 20:34
  • 8
    Haha, thanks! I'll consider 10-year debt of leaching answers of stack overflow repaid.
    – aflesher
    Jun 6, 2018 at 23:43
9
  1. Yes, in web3.eth.sendTransaction({from: ..., to: addressOfE, data: something});, then in contract E, msg.data will be the something.

  2. However, most of the time a contract handles msg.data indirectly and easily.

For example, if you have a contract instance in web3.js

// creation of contract object
var MyContract = web3.eth.contract(abi);

// initiate contract for an address
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');

myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000}, function(err, result){ ... });

then in Solidity, the contract at 0x78e9... would have something like

function myStateChangingMethod(string someStr, uint someNumber) and the contract doesn't have to parse msg.data -- because someStr will have the value someParam1 and someNumber will have the value 23.

Note: Do not mix up #1 and #2. For example, there is no data object when invoking myStateChangingMethod in #2: use a third parameter instead.


  1. Another example is using Solidity's call. For example, a contract C sends a message to D using D.call(something), then msg.data will be the something.

Here is a "proof" to try in Remix:

contract C {
    // in Remix, pass bytes as an array like: // ["0x00","0xaa", "0xff"]
    function test(address addressOfD, bytes bb) {
        addressOfD.call(bb);
    }
}

contract D {
    event LogMsgData(bytes calldata);

    function() {
        LogMsgData(msg.data);
    }
}

enter image description here

enter image description here

8
  • thanks for your answer, but when execution web3.eth.sendTransaction({from: ..., to: addressOfE, data: something}); how to read the "data: something " ? example. data: web3.toHex('something')
    – wakerch
    Apr 9, 2017 at 9:35
  • Get the transaction and look at the input property? Or do you mean getData?
    – eth
    Apr 9, 2017 at 10:15
  • yeah , i want to access the data:web3.toHex('something') in contract internal , can it be ?
    – wakerch
    Apr 9, 2017 at 11:53
  • Are you asking for clarity about point1 of answer above? If so, in your contract's fallback function have you tried logging msg.data like it's done in point3? (I can edit the answer's point1 to mention the fallback function.)
    – eth
    Apr 10, 2017 at 4:57
  • 1
    @IlanAizelmanWS Remix has changed a lot. I think posting a question like this but using 2022 in the title, will help you? ethereum.stackexchange.com/questions/13483/…
    – eth
    Jan 24, 2022 at 10:38
1

CONTENT

msg.data = function selector (the function which is called) + function arguments

SIZE

It is a dynamic byte array which means, it does not have fixed bytes size. Selector is always 4 bytes, and each argument of the function can be maxium 32 bytes. So, bytes size/length of msg.data for a simple function with two uint256 parameters is:

4 bytes selector + 32 bytes first argument + 32 second argument = 68 bytes

However, as Solidity uses a 32-byte word size for data storage and memory access, we need to round up 68 to the nearest multiple of 32 bytes. For this reason, the final length of the msg.data is:

68 + 28 = 96 bytes

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.