Ethernaut을 해보려 하는데 Rinkebey 테스트넷이 3일 뒤에 종료된다.. 따라서 26개의 관문을 3일 안에
통과해야 한다. 안 그러면 언제 또 Ethernaut CTF
를 할 수 있을 지 모른다. 처음 해 보는 CTF라서 시행착오가 많겠지만 이런 저런 과정 속에서 배우는 것도 많을거라 생각한다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
contract Fallback {
using SafeMath for uint256;
mapping(address => uint) public contributions;
address payable public owner;
constructor() public {
owner = msg.sender;
contributions[msg.sender] = 1000 * (1 ether);
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function contribute() public payable {
require(msg.value < 0.001 ether);
contributions[msg.sender] += msg.value;
if(contributions[msg.sender] > contributions[owner]) {
owner = msg.sender;
}
}
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
owner.transfer(address(this).balance);
}
receive() external payable {
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}
Look carefully at the contract's code below.
You will beat this level if
1. you claim ownership of the contract
2. you reduce its balance to 0
Things that might help
How to send ether when interacting with an ABI
How to send ether outside of the ABI
Converting to and from wei/ether units (see help() command)
Fallback methods
컨트랙트에 이더를 보내는 방법은 sendTransaction
을 이용하면 된다. 이 때 인자를 JSON 형태로 넣어주면 되는데 이 문제를 해결하기 전까지 항상 의문점이 있었다. 언제는 from, to, value 값까지 넣어주는데 다른 때는 value 만 넣어줄 때도 있었기 때문에 왜 그런지 몰랐었다. 그런데 JSON 형태로 넣어주기 때문에 그냥 상황에 맞게 key-value 값을 추가해주면 됐던 것. 별거 아닌 것 같지만 아하 모먼트가 생겨서 기분이 좋다.
contract.sendTransaction({value: })
로 현재 owner가 보낸 양보다 더 많은 양의 이더를 보낸 후, owner가 내 지갑 주소로 변경됐다. 이제 withdraw 하고 인스턴스 제출하면 끝!