The difference between tx.origin and msg.sender in Solidity, and how it changes with account abstraction
I was playing an Ethernaut level the other day when the topic of tx.orign and msg.sender came up. The difference between the two is fairly simple (as of early 2023); tx.origin is the address of the EOA (externally ownder account) that originated the transaction, and msg.sender is the address of whatever called the currently executing smart contract (could be an EOA or a smart contract).
Up until now, EOAs were the only things in Ethereum that could create a transaction. This is why tx.origin
always pointed to an EOA. This will change with ERC-4337 (account abstraction), whereby certain smart contracts will have the ability to issue transactions on behalf of a user. This means that any Solidity code which reliess on tx.origin
always pointing to an EOA should be updated, as pointed out in this post by OpenZeppelin.
It’s worth noting why msg.sender
is not always equal to tx.origin
, as it highlights an important feature of Ethereum; smart contract can call other smart contracts as part of the same transaction. A notable example of this is flash loans, in case you ever want to see an NFT “sell” for millions of dollars.
Each time a contract calls another contract, the value of msg.sender
is updated. If the call chain is:
EOA -> Contract A -> Contract B -> Contract C
Then Contract B will see msg.sender
as the address of Contract A. Contract C will see msg.sender
as Contract B, etc. But tx.origin
will always be the address of “leftmost thing in the call chain” — the EOA in this case.
Thanks for reading! If you’d like to see a walkthrough of this level of Ethernaut, here is my video: