1. 문제

gatekepper(문지기)를 통과하고 entrant(참가자)로 등록하라
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleTrick {
    GatekeeperThree public target;
    address public trick;
    uint256 private password = block.timestamp;

    constructor(address payable _target) {
        target = GatekeeperThree(_target);
    }

    function checkPassword(uint256 _password) public returns (bool) {
        if (_password == password) {
            return true;
        }
        password = block.timestamp;
        return false;
    }

    function trickInit() public {
        trick = address(this);
    }

    function trickyTrick() public {
        if (address(this) == msg.sender && address(this) != trick) {
            target.getAllowance(password);
        }
    }
}

contract GatekeeperThree {
    address public owner;
    address public entrant;
    bool public allowEntrance;

    SimpleTrick public trick;

    function construct0r() public {
        owner = msg.sender;
    }

    modifier gateOne() {
        require(msg.sender == owner);
        require(tx.origin != owner);
        _;
    }

    modifier gateTwo() {
        require(allowEntrance == true);
        _;
    }

    modifier gateThree() {
        if (address(this).balance > 0.001 ether && payable(owner).send(0.001 ether) == false) {
            _;
        }
    }

    function getAllowance(uint256 _password) public {
        if (trick.checkPassword(_password)) {
            allowEntrance = true;
        }
    }

    function createTrick() public {
        trick = new SimpleTrick(payable(address(this)));
        trick.trickInit();
    }

    function enter() public gateOne gateTwo gateThree {
        entrant = tx.origin;
    }

    receive() external payable {}
}

2. GateOne

modifier gateOne() {
    require(msg.sender == owner);
    require(tx.origin != owner);
    _;
}

require(msg.sender == owner);

→ construct0r() 함수를 호출하여 onwer 변경할 수 있다

function construct0r() public {
    owner = msg.sender;
}

require(tx.origin != owner); → 예전에 했던 것처럼 2개의 컨트랙트를 만들어서 타고 타고 호출해주면된다.

이번 문제에서는 GatekeeperThreeScript에서 Attack 을 호출하여 GateKeeperThree 컨트랙트에 접근하겠다.


3. GateTwo

modifier gateTwo() {
    require(allowEntrance == true);
    _;
}