Understanding QRNG
The API3 QRNG service is implemented using the Airnode request–response protocol contract AirnodeRrpV0 (by way of RrpRequesterV0.sol) to acquire a random number.
QRNG example project
After reading this page, visit and run the QRNG Example project in the qrng-example
repo.
In the diagram below a requester (smart contract) submits a request for a quantum random number to the on-chain AirnodeRrpV0
protocol contract using its makeFullRequest()
function. The off-chain Airnode gathers the request from the AirnodeRrpV0
protocol contract, gets the random number from an API operation and sends it back to AirnodeRrpV0
. Once received, AirnodeRrpV0
performs a callback to the requester with the quantum random number.
Calling AirnodeRrpV0
for a quantum random number is the same as any Airnode RRP request. Read more about how a requester accesses an Airnode to acquire data from API operations.
Requesters
A requester (smart contract) calls the QRNG service using the request–response protocol (RRP) implemented by the on-chain AirnodeRrpV0
contract. The contract RrpRequesterV0.sol is meant to be inherited by any requester that will be making requests to AirnodeRrpV0. It is part of the NPM @api3/airnode-protocol package.
In practice, the requester implements two functions that are specific to requesting and receiving a random number from the QRNG service. Consider the following flow (extracted from the QRNG example contract) to understand how to call for a random number.
The function
makeRequestUint256()
callsairnodeRrp.makeFullRequest()
to request a random number, which in turn returns arequestId
. TherequestId
is stored in the mappingexpectingRequestWithIdToBeFulfilled
for reference in the callback function.The requester has a function
fulfillUint256
(the function name is user-defined) as the callback to receive the random number from the QRNG service. The callback contains therequestId
returned by the initial request and thedata
, which contains the random number. TherequestId
is verified and removed from the mappingexpectingRequestWithIdToBeFulfilled
.
import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol";
...
function makeRequestUint256() external {
bytes32 requestId = airnodeRrp.makeFullRequest(
airnode,
endpointIdUint256,
address(this),
sponsorWallet,
address(this),
this.fulfillUint256.selector,
""
);
expectingRequestWithIdToBeFulfilled[requestId] = true;
emit RequestedUint256(requestId);
}
...
function fulfillUint256(bytes32 requestId, bytes calldata data)
external
onlyAirnodeRrp
{
require(
expectingRequestWithIdToBeFulfilled[requestId],
"Request ID not known"
);
expectingRequestWithIdToBeFulfilled[requestId] = false;
uint256 qrngUint256 = abi.decode(data, (uint256));
// Do what you want with `qrngUint256` here...
emit ReceivedUint256(requestId, qrngUint256);
}
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
See QrngExample.sol for a complete example.
An additional pair of functions (makeRequestUint256Array() and fulfillUint256Array()) can be used to acquire an array of random numbers.
See the guide Using QRNG - Remix Example for an in-depth tutorial on how use QRNG. Also see the QRNG Example repo, an example project that demonstrates the usage of the Airnode request–response protocol to receive API3 QRNG services.
Gas Costs
Using the QRNG service is free, meaning there is no subscription fee to pay. There is a gas cost incurred on-chain when Airnode places the random number on-chain in response to a request, which the requester needs to pay for.
FLEX_END_TAG