# How to use API3 QRNG
The API3 QRNG service is implemented using the Airnode request–response protocol contract, AirnodeRrpV0 (opens new window), to acquire a random number.
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.
# How it Works
Upon request, Airnode calls a designated API operation and
acquires a random number and then delivers it on-chain, via the AirnodeRrpV0
protocol contract, to a requester.
In the diagram below a requester (smart contract) submits a request for a random
number to AirnodeRrpV0
. 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 random number.
Calling AirnodeRrpV0
for a random number is the same as any other Airnode
request. Read more about how a requester
accesses an Airnode to acquire data from API
operations.
# QRNG Example Project
The qrng-example (opens new window) project (GitHub repo) demonstrates using the Airnode request–response protocol to receive QRNG services. It is recommended to run the example project to learn how it uses the QRNG service on a testnet, and read the associated README file. It also contains example code that will be useful when creating a requester (smart contract) that requests a random number, and is referenced frequently within this doc.
# Using the QRNG Service
Preparing to use the QRNG service involves three steps.
- Create a Requester: Create a requester (smart contract) to make a request and add a callback function to accept the response.
- Set the Parameters: After the requester is added to the desired chain, set its parameters used to make a request.
- Sponsor the Requester: The requester needs to be sponsored to cover gas costs for the on-chain response.
# Step 1: Create a Requester
Call the QRNG service using the request–response protocol (RRP) implemented by
the on-chain AirnodeRrpV0
contract. Refer to the
Calling an Airnode doc for a
detailed explanation and instructions to make a AirnodeRrpV0
request. The
@api3/airnode-protocol (opens new window)
package is distributed via npm.
The code example below is what a requester might look like when requesting a single random number. The code is extracted from the QrngExample.sol (opens new window) contract and has been simplified to only request a single random number with each call.
//SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol";
contract QrngExample is RrpRequesterV0 {
event RequestedUint256(bytes32 indexed requestId);
event ReceivedUint256(bytes32 indexed requestId, uint256 response);
// These can be set using setRequestParameters())
address public airnode;
bytes32 public endpointIdUint256;
address public sponsorWallet;
mapping(bytes32 => bool) public expectingRequestWithIdToBeFulfilled;
constructor(address _airnodeRrp) RrpRequesterV0(_airnodeRrp) {}
// Set parameters used by airnodeRrp.makeFullRequest(...)
// See makeRequestUint256()
function setRequestParameters(
address _airnode,
bytes32 _endpointIdUint256,
address _sponsorWallet
) external {
// Normally, this function should be protected, as in:
// require(msg.sender == owner, "Sender not owner");
airnode = _airnode;
endpointIdUint256 = _endpointIdUint256;
sponsorWallet = _sponsorWallet;
}
// Calls the AirnodeRrp contract with a request
// airnodeRrp.makeFullRequest() returns a requestId to hold onto.
function makeRequestUint256() external {
bytes32 requestId = airnodeRrp.makeFullRequest(
airnode,
endpointIdUint256,
address(this),
sponsorWallet,
address(this),
this.fulfillUint256.selector,
""
);
// Store the requestId
expectingRequestWithIdToBeFulfilled[requestId] = true;
emit RequestedUint256(requestId);
}
// AirnodeRrp will call back with a response
function fulfillUint256(bytes32 requestId, bytes calldata data)
external
onlyAirnodeRrp
{
// Verify the requestId exists
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 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 function
fulfillUint256
is the callback to receive the random number fromAirnodeRrp
. The callback contains therequestId
returned by the initial request and thedata
, which contains the random number. TherequestId
is verified and removed from the mappingexpectingRequestWithIdToBeFulfilled
.
# Step 2: Set the Parameters
The function makeRequestUint256()
calls airnodeRrp.makeFullRequest()
which
requires seven parameters, four of which self-populate. The other three need to
be set as a best practice.
address public airnode;
bytes32 public endpointIdUint256;
address public sponsorWallet;
2
3
Set the value of these parameters prior to using the requester. The most common
method is a script that calls setRequestParameters()
. Once set, the requester
can make a request to get a random number as often as needed without passing any
parameters. The parameters can be altered later to access other QRNG sources in
the future. See the following examples in the QRNG example project.
- script (opens new window) - Script to update the parameters in a requester.
- script data (opens new window) - Values used by the script for the parameters.
Sponsor Wallet
The above mentioned script from the qrng-example
project also
sets the sponsor wallet (opens new window)
used to pay gas costs. An alternate method is to use the airnode-admin
CLI as
detailed in the following section, Step 3: Sponsor the Requester.
# Step 3: Sponsor the Requester
The requester must be sponsored to pay for the gas costs when Airnode places the random number on-chain in response to a request. Requesters can be sponsored using a script or, as an alternate method, using the airnode-admin CLI.
Refer to the
Sponsor a Requester
doc for a detailed explanation and other instructions to create a sponsor wallet
for a requester. The sponsor wallet is applied to a requester using the
airnode-admin
CLI as shown below.
npx @api3/airnode-admin sponsor-requester \
--providerUrl https://ropsten.infura.io/v3/<KEY> \
--sponsor-mnemonic "cricket...oppose" \
--requester-address 0x2c...gDER7
# CLI output
Requester 0x2c...gDER7 sponsored using sponsorAddress 0xF4...dDyu9
2
3
4
5
6
7
See the airnode-admin CLI for additional options to sponsor a requester.
provider-url
- A chain provider such as Infura pointing to the desired chain.sponsor-mnemonic
- A wallet mnemonic to pay gas costs with its default account unless otherwise specified..requester-address
- The on-chain address of the requester (smart contract).
You can use an existing wallet's mnemonic but it is recommended to create one specifically for your requester's sponsor wallet.
Designated Sponsor Wallets
Sponsors should not fund a sponsorWallet
with more then they
can trust the Airnode with, as the Airnode controls the private key to the
sponsorWallet
. The deployer of such Airnode undertakes no
custody obligations, and the risk of loss or misuse of any excess funds
sent to the sponsorWallet
remains with the sponsor.
# QRNG on YouTube
See the YouTube video API3 Developers: QRNG Access & Usage Guide (opens new window) that also covers how to use QRNG.