난이도 총 5단계에서 4단계 짜리 문제여서 겁을 좀 먹었는데 좀 많이 쉽다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Privacy {
bool public locked = true;
uint256 public ID = block.timestamp;
uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(block.timestamp);
bytes32[3] private data;
constructor(bytes32[3] memory _data) {
data = _data;
}
function unlock(bytes16 _key) public {
require(_key == bytes16(data[2]));
locked = false;
}
/*
A bunch of super advanced solidity algorithms...
,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`
.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,
*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^ ,---/V\
`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*. ~|__(o.o)
^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*' UU UU
*/
}
코드를 보면 여러 변수들이 있고, 마지막에 bytes32 배열이 존재한다.locked 변수를 false로 만들면 되는데, 그 조건은 data[2]를 bytes16으로 캐스팅한 값과 같아야 한다는 것이다.
우선 web3.eth.getStorageAt()
함수로 각 변수의 값을 좀 살펴보자.
locked 변수와 ID(block.timestamp) 변수의 값.
여기에는 세 변수의 값이 함께 들어가 있는데, 이렇게 되어 있는 이유는, storage 공간을 더 효율적으로 활용하기 위해서라고 한다.
하위 1바이트(0x0a)는 flattening의 값(10)이고, 그 다음 1바이트(0xff)는 denomination의 값(255)이다.
그 다음 두 바이트는 block.timestamp값을 uint16형으로 캐스팅한 값이고, block.timestamp값의 하위 2바이트의 값을 가지고 있다.
bytes32 배열의 값들이다.
data[2]의 값은 맨 마지막 값일테고, 이 값을 bytes16으로 캐스팅하면 block.timestamp와 마찬가지로 하위 16바이트일 것이라고 생각했는데, 그게 아니었다.
그 이유는 아직도 모르겠지만 상위 16바이트를 매개변수로 unlock함수를 호출해주면 문제를 해결할 수 있다.
Uploaded by N2T