Gatekeeper Three

Pass the three gates of Gatekeeper Three, dealing with tricky modifiers, delegatecall interactions, and understanding contract initialization states.

Vulnerable Code
Analyze the Solidity code below to find the vulnerability.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract GatekeeperThree { address public owner; address public entrant; bool public allowEntrance; modifier gateOne() { require(msg.sender != tx.origin, "Must be contract"); _; } modifier gateTwo() { require(owner == address(0), "Owner not set yet"); require(msg.sender.balance > 0 && address(this).balance == 0, "Balance reqs failed"); _; } modifier gateThree() { require(owner != address(0) && tx.origin == entrant, "Owner/entrant reqs failed"); _; } constructor() { owner = msg.sender; } // Sets owner on deployment function getAllowance(address _password) public { if (keccak256(abi.encodePacked(_password)) == keccak256(abi.encodePacked(owner))) { allowEntrance = true; } } function enter() public payable gateOne gateTwo { owner = msg.sender; // Set owner *after* gateTwo check entrant = tx.origin; require(gateThreeCheck(), "Gate three failed"); } // Helper for gateThree modifier check function gateThreeCheck() public view gateThree returns (bool) { return true; } }
Submit Explanation
Explain the vulnerability and how to exploit it.
Hints (4)
Just a little peak
Hint 1
Hint 2
Hint 3
Hint 4
Explanation
Discomfort = Learning