Ethernaut Lvl 4 Telephone Walkthrough: how to abuse tx.origin & msg.sender

This levels requires you to learn the nuances between tx.origin vs msg.sender to claim ownership of the contract.


  • The original user wallet that initiated the transaction
  • The origin address of potentially an entire chain of transactions and calls
  • Only user wallet addresses can be the tx.origin
  • A contract address can never be the tx.origin


  • The immediate sender of this specific transaction or call
  • Both user wallets and smart contracts can be the msg.sender

Example scenarios:

Where tx.origin, msg.sender is observed in the context of the very last node:

Tip: msg.sender checks where the external function call directly came from. msg.sender is typically who you want to authenticate.

Detailed Walkthrough

  1. Notice Telephone.sol’s changeOwner function checks if (tx.origin != msg.sender). Seems like we can successfully trigger this function with scenario 3:

2. Create a phone contract, Telephony to pose as Contract A. Instantiate Contract B, your Telephone.sol, inside Telephony:

contract Telephony {    Telephone public phone = Telephone(YOUR_INSTANCE_ADDR_HERE);    //TODO...

3. Create a changeOwner function inside Telephony that calls the changeOwner function in Telephone, i.e. play the game of Telephone.

function changeOwner(address _owner) public {

4. Notice await contract.owner() in console now indicate your user wallet is the owner!



Engineer. Tweets @0xSage

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store