On-chain VDF verifier enabling trustless, tamper-resistant randomness on EVM.
Seedy provides secure, unpredictable, and highly tamper-resistant randomness for smart contracts. Current on-chain randomness methods often rely on manipulable blockhashes or trusted/costly oracles. Seedy leverages Verifiable Delay Functions (VDFs), specifically the Pietrzak scheme optimized for EVM based on Lee et al.'s research.
How it works: An off-chain prover computes the VDF output (y) and proof (pi) over a time delay T, using an on-chain derived seed (x). An on-chain SeedyVerifier contract that efficiently verifies the submitted proof pi against x, y, T, and delta using the ModExp precompile and cryptographic hashing.
An on-chain SeedyCoordinator manages requests and provides the final random number (derived from hashing the verified y) to consuming applications like the demo Raffle contract.
Seedy is based on trustless on-chain verification – the smart contract itself validates the VDF computation, ensuring fairness and resistance to manipulation without external dependencies for the proof check.
Smart Contracts (Solidity):
SeedyVerifier.sol: Implements the Pietrzak VDF verification logic (Algorithm 4 from Lee et al.), including the recursive steps and the final y == x^(2^(2^delta)) mod N check using repeated squaring. I heavily utilized the EIP-198 ModExp precompile via a custom assembly wrapper (_modExp) for crucial modular exponentiation steps.
SeedyCoordinator.sol: Manages randomness requests, calls the Verifier, computes/stores the final random hash (keccak256(verified_y)). Conceptually uses blockhash for seeding via computeSeed.
Raffle.sol: Example application consuming the randomness from the Coordinator. Big Numbers: Utilized the provided BigNumbers.sol library for handling arithmetic operations (init, mul) on numbers larger than 256 bits required by the VDF modulus (N).
Off-Chain Prover (TypeScript): A script using Node.js and BigInt (with libraries like bigint-crypto-utils for modPow) to perform the VDF evaluation (evaluateVDF) and generate the proof elements (generateProof).
Challenges: Library Workaround: The BigNumbers.sol library had critical internal bugs (e.g., faulty zero-trimming in its _modexp return value) breaking its mod and modmul functions. I bypassed this by using the library's mul (which seemed to work for plain multiplication) combined with my own direct _modExp call (using exponent 1) to perform the necessary modular multiplications within the verifier (_calculate_new_xi/_yi).