Initialize the VRF Oracle contract.
fee_token: SAC token address used to charge per-request fees.fee_amount: Amount of fee_token charged per VRF request (transferred
from requester to oracle). Set to 0 for fee-free operation.fn init(
env: soroban_sdk::Env,
oracle_pk: soroban_sdk::BytesN<192>,
oracle_address: soroban_sdk::Address,
oracle_ed25519_pk: soroban_sdk::BytesN<32>,
drand_pk: soroban_sdk::BytesN<192>,
g2_generator: soroban_sdk::BytesN<192>,
drand_genesis_time: u64,
drand_period: u32,
round_offset: u32,
fee_token: soroban_sdk::Address,
fee_amount: i128,
)
Fulfill a VRF request with a BLS proof and oracle Ed25519 signature.
Fulfilled = true and store proof BEFORE any external call.fulfill() calls.DataKey::Fulfilling(request_id) is set to true before callback invocation
and cleared after. Any re-entrant call to fulfill() for the same request_id
will see Fulfilling = true and panic with "fulfill already in progress".
This provides defense-in-depth alongside the Fulfilled = true check.
fn fulfill(
env: soroban_sdk::Env,
request_id: u64,
proof: BlsVrfProof,
signature: soroban_sdk::BytesN<64>,
)
fn request(
env: soroban_sdk::Env,
context: soroban_sdk::Bytes,
requester: soroban_sdk::Address,
) -> u64
fn get_proof(env: soroban_sdk::Env, request_id: u64) -> BlsVrfProof
fn oracle_pk(env: soroban_sdk::Env) -> soroban_sdk::BytesN<192>
fn callback_of(
env: soroban_sdk::Env,
request_id: u64,
) -> Option<(soroban_sdk::Address, soroban_sdk::Symbol)>
fn get_context(env: soroban_sdk::Env, request_id: u64) -> soroban_sdk::Bytes
fn is_refunded(env: soroban_sdk::Env, request_id: u64) -> bool
fn is_fulfilled(env: soroban_sdk::Env, request_id: u64) -> bool
fn requester_of(env: soroban_sdk::Env, request_id: u64) -> soroban_sdk::Address
Allows the requester (or oracle) to remove proof data for a fulfilled request, reclaiming the associated storage rent. The fulfillment flag is preserved.
After cleanup, DataKey::Proof is removed but DataKey::Fulfilled is kept.
Callers relying on is_fulfilled() will continue to get true.
Callers calling get_proof() or derive_random() after cleanup will panic —
consumers must call derive_random() before cleanup or cache the result.
fn cleanup_proof(env: soroban_sdk::Env, request_id: u64, caller: soroban_sdk::Address)
fn derive_random(
env: soroban_sdk::Env,
request_id: u64,
context: soroban_sdk::Bytes,
) -> u64
fn request_round(env: soroban_sdk::Env, request_id: u64) -> u64
fn oracle_address(env: soroban_sdk::Env) -> soroban_sdk::Address
fn timeout_refund(env: soroban_sdk::Env, request_id: u64)
fn timeout_rounds(env: soroban_sdk::Env) -> u64
Rotate the drand public key used to verify BLS beacon signatures.
This is required when the drand network performs a key rotation or when switching to a different drand chain (e.g., quicknet → a future chain).
The current oracle must authorize this call.
fn rotate_drand_pk(env: soroban_sdk::Env, new_drand_pk: soroban_sdk::BytesN<192>)
Rotate the oracle's BLS public key, Stellar address, and Ed25519 signing key.
The current oracle address must authorize this call. This prevents an attacker who obtains a new keypair from hijacking the oracle role.
Pending requests are not locked to the oracle key that was active at
request time. At fulfillment, fulfill() checks the currently configured
oracle key in instance storage. This means:
Best practice: rotate keys only after the new oracle node is running and ready to fulfill requests, to avoid a gap where no oracle is active.
fn rotate_oracle_keys(
env: soroban_sdk::Env,
new_oracle_pk: soroban_sdk::BytesN<192>,
new_oracle_address: soroban_sdk::Address,
new_oracle_ed25519_pk: soroban_sdk::BytesN<32>,
)
Request verifiable randomness with an on-chain callback.
callback_contract must equal requester: only contracts requesting
randomness for themselves may receive callbacks.callback_contract.require_auth() is enforced to ensure authorization.callback_fn is restricted to on_vrf to prevent arbitrary dispatch.fn request_with_callback(
env: soroban_sdk::Env,
context: soroban_sdk::Bytes,
requester: soroban_sdk::Address,
callback_contract: soroban_sdk::Address,
callback_fn: soroban_sdk::Symbol,
) -> u64
Derives a random u64 in the range [0, max) with no modulo bias. Uses iterative hashing (rejection sampling variant) to ensure uniform distribution. Worst-case bounded at 10 iterations (p < 2^-640 of exceeding).
fn derive_random_in_range(
env: soroban_sdk::Env,
request_id: u64,
context: soroban_sdk::Bytes,
max: u64,
) -> u64