In level 4 of the Ethernaut Game our goal is to claim ownership of the contract. Telephone // 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; } } } This is a simple contract with only one function and constructor that assigns the ownership to the address that deployed the contract. Considering that we have only one function it is fairly easy to guess that need to focus on it if we want to win the game. The function takes as argument an address and verifies if . changeOwner (tx.origin != msg.sender) To claim the ownership we need to first understand what is the difference between and and why contracts that use the to authorize users are vulnerable to phishing attacks. tx.origin msg.sender tx.origin : tx.origin 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, not contract address : msg.sender both user wallets and smart contracts can be the msg.sender checks where the external function call directly came from For more details, I encourage you to read my post about tx.origin Hack Solidity: Tx Origin Attacks To hack the contract and claim ownership all we need to do is to create a new malicious contract and encourage the owner to call a specific function that under the hood will change the ownership. Let's think about that like a phishing attack. Go to Remix IDE and paste a smart contract. Next, a open new file and create the following contract. Do not forget to import the contract. Telephone Telephone Here we have a constructor that takes the Telephone's contract address. Next, we have a malicious function that takes the address of the attacker and uses it to change the ownership of the contract. changeOwner Telephone // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./Telephone.sol"; contract Attack { Telephone telephone; constructor(address _address) public { telephone = Telephone(_address); } function changeOwner(address _address) public { telephone.changeOwner(_address); } } Before we deploy the contract let's first check the current Telephone's owner address. Before you deploy the contract in Remix you need to change the environment to Injected Web3. Next, in the Deploy field put a contract address. Telephone To check the address run the following command in the browser console. Once you deploy the contract in the next step you can call the function. As an argument put your MetaMask address. changeOwner When you call the function you should claim the ownership of the Telephone smart contract. To check that run the following command in the browser console. As you can see the owner's address has changed, i.e. I claimed the ownership. Note, your wallet address is different, thus your output will differ from mine. Also Published Here