티스토리 뷰
1. 문제
이 컨트랙트의 작성자는 스토리지의 민감한 부분에 대해 충분히 주의를 기울이고 컨트랙트를 작성했습니다.
이 컨트랙트의 잠금을 해제하시오.
도움이 될 만한 것들:
* 스토리지 작동 원리 이해
* 함수의 파라미터가 어떻게 파싱되는지 이해
* 타입 캐스팅이 어떻게 동작하는지 이해
// 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
*/
}
2. 해법
컨트랙트의 잠금을 해제하기 위해서는 스토리지에 저장된 32bytes 타입의 길이가 3인 배열 data의 마지막 원소값이 필요합니다. 우선 블록 탐색기를 열어서 컨트랙트가 배포될 때 스토리지에 어떤 변화가 있었는지 확인합니다.
여기서 스토리지 슬롯의 다섯 번째 인덱스에 들어있는 값을 사용하겠습니다. bytes32 타입의 값을 더 작은 타입으로 캐스팅하면 값이 뒷부분에서부터 잘려나갑니다. 따라서 bytes16으로 캐스팅한 결과는 0x를 제외하고 앞부분의 16 바이트를 가지게 됩니다. 이 값을 unlock 함수의 인수로 집어넣고 함수를 호출합니다.
트랙잭션이 컨펌되고나서 locked 값을 확인하면 false로 변경된 것을 확인할 수 있습니다.
인스턴스를 제출하고 마무리합니다.
3. 스토리지
스토리지에 저장되는 값들은 슬롯에 순서대로 저장이 되며, 스토리지의 각 슬롯에는 최대 32바이트 크기의 데이터가 저장될 수 있습니다. 그렇다면 우선적으로 다음과 같은 스토리지 레이아웃을 생각해볼 수 있습니다.
그런데 이렇게 배치를 하게 되면 31바이트(엄밀히 따지면 255비트) + 31바이트 + 31바이트 + 30바이트해서 총 123바이트가 낭비됨으로 인해 불필요한 비용이 발생하게 됩니다. (일반적인 값 타입의 경우 빈 자리는 00으로 채워짐)
그래서 Solidity에서는 다음과 같이 연속하는 스토리지 변수들의 크기의 합이 32바이트를 초과하지 않는 선에서 하나의 슬롯에 함께 담습니다. 이 경우에는 낭비되는 메모리가 31바이트 + 28바이트로 크게 줄은 것을 확인할 수 있습니다. 스토리지 레이아웃이 이러하므로, data[2]는 스토리지의 다섯 번째 슬롯에서 읽어올 수 있습니다.
4. 결론
- private은 secret이 아니다.
- 스토리지가 어떻게 동작하는지 알아보았다.
- 바이트열 타입의 값은 작은 타입으로 캐스팅할 때 뒷부분에서 잘려나간다.
'Solidity > Hacking' 카테고리의 다른 글
[Ethernaut] 14. Gatekeeper Two (0) | 2024.01.27 |
---|---|
[Ethernaut] 13. Gatekeeper One (1) | 2024.01.25 |
[Ethernaut] 11. Elevator (1) | 2024.01.23 |
[Ethernaut] 10. Re-entrancy (0) | 2024.01.22 |
[Ethernaut] 9. King (0) | 2024.01.20 |