gatekepper(문지기)를 통과하고 entrant(참가자)로 등록하라
extcodesize 호출은 특정 주소에 배포된 컨트랙트의 코드 크기를 가져옵니다.
이 값이 언제, 어떻게 설정되는지에 대해서는 이더리움 [옐로우 페이퍼](<https://ethereum.github.io/yellowpaper/paper.pdf>)의 섹션 7을 참고하면 알 수 있습니다.
세 번째 게이트에서 사용된 ^ 기호는 비트 단위 연산(XOR)**이며,
여기서는 또 다른 일반적인 비트 연산을 적용하기 위해 사용되었습니다 (자세한 내용은 [Solidity 치트시트](<https://docs.soliditylang.org/en/v0.4.23/miscellaneous.html#cheatsheet>)를 참고하세요).
이 문제에 접근할 때는 Coin Flip 레벨부터 시작해 보는 것도 좋은 방법입니다.
pragma solidity ^0.8.0;
contract GatekeeperTwo {
address public entrant;
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
modifier gateTwo() {
uint256 x;
assembly {
x := extcodesize(caller())
}
require(x == 0);
_;
}
modifier gateThree(bytes8 _gateKey) {
require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == type(uint64).max);
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
해법 : 이거는 contract 하나 만들어서 배포하면 풀리는 문제 아래에서 풀었던 문제당~
https://www.notion.so/4-Telephone-22571d824ff28069aee9e3337b38dbc9?source=copy_link
https://www.notion.so/13-GatekeeperOne-22671d824ff28079a118ed579e65f1d1?source=copy_link
modifier gateTwo() {
uint256 x;
assembly {
x := extcodesize(caller())
}
require(x == 0);
_;
}
힌트
황서에 따르면 아래와 같이 적혀 있다.

컨트랙트 초기화 코드가 실행되는 동안, EXTCODESIZE를 해당 주소에 대해 호출하면 0을 반환해야 한다.
이는 해당 계정(컨트랙트)의 코드 길이를 의미하지만, 아직 배포되지 않았기 때문에 코드가 존재하지 않기 때문이다.
반면, CODESIZE는 현재 실행 중인 초기화 코드의 길이를 반환한다.
→ 이 말은 즉 constructor 안에서 코드를 실행하면 extcodesize() 함수를 호출했을 때 0이라는 값이 나온다는 뜻!