[Ethernaut] Level 0 Hello Ethernaut 풀이
https://ethernaut.openzeppelin.com/
https://ethernaut.openzeppelin.com/
ethernaut.openzeppelin.com
이더넛(Ethernaut)이란 Web3 워게임 사이트에서 공부를 시작하였고 문제 풀이를 꾸준히 포스팅해보도록 하겠다.
This level walks you through the very basics of how to play the game.
Difficulty: ☆☆☆☆☆
우선 브라우저의 콘솔을 열어 컨트랙트와 통신해야 하는 것으로 보인다.
player의 주소와 getBalance() 함수로 player의 잔고도 확인할 수 있다.
문제에서 제시해준 대로 contract.info()를 입력해보겠다.
info() 함수를 호출하니 위와 같은 문자열이 반환되었다. 추측하기로 다음은 contract.info1()을 입력해봐야 할 것 같다.
info2() 함수에 hello라는 문자열을 넘겨 호출하였고 그 다음은 infoNum() 함수를 호출하였다.
infoNum() 함수를 호출하니 42라는 값이 담겨있었고 이는 아래와 같이 여러 메소드들 중 info42()를 뜻하는 것 같았다.
password를 알고 있다면 authenticate() 함수에 전달하여 submit하라고 한다.
콘솔에서 "contract."를 입력하여 컨트랙트의 변수들과 메소드들 중에서 password라는 것을 발견하였다.
password는 'ethernaut0'이었고 이를 authenticate 함수에 전달하면 될 것이다.
위와 같이 입력하니 MetaMask가 실행되며 트랜잭션이 성공적으로 생성되었고 이제 Submit instance 버튼을 눌러 문제를 해결하면 된다.
✌
문제 보충 설명
문제를 해결하니 해당 컨트랙트의 코드가 보여지며 문제점을 확인할 수 있었다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Instance {
string public password;
uint8 public infoNum = 42;
string public theMethodName = "The method name is method7123949.";
bool private cleared = false;
// constructor
constructor(string memory _password) {
password = _password;
}
function info() public pure returns (string memory) {
return "You will find what you need in info1().";
}
function info1() public pure returns (string memory) {
return 'Try info2(), but with "hello" as a parameter.';
}
function info2(string memory param) public pure returns (string memory) {
if (keccak256(abi.encodePacked(param)) == keccak256(abi.encodePacked("hello"))) {
return "The property infoNum holds the number of the next info method to call.";
}
return "Wrong parameter.";
}
function info42() public pure returns (string memory) {
return "theMethodName is the name of the next method.";
}
function method7123949() public pure returns (string memory) {
return "If you know the password, submit it to authenticate().";
}
function authenticate(string memory passkey) public {
if (keccak256(abi.encodePacked(passkey)) == keccak256(abi.encodePacked(password))) {
cleared = true;
}
}
function getCleared() public view returns (bool) {
return cleared;
}
}
password 변수의 visibility(접근 제어자)가 public으로 되어 있어 외부에서도 제한 없이 변수값을 확인할 수 있었던 것이 문제였다. 이와 같은 문제를 해결하기 위해선 private로 접근제어자를 변경하여 외부에서 변수의 값을 쉽게 볼 수 없도록 해주면 될 것이다.