The book Mastering Ethereum pointed out that it is not safe to use tx.origin in smart contracts. I want to know what is the reason for insecurity?


Primarily to protect against phishing contracts.

tx.origin is the original user that initiated the transaction.

So if contract has some method like this (in Vyper):

def burnBalance():
    assert tx.origin == owner, "You are not the owner"
    balance[tx.origin] = 0

Then another smart contract can "phish" you with a proxy function - If you accidentally interact with this evil contract then you will lose your funds:

# The attacking contract calling the original contract

If burnBalance was instead using msg.sender then this attack will fail:

# This is the correct way of checking permissions
def burnBalance():
    assert msg.sender == owner, "You are not the owner"
    balance[msg.sender] = 0

msg.sender is the intermediate caller; In this case the phishing contract is the msg.sender.

Sidenote: There is actually some discussion in the ethereum community on removing tx.origin all together. Personally I disagree with this as it has some niche use cases. One of which is checking if the caller who is interacting with the smart contract is another smart contract or a normal user. e.g.

assert tx.origin == msg.sender, "Only users can interact with this contract"
  • Thank you for your answer, it has benefited me a lot
    – wei wang
    Dec 10 '20 at 0:28

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.