Tags: web3py 

Rating:

These are the challenge contracts

```
# Setup.sol
pragma solidity ^0.8.18;

import {ShootingArea} from "./ShootingArea.sol";

contract Setup {
ShootingArea public immutable TARGET;

constructor() {
TARGET = new ShootingArea();
}

function isSolved() public view returns (bool) {
return TARGET.firstShot() && TARGET.secondShot() && TARGET.thirdShot();
}
}
```

```
# ShootingArea.sol
pragma solidity ^0.8.18;

contract ShootingArea {
bool public firstShot;
bool public secondShot;
bool public thirdShot;

modifier firstTarget() {
require(!firstShot && !secondShot && !thirdShot);
_;
}

modifier secondTarget() {
require(firstShot && !secondShot && !thirdShot);
_;
}

modifier thirdTarget() {
require(firstShot && secondShot && !thirdShot);
_;
}

receive() external payable secondTarget {
secondShot = true;
}

fallback() external payable firstTarget {
firstShot = true;
}

function third() public thirdTarget {
thirdShot = true;
}
}
```

The modifiers basically put the function at the "\_;". In this case the contract forces you to call `fallback`, `receive` and `third` in order. However, `fallback` and `receive` are special functions, as documented [here](https://docs.soliditylang.org/en/v0.8.19/contracts.html#special-functions).

The `fallback` function is called when the contract receives a call for a function it does not know and the `receive` function is called when the contract receives money without a function call. To trigger fallback I added the following function to my local ShootingArea code.

```
function invalid(uint x) public {
thirdShot = true;
}
```

Then I used the following script to communicate to the blockchain:

```python
from web3 import Web3
from solcx import compile_files

addr = "0xf5Eb625F3BCfc73021cCC0cadf935EB22Cbe80d4"
target = "0x3ac666e2c809Ba6d471ad501925de80d23566599"

compiled = compile_files(["ShootingArea.sol"], output_values=["abi"], solc_version="0.8.18")
abi = compiled['ShootingArea.sol:ShootingArea']['abi']

w3 = Web3(Web3.HTTPProvider('http://68.183.37.122:31550'))
print("current balance", w3.eth.get_balance(addr), "wei")

contract = w3.eth.contract(address=target, abi=abi)

# invalid function added to source with an uint parameter
# first target calls fallback (special function)
contract.functions.invalid(10).transact()
# second target calls receive (special function)
w3.eth.send_transaction({"from":addr, "to":target,"value":1,})
# third target calls third
contract.functions.third().transact()
```

The flag is `HTB{f33l5_n1c3_h1771n6_y0ur_74r6375}`