// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) public {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
Unlock the vault to pass the level!
password를 맞춰서 unlock
을 실행하면 풀리는 문제인 것 같다. private 으로 선언된 변수를 알 수 있는 방법이 있을까?
stackoverflow에서 간단히 찾을 수 있었다.
web3.eth.getStorageAt("컨트랙트주소", 변수 순서)
password 변수는 2번째에 있으므로 두 번째 인자에 2를 넣어주면 된다.
마지막에 unlock 되면서 false로 바뀌었다. 해결 완료 :)
그렇다면 getStorageAt
은 도대체 뭘까? getStorageAt
은 storage에 저장된 상태값을 읽어온다. storage는 블록체인 상에 영구적으로 저장되는 공간이다. 함수 밖에 있는 변수와 함수 그 자체, struct와 배열 내부 변수가 저장된다. 따라서 prive으로 설정된 변수라고 하더라도 블록체인 상에 영구적으로 저장되기 때문에 값을 읽어 올 수 있다.
storage는 메모리 슬롯이 존재한다. 슬롯의 갯수는 2^256개이고, 슬롯 하나의 크기는 256비트(32바이트)다. 컨트랙트에 선언된 변수들은 다음과 같이 슬롯에 저장된다. gas 최적화를 위해 여러 변수가 하나의 슬롯에 저장되는 경우도 있으며, Array에 저장된 데이터의 경우 Array가 저장된 슬롯이 keccak256에 input으로 들어가서 계산된 슬롯에 할당된다.
이더스캔으로도 password를 알 수 있다. 컨트랙트가 생성된 트랜잭션을 보면 State 부분의 2번째에서 password를 찾을 수 있다. Hex로 표시된 부분을 Text로 바꾸면 A very strong secret password :)
가 실제 패스워드라는 것을 확인할 수 있다.