CoinFlipper
A provably fair dice game using Full VRF — verifiable randomness on every tick.
Overview
CoinFlipper (RandomGame) is a dice game that rolls a fair 1-6 on every tick using ECVRF proof verification. Every roll is provably fair and tamper-proof.
- Base:
AutoLoopVRFCompatible - VRF: Every tick
- Gas: ~240,000 per tick
- Use case: Dice games, lotteries, coin flips, any game needing randomness on every tick
Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {AutoLoopVRFCompatible} from
"autoloop/AutoLoopVRFCompatible.sol";
contract RandomGame is AutoLoopVRFCompatible {
uint256 public lastRoll;
uint256 public totalRolls;
uint256 public interval;
uint256 public lastTimeStamp;
uint256[10] public rollHistory;
uint256 private _loopID;
event DiceRolled(
uint256 indexed loopID,
uint256 roll,
bytes32 randomness,
uint256 timestamp
);
constructor(uint256 _interval) {
interval = _interval;
lastTimeStamp = block.timestamp;
}
function shouldProgressLoop()
external view override
returns (
bool loopIsReady,
bytes memory progressWithData
)
{
loopIsReady =
(block.timestamp - lastTimeStamp) > interval;
progressWithData = abi.encode(_loopID);
}
function progressLoop(
bytes calldata progressWithData
) external override {
(bytes32 randomness, bytes memory gameData) =
_verifyAndExtractRandomness(
progressWithData, tx.origin
);
uint256 loopID =
abi.decode(gameData, (uint256));
require(loopID == _loopID, "stale");
lastRoll = (uint256(randomness) % 6) + 1;
rollHistory[totalRolls % 10] = lastRoll;
lastTimeStamp = block.timestamp;
emit DiceRolled(
_loopID, lastRoll, randomness, block.timestamp
);
++totalRolls;
++_loopID;
}
function getRecentRolls()
external view returns (uint256[10] memory)
{
return rollHistory;
}
}Deploy
forge create examples/CoinFlipper.sol:CoinFlipper \
--constructor-args 60 \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEYDon't forget to register the controller's VRF public key after deployment:
coinFlipper.registerControllerKey(controllerAddress, pkX, pkY);