aere-contracts/contracts/oracle/AereDrandConsumer.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

64 lines
2.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import "./AereRandomnessBeacon.sol";
/**
* @title AereDrandConsumer
* @notice Reference example of consuming verifiable randomness on AERE.
* Pattern: dApp picks a future drand round, waits for it to be
* submitted (by anyone — typically the dApp itself), then reads
* the randomness.
*
* This is a minimal lottery — illustration only, not a production lottery.
* Any dApp on AERE can use the same pattern. Two lines of integration code.
*/
contract AereDrandConsumer {
AereRandomnessBeacon public immutable beacon;
uint64 public targetRound;
bytes32 public winnerSeed;
event RandomnessCommitted(uint64 targetRound, uint64 willResolveAt);
event RandomnessRevealed(uint64 round, bytes32 randomness, bytes32 winnerSeed);
constructor(AereRandomnessBeacon _beacon) {
beacon = _beacon;
}
/**
* @notice Commit to a future drand round as the source of randomness.
* The round must be in the future at commit time so its
* signature cannot already be known.
*/
function commitToFutureRound(uint64 minSecondsInFuture) external returns (uint64) {
uint64 targetTime = uint64(block.timestamp) + minSecondsInFuture;
targetRound = beacon.roundAtTime(targetTime);
emit RandomnessCommitted(targetRound, beacon.DRAND_GENESIS() + targetRound * beacon.DRAND_PERIOD());
return targetRound;
}
/**
* @notice Reveal the random outcome. Caller submits the drand signature
* for `targetRound` (anyone can; signature is public on api.drand.sh).
*/
function reveal(bytes calldata signature) external returns (bytes32 randomness) {
require(targetRound != 0, "Consumer: not committed");
randomness = beacon.submitRound(targetRound, signature);
// Derive the winnerSeed deterministically from the randomness + this contract.
winnerSeed = keccak256(abi.encodePacked(randomness, address(this), targetRound));
emit RandomnessRevealed(targetRound, randomness, winnerSeed);
}
/**
* @notice If the round has already been submitted by someone else,
* just consume it without paying gas for re-submission.
*/
function consumeExistingRound() external returns (bytes32 randomness) {
require(targetRound != 0, "Consumer: not committed");
randomness = beacon.getRandomness(targetRound);
require(randomness != bytes32(0), "Consumer: round not submitted yet");
winnerSeed = keccak256(abi.encodePacked(randomness, address(this), targetRound));
emit RandomnessRevealed(targetRound, randomness, winnerSeed);
}
}