This level represents the working of a Telephone call, hence the level name. In a Telephone call, your call doesn’t directly go towards the person you are calling, there is a tower in between where your call goes first then it gets redirect to the recipient of the call (even though there are many other things like BTS and MSC among a call between two persons but let’s just keep it simple for now).
So the code in this level is quite short and simple. It has only function changeOwner() which requires you to not be the origin of the transaction in order to obtain ownership of the contract.
When you call the function in this contract there is only you and the contract interacting, no middle-man in between which the transaction can go through (just like a tower to make a telephone call) so we need a middle-man in order to become the contract owner.
You see the conflict now? You have to be a non-originator in order to become the owner of the contract.
Let’s start by understanding the difference between tx.origin and msg.sender. In msg.sender both the user wallet address and smart contract address can be the msg.sender while in tx.origin only user wallet address can be the tx.origin. So in this contract, currently the tx.origin and msg.sender are the same which is user wallet address so we need to give msg.sender a smart contract address to breach the only condition written inside changeOwner() function.
if (tx.origin != msg.sender) {
owner = _owner;
}
For this, we first need to paste the original contract inside a file (I named it Telephone.sol) and then we make another contract of our own which I named Attacker.sol as follows.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "./Telephone.sol";
contract Attacker {
Telephone telephone;
constructor(address _address) public {
telephone = Telephone(_address);
}
function changeOwner(address _address) public {
telephone.changeOwner(_address);
}
}
What this contract does it calls the actual contract address which we named Telephone.sol inside the constructor. It then takes the address of the attacker which will be our Metamask wallet itself and use that to change the owner of the actual contract which we named Telephone.sol of course.
Now compile both the contracts Telephone.sol and Attacker.sol then go towards Deploy. In Deploy, change the environment to “Injected Provider - Metamask” and choose the contract Attacker.sol. Right below it you’ll see a Deploy button, put your Instance Address inside it. To check what it is type await contract.address
in the console. See the screenshot below for reference.
After clicking the Deploy button you’ll see the changeOwner button down below, put your Metamask address inside it and click the changeOwner button to take the ownership of this contract and win the level.
Now you can check the owner of the contract by typing await contract.owner() inside the console and will see that your Metamask address is now showing up there. I have attached a screenshot of the initial owner address, instance address and current owner address respectively of the contract down below.
Finally click the “Submit Instance” and that’s how you win.
Top comments (0)