> For the complete documentation index, see [llms.txt](https://ret2basic.gitbook.io/ctfwriteup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/quillctf/pelusa.md).

# Pelusa

## Idea

We have to overcome 3 barriers:

1. `passTheBall()`
2. `getBallPossesion()`
3. `shoot()`

### 1. passTheBall()

```solidity
    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 $$x \mod 100 \equiv 10$$ is $$\frac{1}{100}$$ if we are bruteforcing $$x$$.

### 2. getBallPossesion()

```solidity
    function isGoal() public view returns (bool) {
        // expect ball in owners posession
        return IGame(player).getBallPossesion() == owner;
    }
```

```solidity
    constructor() {
        owner = address(uint160(uint256(keccak256(abi.encodePacked(msg.sender, blockhash(block.number))))));
    }
```

Just re-compute `owner` locally.&#x20;

### 3. shoot()

```solidity
    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

{% embed url="<https://github.com/ret2basic/QuillCTF-PoC/blob/main/Pelusa/test/Pelusa.t.sol>" %}
Pelusa PoC
{% endembed %}
