Native VRF Randomness
TOS provides Verifiable Random Functions (VRF) at the protocol level, enabling secure, unpredictable, and verifiable random numbers at $0.01 per request.
Implementation Status
| Feature | Status |
|---|---|
| Block VRF proof generation | Implemented |
| vrf_random syscall | Implemented |
| vrf_verify syscall | Implemented |
| vrf_public_key syscall | Implemented |
| Instant randomness | Implemented |
| Delayed randomness (10 blocks) | Implemented |
Why VRF?
Block hashes are NOT secure for randomness:
Block N: Player bets → Chooses "High"
Block N+1: Miner sees bet → Can manipulate block
by reordering transactions until favorable
VRF Properties:
âś“ Verifiable: Anyone can verify correctness
âś“ Unpredictable: Unknown before generation
âś“ Unmanipulable: Generator cannot choose outputCost Comparison
| Operation | Chainlink VRF (BSC) | TOS Native |
|---|---|---|
| Request random | $0.25 | $0.01 |
| Get result | $0.05 | $0.001 |
| Instant random | N/A | $0.005 |
| Batch (10) | $2.50 | $0.08 |
25x cheaper than Chainlink VRF.
Randomness Types
| Type | Latency | Security | Use Case |
|---|---|---|---|
| Instant | 0 blocks | Medium | Low-stakes games |
| Block VRF | 0 blocks | High | Most applications |
| Delayed | 10 blocks | Maximum | High-stakes gambling |
Syscall Reference
/// Generate VRF random number
/// Cost: 10,000 CU
pub fn vrf_random(seed: &[u8]) -> Result<VRFOutput, u64>;
/// Verify VRF proof
/// Cost: 5,000 CU
pub fn vrf_verify(
public_key: &[u8; 32],
input: &[u8; 32],
pre_output: &[u8; 32],
proof: &[u8; 64],
) -> Result<(), u64>;
/// Get current block's VRF public key
/// Cost: 100 CU
pub fn vrf_public_key() -> Result<[u8; 32], u64>;VRF Output
pub struct VRFOutput {
/// 32-byte random value
pub random: [u8; 32],
/// Pre-output for verification
pub pre_output: [u8; 32],
/// Cryptographic proof (64 bytes)
pub proof: [u8; 64],
}Examples
Dice Roll
fn roll_dice() -> u8 {
let seed = get_block_hash();
let output = vrf_random(&seed).expect("VRF failed");
// Map to 1-6
(output.random[0] % 6) + 1
}NFT Rarity
fn determine_rarity() -> Rarity {
let seed = get_block_hash();
let output = vrf_random(&seed).expect("VRF failed");
let roll = u16::from_le_bytes([
output.random[0],
output.random[1],
]) % 10000;
match roll {
0..=49 => Rarity::Legendary, // 0.5%
50..=499 => Rarity::Epic, // 4.5%
500..=1999 => Rarity::Rare, // 15%
_ => Rarity::Common, // 80%
}
}Verified Gambling
fn bet_high_low(choice: u8) {
let player = get_tx_sender();
let bet = get_call_value();
// Generate VRF
let seed = get_block_hash();
let output = vrf_random(&seed).expect("VRF failed");
// Verify for transparency
let pk = vrf_public_key().unwrap();
vrf_verify(&pk, &seed, &output.pre_output, &output.proof)
.expect("Verification failed");
// Roll 0-99
let roll = output.random[0] % 100;
let player_wins = (roll < 50 && choice == 0) ||
(roll >= 50 && choice == 1);
if player_wins {
let payout = bet * 195 / 100; // 1.95x
transfer(&player, payout).ok();
}
// Log for verification
log_u64(roll as u64, choice as u64, bet, 0, 0);
}Security Guarantees
Cryptographic Standard
- EC-VRF (Elliptic Curve VRF)
- IETF draft-irtf-cfrg-vrf-15 compliant
Anti-Manipulation
- Random generated by validator set
- Single validator cannot predict output
- Request-response prevents front-running
Verifiability
- Proof stored on-chain permanently
- Anyone can verify correctness
- Mathematical guarantee of fairness
Best Practices
- Always use unique seeds - Include contract address or tx data
- Verify for high-stakes - Call vrf_verify for transparency
- Store proofs - Enable post-hoc auditing
- Log results - Let users verify outcomes
See Also
- Why TOS: VRF Randomness - Overview
- Contract Example: VRF Random - Implementation
Last updated on