The goal is the same – pass through 3 gates and register as an entrant.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
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) {
unchecked {
require(
uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^
uint64(_gateKey) ==
uint64(0) - 1
);
}
_;
}
function enter(bytes8 _gateKey)
public
gateOne
gateTwo
gateThree(_gateKey)
returns (bool)
{
entrant = tx.origin;
return true;
}
}
Analysis & Solution
Gate 1
We already know how to pass the gateOne – by using an intermediate contract.
Gate 2
modifier gateTwo() {
uint256 x;
assembly {
x := extcodesize(caller())
}
require(x == 0);
_;
}
Gate 3
modifier gateThree(bytes8 _gateKey) {
unchecked {
require(
uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^
uint64(_gateKey) ==
uint64(0) - 1
);
}
_;
}