Description
Generating random numbers was difficult before the Oracles. People had to simulate randomness using built-in variables like sha3(block.number)
.
How to Submit a Solution:
Use the below submission form to submit the solution: https://quillaudits.typeform.com/QuillCTF
Objective of CTF:
In this game, you can spend 1 ether to "mint" an NFT token with 3 possible ranks: Common(1), Rare(2), and Superior(3). As a hacker, your goal is to always mint the Superior ones.
Note: You can create POCs using Foundry/Hardhat. Without proper POC, your submissions will not be accepted.
Contract:
So this time, the contract isn't open source, but who needs that anyway?
You can find the underlying contract of this game on the Goerli Testnet.
Contract Address: 0xFD3CbdbD9D1bBe0452eFB1d1BFFa94C8468A66fC
Foundry setUp:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^ 0.8.19;
import "forge-std/Test.sol";
contract PredictableNFTTest is Test {
address nft;
address hacker = address(0x1234);
function setUp() public {
vm.createSelectFork("goerli");
vm.deal(hacker, 1 ether);
nft = address(0xFD3CbdbD9D1bBe0452eFB1d1BFFa94C8468A66fC);
}
function test() public {
vm.startPrank(hacker);
uint mintedId;
uint currentBlockNum = block.number;
// Mint a Superior one, and do it within the next 100 blocks.
for(uint i=0; i<100; i++) {
vm.roll(currentBlockNum);
// ---- hacking time ----
currentBlockNum++;
}
// get rank from `mapping(tokenId => rank)`
(, bytes memory ret) = nft.call(abi.encodeWithSignature(
"tokens(uint256)",
mintedId
));
uint mintedRank = uint(bytes32(ret));
assertEq(mintedRank, 3, "not Superior(rank != 3)");
}
}