All About msg.data in solidity


msg.data or calldata store the data of the called function means calling function id, and its parameters in the form of bytes.

here is an method:

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

Now assume we pass call above method like this:

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

This calldata or msg.data something 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

another example of calldata

contract Calldata {
    function add(uint256 _a, uint256 _b) public view
    returns(uint256 result) {
        assembly {
            let a: = mload(0x40)
            let b: = add(a, 32)
            calldatacopy(a, 4, 32)
            calldatacopy(b, add(4, 32), 32)
            result: = add(mload(a), mload(b))
        }
    }
}

The idea here is to return the addition of two numbers passed by arguments. As you can see, once again we are loading a memory pointer reading from <code0x40, but please ignore that for now; we will explain it right after this example. We are storing that memory pointer in the variable a and storing in b the following position which is 32-bytes right after a. Then we use calldatacopy to store the first parameter in a. You may have noticed we are copying it from the 4th position of the calldata instead of its beginning. This is because the first 4 bytes of the calldata hold the signature of the function being called, in this case bytes4(keccak256("add(uint256,uint256)")); this is what the EVM uses to identify which function has to be executed on a call. Then, we store the second parameter in b copying the following 32 bytes of the calldata. Finally, we just need to calculate the addition of both values loading them from memory.