3.14 Transaction Checks

tx.origin

The use of tx.origin is considered dangerous in certain situations within smart contracts. Remember that in the context of Ethereum, tx.origin gives the address of the externally owned account that originated the transaction.

If the tx.origin address is used for authorization, then it can be abused by attackers to launch replay attacks by coming in between the user and the smart contract of concern.

This is sometimes known as "man in the middle replay attack" (or MITM as an abbreviation) because the attacker comes in between the user and the contract, captures the transaction and later replaces it. Because the smart contract uses tx.origin, it fails to recognize that this transaction actually was originated from the attacker in the middle.

So in this case the recommended best practice for smart contracts using authorization is to use msg.sender instead of tx.origin, because msg.sender would give the address of the most recent or the closest entity. So in this case, if there is a man in the middle attacker, then msg.sender would give the address of the attacker and not that of the authorized user pointed to by tx.origin.

Contract Check

There may be situations where a particular smart contract may want to know, if the transaction or the call made to it is coming from a contract account or an externally owned account.

There are two popular ways for determining that:

  1. Checking if the code size of the account of the originating transaction is greater than zero and if this is not zero, it means that that account has code and therefore is a contract account.

  2. Checking if the msg.sender is the same as the tx.origin and, if it is, then it means that the msg.sender is an externally owned account.

Remember that tx.origin can only be an externally owned account in Ethereum as of now.

So these two techniques have pros and cons and depending on the specific application it may make more sense to use one over the other.

There are risks associated and implications thereof of either of these two approaches particularly with the code size approach the risk is that, if this check is made while a contract is still being constructed within the constructor the code size will still be zero for that account so, if we determine based on that aspect that this is an externally owned account, then it would be a wrong assumption.

Last updated