// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
contract Recovery {
//generate tokens
function generateToken(string memory _name, uint256 _initialSupply) public {
new SimpleToken(_name, msg.sender, _initialSupply);
}
}
contract SimpleToken {
using SafeMath for uint256;
// public variables
string public name;
mapping (address => uint) public balances;
// constructor
constructor(string memory _name, address _creator, uint256 _initialSupply) public {
name = _name;
balances[_creator] = _initialSupply;
}
// collect ether in return for tokens
receive() external payable {
balances[msg.sender] = msg.value.mul(10);
}
// allow transfers of tokens
function transfer(address _to, uint _amount) public {
require(balances[msg.sender] >= _amount);
balances[msg.sender] = balances[msg.sender].sub(_amount);
balances[_to] = _amount;
}
// clean up after ourselves
function destroy(address payable _to) public {
selfdestruct(_to);
}
}
A contract creator has built a very simple token factory contract.
Anyone can create new tokens with ease.
After deploying the first token contract, the creator sent 0.001 ether to obtain more tokens.
They have since lost the contract address.
This level will be completed if you can recover (or remove) the 0.001 ether from the lost contract address.
keccack256(RLP_encode(sender, nonce))
keccak256( 0xff ++ senderAddress ++ salt ++ keccak256(init_code))
RLP
는 Recursive-length prefix의 약자로 임의의 길이를 가진 문자열과 배열을 인코딩하는 방법이다. 이 때 값과 길이에 대한 정보가 포함되어 있다. 이더리움 네트워크에서는 RLP
방식을 트랜잭션 정보와 state, receipt, DB 저장에 사용한다.
처음엔 주소 생성을 랜덤으로 하는 줄 알았다. 하지만 1번과 같은 방법을 사용해서 주소를 만든다는 것을 알면 주소를 분실했을 때 다시 찾을 수 있다. sender의 주소와 nonce 값만 알면 되기 때문. 사실 이러한 방법보다 더 쉬운 방법이 있다. 바로 이더스캔을 보면 된다. 트랜잭션을 보면 어떤 주소가 생성됐는지 쉽게 알 수 있다.
컨트랙트에게 어떤 함수를 실행할지, 인자에 어떤 값을 넣어줄지 알려주는 역할을 한다. 예를 들어, 컨트랙트에서 아래 함수를 실행한다고 해보자.
transfer(address,uint256)
이더리움에서는 함수명과 인자를 keccack256
에 넣어서 나온 첫 4바이트를 통해 어떤 인자를 가지고 어떤 함수를 실행하는지 파악할 수 있다. 위 예에서는 0xa9059cbb
가 첫 4바이트다. 0x337c67618968370907da31dAEf3020238D01c9de
주소로 10000
개의 토큰을 보낸다고 했을 때, 각각의 정보는 32바이트로 바뀐 다음 합쳐진다. 주소는 0x000000000000000000000000337c67618968370907da31dAEf3020238D01c9de
로 바뀌고 토큰 갯수는 0x0000000000000000000000000000000000000000000000008ac7230489e80000
로 변환된다. 각 정보에서 16진수를 나타내는 0x를 제외한 후, 함수와 인자에 대한 정보까지 합쳐져서 최종 payload는 다음과 같다.
a9059cbb000000000000000000000000337c67618968370907da31dAEf3020238D01c9de0000000000000000000000000000000000000000000000008ac7230489e80000
이더스캔으로 알아낸 주소를 인자로 넣어서 selfdestruct
함수를 실행하면 컨트랙트가 파괴되면서 안에 있던 토큰을 주소로 보낼 수 있다.