8

It is known that msg.sender must be used for authentication instead of tx.origin (the difference explained here). Some static analysis tools (e.g., in Remix) detect all usages of tx.origin as potential vulnerabilities and advise to use msg.sender instead.

What are the use cases where tx.origin is legitimate? If there are none, is tx.origin going to be deprecated?

1

I can only think of two semi-legitimate use cases:

  • If you, for some reason, want to block an address from interacting with your contract, tx.origin would be more appropriate because the owner of the address can't use a contract as a middleman to circumvent your block.

    Note that this block would of course only block an address, not a person. Any human can just create a new address and use that one. This block could also be circumvented using external oracle, timer or other types of services that can provide a callback.

  • You may want to record which people use your contract most, and add some counters in your contract to keep track of it. If you only want to count the 'human addresses' that originally initiated the use of your contract, you should use tx.origin instead of msg.sender.

I would personally be fine with the deprecation and removal of tx.origin. Contract functions should idealistically be unaware of whether a human or another contract is calling it.

I'm not aware of any current plans to remove it.

2

You can only use tx.origin when you are interested in the user, but security isn't a concern. I'm open-minded but I've yet to see a compelling case that fits both requirements simultaneously. It's a wonderful idea in principle, but since it has a vulnerability in practice, it's a "do not use" in my opinion.

1

Using a CloneFactory is a legitimate reason to use tx.origin if you want to set the owner correctly. Since you would usually write something like this in the constructor:

owner = msg.sender

However, when using the CloneFactory this would actually be the CloneFactoryContract. Therefore, setting the owner instead to tx.origin is the solution. After deployment, all other checks won't use the tx.origin:

require(msg.sender == owner)

So it's only about setting the correct owner when deploying the contract.

1

If a smart contract, and not some EOA, is calling you:

tx.origin != msg.sender

This can permit you to manage if you are interested in knowing that.

0

https://github.com/ethereum/solidity/issues/683 argued for the removal of tx.origin because it was often misused.

It also includes a use case by HarryR for using tx.origin:

For example, I want to verify the call chain of a transaction, to ensure that it originated from a user, and that it passed through exactly two other contracts (which are on my whitelist) before reaching me.

To sum up, the most obvious legitimate uses of tx.origin is for checking the call chain (not the type of accounts in the call chain). This is consistent with the probable intent of the authors of the EVM and they did not want contracts to be discriminated against.

An advanced example is in @Markus' answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.