Pelusa

Idea

We have to overcome 3 barriers:

  1. passTheBall()

  2. getBallPossesion()

  3. shoot()

1. passTheBall()

    function passTheBall() external {
        require(msg.sender.code.length == 0, "Only EOA players");
        require(uint256(uint160(msg.sender)) % 100 == 10, "not allowed");

        player = msg.sender;
    }

The first require can be bypassed by storing all code in the constructor. The second require is about bruteforcing create2() salt but it is a very simple bruteforce. Note that the probability of xmod10010x \mod 100 \equiv 10 is 1100\frac{1}{100} if we are bruteforcing xx.

2. getBallPossesion()

    function isGoal() public view returns (bool) {
        // expect ball in owners posession
        return IGame(player).getBallPossesion() == owner;
    }
    constructor() {
        owner = address(uint160(uint256(keccak256(abi.encodePacked(msg.sender, blockhash(block.number))))));
    }

Just re-compute owner locally.

3. shoot()

    function shoot() external {
        require(isGoal(), "missed");
		/// @dev use "the hand of god" trick
        (bool success, bytes memory data) = player.delegatecall(abi.encodeWithSignature("handOfGod()"));
        require(success, "missed");
        require(uint256(bytes32(data)) == 22_06_1986);
    }

Returning 22_06_1986 is easy. Updating goals to 2 via delegatecall is also a simple task.

PoC

Last updated