跳至主要內容
本頁面使用機器翻譯自英語,可能包含錯誤或不清楚的語言。如需最準確的信息,請參閱英文原文。由於更新頻繁,部分內容可能與英文原文有出入。請加入我們在 Crowdin 上的努力,幫助我們改進本頁面的翻譯。 (Crowdin translation page, Contributing guide)

Verified Random Number Generator (vRNG)

This document serves as an overview of the Verified Random Number Generator (vRNG) guide by Proof of Play, designed for integration with Kaia provided. The vRNG system leverages the drand randomness beacon to deliver secure and verifiable random numbers to smart contracts on the Kaia blockchain.

The Verified Random Number Generator (vRNG) is optimized for low-latency delivery of random numbers to minimize application lag. It is designed with a strong emphasis on reliability and scalability.

Registration

During early access, all users of the Verified Random Number Generator system must be manually registered. In order to use it, your contract address must be approved, otherwise any requests will revert.

信息

Teams can request approval by either submitting through the official form, or by contacting the Kaia team directly, depending on which option is more convenient.

vRNG Contract Address

NetworkAddressAPI URL
Kaia Mainnet0xf628f7843d94064c5072704a53b9ec455bcc4abbhttps://vrf.proofofplay.com/v1
Kairos Testnet0xd14d984603b0b7ade91be52f3fc4a917dfa77bcdhttps://staging.vrf.proofofplay.com/v1

Usage

Requesting a Random Number

The following interface provides a method for requesting random numbers.

Your contract can call the VRFSystem deployed on each chain. You can optionally provide a traceId, which will be annotated to each event (Useful if you have one transaction that does many steps, users can trace their transactions on chain). This is not required and can be left as 0.


// SPDX-License-Identifier: MIT LICENSE
pragma solidity ^0.8.26;
uint256 constant ID = uint256(keccak256('com.proofofplay.vrfsystem.v1'));
interface IVRFSystem {
/**
* Starts a VRF random number request
*
* @param traceId Optional ID to use when tracing the request
* @return requestId for the random number, will be passed to the callback contract
*/
function requestRandomNumberWithTraceId(uint256 traceId) external returns (uint256);
}

Random Number Callbacks

Every random number requested is delivered as soon as the first number from drand is available to be delivered. This can take as long as 3 seconds.

備註

Your call will be delivered the first number after your first requestForRandomNumber has been submitted. This ensures the number can not be known before the user has requested the random number.


// SPDX-License-Identifier: MIT LICENSE
pragma solidity ^0.8.26;
interface IVRFSystemCallback {
/**
* Callback for when a Random Number is delivered
*
* @param requestId Id of the request
* @param randomNumber Random number that was generated by the Verified Random Number Generator Tool
*/
function randomNumberCallback(uint256 requestId, uint256 randomNumber) external;
}

What if I want to have different numbers in the same 3 second window?

By default, we deliver the same number to all requests inside the same 3 second window that drand provides. This is great to be able to verify, but if you would like to have users all have different numbers over this time period, we recommend you add a source of entropy.

Here's a couple of examples of having unique random numbers per transaction.


// Add the requestId (Most Gas Efficient)
uint256 newRandomNumber = requestId + randomNumber;
// Hash with requestId
uint256 newRandomNumber = uint256(keccak256(abi.encodePacked(requestId, randomNumber)
// More expensive, but more normalized, hash based on requestId in last 256 block hashes
uint256 newRandomNumber = uint256(keccak256(abi.encodePacked(blockhash(block.number - (requestId % 256)), randomNumber))

備註

These are not guaranteed to be normalized, but will retain the randomness properties of the above. We recommend adjusting to your liking to achieve more or less normalized (for instance, adding sequenceId to the randomNumber would be very skewed, whereas using a blockhash would be very normalized).

If you would like to have different numbers within the same block, we recommend re-hashing the same number multiple times in the same transaction


functionThatUsesNumber(randomNumber);
randomNumber = uint256(keccak256(randomNumber));
functionThatUsesNumber(randomNumber);

What if I want to have different numbers in the same transaction?

By default, we will give you only one number per transaction. We encourage developers to use this number to derive other numbers from this to create new numbers.


//Example 1: Keccak derive
uint256 randomNumber = 12398012938091283113928;
uint256 randomNumber2 = keccak256(randomNumber);
uint256 randomNumber3 = keccak256(randomNumber2);
//Example 2: Split the number and use both sides
uint256 randomNumber = 234345234523452345;
uint256 randomNumber2 = randomNumber >> 128; // Take upper 128 bits
uint256 randomNumber3 = randomNumber & ((1 << 128) - 1); // Take lower 128 bits

Blockchain Events

The contract will emit the following events.


/// @notice Emitted when a random number request is initiated
/// @param requestId The unique identifier for the random number request
/// @param callbackAddress The address to which the random number is requested
/// @param traceId The trace ID used to track the request across transactions (0 if no trace ID)
event RandomNumberRequested(uint256 indexed requestId, address indexed callbackAddress, uint256 indexed traceId);
/// @notice Emitted when a random number is successfully delivered
/// @param requestId The unique identifier of the fulfilled request
/// @param callbackAddress the address was random number is requested to
/// @param traceId The trace ID associated with the request
/// @param number The round number that was used for the random number
/// @param randomNumber The random number that was generated
event RandomNumberDelivered(uint256 indexed requestId, address indexed callbackAddress, uint256 indexed traceId, uint256 roundNumber, uint256 randomNumber);

You can query these events on RPC level to see if they were delivered or use the block explorer to view a stream of events.

Verifying the round number / random number with drand

If you want to verify the random number, you can check directly with drand for this. We use drand's quicknet for this.

For instance, to see the roundNumber 11:

GET https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/11


{
"round": 11,
"randomness": "ebdcbfe855d10c56db22455fa5a18963c1f62d85f859c35c310273449b49d284",
"signature": "163d14081e191a3f5d81e2f580eab591ea608402fda4f6e44b5a0bde11e368070e77d07ad3240726ea33e410c84d4b09ea0a4a0291f6c3c485d8630e1c0edf0a"
}

We can see here the random number in hex is ebdcbfe855d10c56db22455fa5a18963c1f62d85f859c35c310273449b49d284

Manual Retries with EIP712 signatures

信息

This feature is in preview. Please contact the Kaia team if you wish to use this.

In a very rare instance, you may see random numbers fail to be delivered. In most cases, this will be an issue on the contract side.

In these situations, you can choose to deliver this number yourself. First you should request the EIP712 signature from our API servers which you can use to deliver the random number directly to the contract on the blockchain.

Request:


GET https://vrf.proofofplay.com/v1/vrf/{chainId}/{txHash}

Response:


{
"requestId": Number,
"roundNumber": Number,
"randomNumber": BigInt,
"signature": String // bytes data of signature
}

With the response you can now call the VRFSystem contract


vrf.deliverSignedRandomNumber(requestId, roundNumber, randomNumber, signature);

警告

You will be racing the normal relay flow. If you get a tx revert with InvalidRequestId, this means that a relay has already delivered this random number. Random numbers can only be delivered once.

讓這個頁面變得更好