Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions apps/web/content/docs/examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,24 @@ fn request_random_number(seed: b256) -> u64 {
let request_id = simple_vrf.request{
asset_id: AssetId::base().bits(),
coins: fee,
}(seed);
}(seed, None); // Default callback behavior (enabled)
request_id
}

fn request_random_number_no_callback(seed: b256) -> u64 {
let simple_vrf = abi(SimpleVrf, vrf_id);
let fee = simple_vrf.get_fee(AssetId::base());
let request_id = simple_vrf.request{
asset_id: AssetId::base().bits(),
coins: fee,
}(seed, Some(false)); // Disable callback - useful for scripts
request_id
}
```

- Implement the callback to receive the proof.
- Call `request_random_number(seed)` to request randomness.
- Call `request_random_number(seed)` to request randomness with callback enabled (default).
- Call `request_random_number_no_callback(seed)` to request randomness without callback (useful for scripts).

---

Expand All @@ -52,7 +63,7 @@ abi SampleVrfContract {

#[payable]
#[storage(read, write)]
fn request(seed: b256) -> u64;
fn request(seed: b256, callback: Option<bool>) -> u64;
Copy link
Copy Markdown

@IGI-111 IGI-111 Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the logic behind making it an Option. This will still be incompatible with all previous usages, since the function selector hash includes the arguments.

If you want backwards compatibility, a better way would be to have a fn request_without_callback(seed: b256) -> u64.

If you're willing to break the interface however, I think making it an Option<b256> makes more sense, allowing the callback to be another contract than the caller:

// same behavior as current usage
let rid = request(seed, Some(CONTRACT_ID));
// no callback
let rid = request(seed, None);
// call another contract
let rid = request(seed, Some(other_contract_id));


#[storage(read)]
fn get_latest_proof() -> b256;
Expand Down Expand Up @@ -85,15 +96,15 @@ impl SampleVrfContract for Contract {

#[payable]
#[storage(read, write)]
fn request(seed: b256) -> u64 {
fn request(seed: b256, callback: Option<bool>) -> u64 {
let vrf_id = storage.vrf_id.try_read().unwrap();
storage.seed.write(seed);
let simple_vrf = abi(SimpleVrf, vrf_id);
let fee = simple_vrf.get_fee(AssetId::base());
let request_id = simple_vrf.request{
asset_id: AssetId::base().bits(),
coins: fee,
}(seed);
}(seed, callback);
request_id
}

Expand All @@ -116,10 +127,14 @@ impl SampleVrfContract for Contract {

### How it works
- The contract implements a callback interface (`SimpleVrfCallback`) to receive the random proof.
- The `request(seed)` function stores the seed, fetches the fee, and calls the SimpleVrf contract to request randomness.
- The callback (`simplevrf_callback` or `simple_callback`) is triggered by SimpleVrf when the proof is ready, storing the result in contract storage.
- The `request(seed, callback)` function stores the seed, fetches the fee, and calls the SimpleVrf contract to request randomness with optional callback control.
- The callback (`simplevrf_callback` or `simple_callback`) is triggered by SimpleVrf when the proof is ready (if callback is enabled), storing the result in contract storage.
- Helper functions allow reading the latest proof and seed, and setting the VRF contract address.

### Callback Parameter Options:
- `None` or `Some(true)` – Enable callback (default behavior)
- `Some(false)` – Disable callback, useful when calling from scripts or when you want to manually check for fulfillment

---

You can use this pattern to integrate verifiable randomness into your own Fuel contracts. For more, see the [SimpleVrf ABI documentation](./smart-contracts/simple-vrf).
19 changes: 17 additions & 2 deletions apps/web/content/docs/smart-contracts/simple-vrf.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct Request {
pub proof: ChunkedProof,
pub fullfilled_by: Address,
pub callback_contract: Identity,
pub should_callback: bool,
}

abi SimpleVrfCallback {
Expand Down Expand Up @@ -63,7 +64,7 @@ abi SimpleVrf {

#[payable]
#[storage(read, write)]
fn request(seed: b256) -> u64;
fn request(seed: b256, callback: Option<bool>) -> u64;

#[storage(read, write)]
fn submit_proof(seed: b256, proof: ChunkedProof) -> bool;
Expand All @@ -74,7 +75,7 @@ The SimpleVrf Fuel contract exposes the following key methods:

## Request Management

- `request(seed)` – Create a new randomness request
- `request(seed, callback)` – Create a new randomness request with optional callback control (defaults to true)
- `get_request(seed)` – Get details of a request
- `get_request_count()` – Get the total number of requests
- `get_unfinalized_requests()` – List all pending requests
Expand All @@ -98,6 +99,20 @@ The SimpleVrf Fuel contract exposes the following key methods:

- `simplevrf_callback(seed, proof)` – Called by the contract when randomness is fulfilled

### Callback Control

The `request` function now accepts an optional `callback` parameter:

- `callback: Some(true)` (default) – Enable callback when request is fulfilled
- `callback: Some(false)` – Disable callback, useful when calling from scripts
- `callback: None` – Defaults to true (enabled)

When `callback` is set to `false`, the contract will fulfill the request and store the proof, but will not attempt to call back to the requesting contract. This is particularly useful when:

- Making requests from Fuel scripts (which cannot receive callbacks)
- You want to manually check for fulfillment later
- The requesting contract doesn't implement the callback interface

---

See [Example Integration](../examples) for usage in your own contracts.
Loading