TossUp is an attempt to achieve on-chain psuedorandomness disguised as a head to head coin flip like game. My half baked idea is to indirectly leverage VRF by accessing block proposers in the avm with pragma v11.
The project consists of:
- Smart contracts written in TealScript that manage the game logic and funds
- A Next.js frontend that provides a user-friendly interface to interact with the contracts
- A "register and play" system where users can either create games or play existing games created by others
- Classic: Uses the randomness seen in the main branch of the repo
- Funk: Uses randomness found in this branch which was inspired by a convo on algorand discord
- Switch to the "Register Game" tab
- Enter your amount in MicroAlgos (1 ALGO = 1,000,000 MicroAlgo)
- Click "Register Game" to create a new game instance
- The transaction will be signed with your connected Algorand wallet
- Once confirmed, your game will be available for others to play
- Switch to the "Open Games" tab
- Browse available games - each card shows the owner's address and the amount
- Click "Play" on any game to match the amount and play
- The outcome will be determined by the random mechanism in the smart contract
- Funds will be automatically transferred to the winner
The dashboard header displays:
- Total owner (house) wins
- Total player wins
- Owner win percentage
Click "Refresh Stats" to update the displayed information.
Classic: 736389917 Funk: 736470454
The smart contracts are opensource and can be found in their entirerty here
The GameMaker contract is responsible for:
- Creating new TossUp game instances
- Tracking game results (owner wins vs player wins)
- Managing the deployment of individual games
Key methods:
createApplication()
: Initializes the game bookkeeping contractregister(payment)
: Creates a new TossUp game with the provided amountplay(payment, appID)
: Plays a game and records the result
The TossUp contract handles the logic for individual games:
- Holds the game funds
- Implements the random outcome generator
- returns the random outcome to the GameMaker contract
Key methods:
register(payment, owner)
: Initializes a game with the owner and amountplay(payment, player)
: Executes the game logic and distributes fundsgetRandom(player)
: Generates a pseudo-random number for fair outcome determination
The getRandom()
function in TossUp.algo.ts generates randomness through a multi-step process that draws entropy from blockchain data:
private getRandom(player: Address): uint64 {
let seed: uint64;
const blockSeed =
extractUint64(blocks[this.txn.firstValid - 1].seed, blocks[this.txn.firstValid - 1].timestamp % 24) % 24;
const proposer = blocks[this.txn.firstValid - 1].proposer;
const maxSeed = 4294967295; // maximum uint that prevents overflow
const playerSeed = extractUint64(player, blockSeed) % maxSeed;
const ownerSeed = extractUint64(this.owner.value, blockSeed) % maxSeed;
const intraRoundRandomness = (playerSeed * ownerSeed) % 24;
if (proposer === globals.zeroAddress) {
// For localnet testing
seed = extractUint64(player, intraRoundRandomness);
} else {
seed = extractUint64(proposer, intraRoundRandomness);
}
return seed;
}
The randomness generation works as follows:
-
Block-derived entropy: Uses data from the previous block including:
- Block seed
- Block timestamp
- Block proposer
-
Player-specific entropy:
- Extracts a value from the player's address
- Extracts a value from the owner's address
- Combines these with the block-derived values
-
Combination logic:
- Multiplies player and owner derived values
- Modulo operations ensure values stay within acceptable ranges
-
Final outcome:
- Returns the seed value
- Game outcome is determined by whether the seed is even or odd (
seed % 2
)
I would love for this to be improved upon in many ways, here are a few ideas:
-
Tournament Mode
- Allow users to organize tournaments with multiple rounds
- Create brackets and elimination structures
-
Time-based Mechanics
- Add time limits for game participation
- Implement auto-refunds for games not played within time limits
-
Game History
- Add a personal game history section
- Implement replay functionality
-
Social Features
- Support for NF Domains
- Add a leaderboard for top players
-
Enhanced Visualizations
- Animated coin flip
- Visual indicators of randomness sources
To verify the 50/50 outcome distribution:
-
Statistical Analysis Framework
- Develop a test framework to simulate thousands of games
- Apply statistical tests (chi-square, z-test) to evaluate fairness
-
Real-world Analysis Dashboard
- Track actual game outcomes over time
- Visualize distribution and detect anomalies
-
Compare Alternative Implementations
- Implement multiple randomness algorithms in test environments
- Compare their statistical properties against the current algorithm
- Smart Contract Development:
- Frontend:
- use-wallet
- Next.js
- React
- Tailwind CSS
- shadcn/ui components