- Published on
Ethernaut - Recovery - Solution
- Authors
- Name
- Marco Besier, Ph.D.
- @marcobesier
Ethernaut - Recovery - Solution
Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Recovery {
//generate tokens
function generateToken(string memory _name, uint256 _initialSupply) public {
new SimpleToken(_name, msg.sender, _initialSupply);
}
}
contract SimpleToken {
string public name;
mapping(address => uint256) public balances;
// constructor
constructor(string memory _name, address _creator, uint256 _initialSupply) {
name = _name;
balances[_creator] = _initialSupply;
}
// collect ether in return for tokens
receive() external payable {
balances[msg.sender] = msg.value * 10;
}
// allow transfers of tokens
function transfer(address _to, uint256 _amount) public {
require(balances[msg.sender] >= _amount);
balances[msg.sender] = balances[msg.sender] - _amount;
balances[_to] = _amount;
}
// clean up after ourselves
function destroy(address payable _to) public {
selfdestruct(_to);
}
}
Solution
The goal of this challenge is determine the address of the SimpleToken
contract and recover the 0.001 ETH that the contract creator sent to it.
As a first step, we search for the level instance address, i.e., the address of the Recovery
contract, on sepolia.etherscan.io. Looking at the Internal Transactions tab, we see two Contract Creation transactions. One of them has the level instance address as its From address, telling us that it corresponds to the creation of the SimpleToken
contract in the constructor of the Recovery
contract. If we click on its Contract Creation link under To, Etherscan will take us to the detail view of the SimpleToken
contract. In particular, it will reveal the SimpleToken
's contract address. Knowing this address, we can now call the destroy()
function, specifying an arbitrary address, e.g., our player
, as the _to
parameter.
cast send <your level instance> "destroy(address)" <your player address> --private-key <your private key> --rpc-url $SEP_RPC_URL