109

If either are used in the body of a Solidity function that may change the state of a contract (write call), what's the primary difference and/or benefit of using one over the other. For example:

   function setOwner() {
      owner = msg.sender;
   }

vs.

   function setOwner() {
      owner = tx.origin;
   }

What's the difference?

2 Answers 2

129

With msg.sender the owner can be a contract.

With tx.origin the owner can never be a contract.

In a simple call chain A->B->C->D, inside D msg.sender will be C, and tx.origin will be A.

msg.sender is preferred for the flexibility it provides. Furthermore, for Serenity, even though it's a while out, Vitalik recommends avoiding tx.origin: How do I make my DAPP "Serenity-Proof?"

Carefully consider if you really ever need to use tx.origin. Remember, you may not be the only user of your contract. Other people may want to use your contract and want to interact with it via a contract they've been written.

If the origin is really desired in D, then each of the functions in the contracts B, C, D could take an extra parameter to propagate the origin: A would pass its address (this) to B, B would pass the value to C, and C would pass it to D.

EDIT: To emphasize the comment by @WBT below, a contract that uses a passed in value for the origin, must be very careful in how it uses the origin: anyone can pass in a value that is not the real origin.

5
  • 4
    If you use a wallet like the Mist wallet you will not want to use tx.origin, if I understand this explanation correctly. I would not ever hold substantial ether unless it was in a multi-sig wallet such as the Mist wallet.
    – Paul S
    Commented Mar 7, 2016 at 5:45
  • 2
    Agree! Code that uses tx.origin will not be "ownable" by a contract multi-sig wallet like Mist.
    – eth
    Commented May 29, 2016 at 3:40
  • 2
    OpenZeppelin's sample code has "address public owner", which means anyone can get the contract's owner's address. Can a wallet (hacker) ever spoof msg.sender to impersonate the owner?
    – Curt
    Commented Aug 3, 2017 at 14:11
  • 2
    @Curt The feasible way to impersonate msg.sender is to have their private key; without the private key it is computationally infeasible.
    – eth
    Commented Aug 10, 2017 at 6:19
  • 4
    Passing on the origin address as a parameter should never be used for security (e.g. "only allow this action if the passed-in address is the contract owner / has certain privileges") because it is easy to spoof: an attacker can just figure out the right address to pass in (e.g. calling owner()) and pass that in as the parameter value. You don't want that giving the caller permissions which should require demonstration that the actor holds the private key associated with the address (as when reading msg.sender directly, not via a passed parameter).
    – WBT
    Commented Feb 1, 2018 at 18:41
28

msg.sender gives the direct sender of the message, so for example a contract that passed it along.

tx.origin gives the origin of the transactions, so the user address it was originally sent from. In practice this will always be a user so eth's answer holds true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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