Solidity: who the heck is msg.sender?

Rosario De Chiara
Coinmonks

--

Here we will shortly discuss how the msg.sender mechanism works. As usual we will experiment with small chunks of Solidity that you will be able to run in your browser

At the core of the blockchain is the mechanism of adding blocks of transactions to the chain of blocks: this is the job carried out by the miners that keep the state of the Ethereum Virtual Machine (EVM) consistent; miners are in a competition to append transactions to blocks.

The state of the EVM is the effect of the execution of all the transactions collected in blocks: in a way Ethereum (and blockchains in general) are a distributed log file that collect the result of operations performed by smart contracts. Another way is to consider the blockchain as a globally shared, transactional database.

Operations on smart contracts are ignited by a simple mechanism of sending gas to an address, if the address is a smart contract it will produce an invocation of a method whose name is hashed within the transaction payload. following an example of how to invoke a method store(uint256) on a smart contract with the parameter 1:

The method store(uint256) and its invocation with parameter 1, notice the input and decoded input

What really happens in a transaction containing a method invocation is that the method signature, store(uint256) is hashed with keccak256 and the first 4 bytes are packed together with the arguments; this sequence of bytes is the content of the input field in the transaction above. More complex parameters (e.g. strings, arrays etc..) are packed in a sensible way by serializing them and concatenating together with the function hash.

In depth analysis can be found here but, for the sake of the clarity of this article, the sense of this packing is to have a compact representation of the function name together with all the parameters and this is what you find in the input field of the transaction in Remix and you also find it decoded in the inspector.

The sender of the transaction

Among the fields of each of the transactions, in Remix, you may notice the field from which is the originating account of the transaction. In Remix it is pretty straightforward to notice how the content of this field matches exactly with the field Account, on the left (see next figure)

As you may expect the account on the left matches the field from in the transaction receipt

This mechanism is quite easy but in the Ethereum specification there are two different functions to access, in Solidity, to the sender of a transaction: msg.senderand tx.origin. A couple of simple functions allows you to check that both functions returns exactly the same value.

inspectOrigin and inspectSender return the same value: the account used to call them

Are they redundant? Not at all, there is a difference, and can be emphasized in the section.

A simple smart contract to show the difference

The difference between the two is thatmsg.sender contains the address that has originated the call while tx.origin contains the originator of the transaction. To clarify the way the two variables work you can use the following piece of code, ready to be tested right in Remix.

The source contains two different contracts, one called Storage the other one is Caller and contains an instance of Storage in the field StorageObject.

The instance of Storage is created in the constructor of Caller(line 28).

Both contracts contain the same functions that will return the content of msg.sender and the content of tx.origin. But what really will shed light on the difference are the two methods (line 34 and 42): they will return the content of msg.sender and tx.origin from the point of view of the instance of Storage.

As usual the test is more explanatory than words describing it:

What you can see here is: the tx.origin contains the same value in both contracts, Storage with the function inspectOrigin and Caller with the function inspectInspectOrigin, because for both the originator of the call is the account 0x5B38...C4. You may notice the difference with the result of inspectSenderand inspectInspectSender, they both return the msg.sender but, respectively, for Callerand Storagethe result is different, as expected. For Callerthe msg.sender(function inspectSender) is, again, the account 0x5B38...C4 while for the smart contract Storage it is the address 0x9d7f...99, which is the address of the smart contract Caller.

The documentation (you can find it here) is simple but it is always interesting to check what really happens under the hood.

Join Coinmonks Telegram group and learn about crypto trading and investing

Also, Read

--

--

Rosario De Chiara
Coinmonks

Distributed Ledger Surfer, Data Masseur, Distributed Systems Sculptor, and Scalability Evangelist