This Cartridge Verfiable Random Function (VRF) is designed to provide cheap, atomic verfiable randomness for fully onchain games.
-
Atomic Execution: The VRF request and response are processed within the same transaction, ensuring synchronous and immediate randomness for games.
-
Efficient Onchain Verification: Utilizes the Stark curve and Poseidon hash for optimized verification on Starknet.
-
Fully Onchain: The entire VRF process occurs onchain, maintaining transparency and verifiability.
-
Improved Player Experience: The synchronous nature of the VRF allows for instant resolution of random events in games, enhancing gameplay fluidity.
- A game calls
request_random(caller, source)
as the first call in their multicall. - A game contract calls
consume_random(source)
on the VRF contract. - The VRF server generates a random value using the VRF algorithm for the provided entropy source.
- The Cartridge Paymaster wraps the players multicall with a
submit_random
andassert_consumed
call. - The
submit_random
call submit a VRF Proof for the request, the VRF Proof is verified onchain, ensuring the integrity of the random value which is immediately available and must be used within the same transaction. - The
assert_consumed
call ensures thatconsume_random(source)
has been called, it also reset the storage used to store the random value during the transaction to 0.
- Simplicity: Easy integration with existing Starknet smart contracts and Dojo.
- Performance: Synchronous randomness generation without waiting for multiple transactions.
- Cost-effectiveness: Potential cost savings through Paymaster integration.
- Security: Cryptographically secure randomness that's fully verifiable onchain.
To integrate the Verifiable Random Function (VRF) into your Starknet contract, follow these steps:
- Import the VRF Provider interface:
use cartridge_vrf::IVrfProviderDispatcher;
use cartridge_vrf::IVrfProviderDispatcherTrait;
use cartridge_vrf::Source;
- Define the VRF Provider address in your contract:
const VRF_PROVIDER_ADDRESS: starknet::ContractAddress = starknet::contract_address_const::<0x123>();
- Create a dispatcher for the VRF Provider:
let vrf_provider = IVrfProviderDispatcher { contract_address: VRF_PROVIDER_ADDRESS };
- To consume random values, use the following pattern in your contract functions:
fn roll_dice(ref self: ContractState) {
// Your game logic here...
// Consume random value
let player_id = get_caller_address();
let random_value = vrf_provider.consume_random(Source::Nonce(player_id));
// Use the random value in your game logic
// ...
}
-
You can use either
Source::Nonce(ContractAddress)
orSource::Salt(felt252)
as the source for randomness:-
Source::Nonce(ContractAddress)
: Uses the provided contract address internal nonce for randomness.
Each request will generate a different seed ensuring unique random values. -
Source::Salt(felt252)
: Uses a provided salt value for randomness.
Two requests with same salts will result in same random value.
-
In order to execute a transaction that includes a consume_random
call, you need to include a request_random
transaction as the first transaction in the multicall. The request_random
call allows our server to efficiently parse transactions that include a consume_random
call internally.
const call = await account.execute([
// Prefix the multicall with the
{
contractAddress: VRF_PROVIDER_ADDRESS,
entrypoint: 'request_random',
calldata: CallData.compile({
caller: GAME_CONTRACT,
// Using Source::Nonce(address)
source: [0, address],
}),
},
{
contractAddress: GAME_CONTRACT,
entrypoint: 'roll_dice',
...
},
]);
Ensure that you call consume_random
with the same Source
as used in request_random
.
By following these steps, you can integrate the VRF Provider into your Starknet contract and generate verifiable random numbers for your onchain game or application.