
QrngExample.sol
This contract gets an array of random numbers. It is also possible to get a single random number as with the the example contract RemixQrngExample.sol.
solidity
//SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol";
/// @title Example contract that uses Airnode RRP to receive QRNG services
/// @notice This contract is not secure. Do not use it in production. Refer to
/// the contract for more information.
/// @dev See README.md for more information.
contract QrngExample is RrpRequesterV0 {
event RequestedUint256(bytes32 indexed requestId);
event ReceivedUint256(bytes32 indexed requestId, uint256 response);
event RequestedUint256Array(bytes32 indexed requestId, uint256 size);
event ReceivedUint256Array(bytes32 indexed requestId, uint256[] response);
// These variables can also be declared as `constant`/`immutable`.
// However, this would mean that they would not be updatable.
// Since it is impossible to ensure that a particular Airnode will be
// indefinitely available, you are recommended to always implement a way
// to update these parameters.
address public airnode;
bytes32 public endpointIdUint256;
bytes32 public endpointIdUint256Array;
address public sponsorWallet;
mapping(bytes32 => bool) public expectingRequestWithIdToBeFulfilled;
/// @dev RrpRequester sponsors itself, meaning that it can make requests
/// that will be fulfilled by its sponsor wallet. See the Airnode protocol
/// docs about sponsorship for more information.
/// @param _airnodeRrp Airnode RRP contract address
constructor(address _airnodeRrp) RrpRequesterV0(_airnodeRrp) {}
/// @notice Sets parameters used in requesting QRNG services
/// @dev No access control is implemented here for convenience. This is not
/// secure because it allows the contract to be pointed to an arbitrary
/// Airnode. Normally, this function should only be callable by the "owner"
/// or not exist in the first place.
/// @param _airnode Airnode address
/// @param _endpointIdUint256 Endpoint ID used to request a `uint256`
/// @param _endpointIdUint256Array Endpoint ID used to request a `uint256[]`
/// @param _sponsorWallet Sponsor wallet address
function setRequestParameters(
address _airnode,
bytes32 _endpointIdUint256,
bytes32 _endpointIdUint256Array,
address _sponsorWallet
) external {
// Normally, this function should be protected, as in:
// require(msg.sender == owner, "Sender not owner");
airnode = _airnode;
endpointIdUint256 = _endpointIdUint256;
endpointIdUint256Array = _endpointIdUint256Array;
sponsorWallet = _sponsorWallet;
}
/// @notice Requests a `uint256`
/// @dev This request will be fulfilled by the contract's sponsor wallet,
/// which means spamming it may drain the sponsor wallet. Implement
/// necessary requirements to prevent this, e.g., you can require the user
/// to pitch in by sending some ETH to the sponsor wallet, you can have
/// the user use their own sponsor wallet, you can rate-limit users.
function makeRequestUint256() external {
bytes32 requestId = airnodeRrp.makeFullRequest(
airnode,
endpointIdUint256,
address(this),
sponsorWallet,
address(this),
this.fulfillUint256.selector,
""
);
expectingRequestWithIdToBeFulfilled[requestId] = true;
emit RequestedUint256(requestId);
}
/// @notice Called by the Airnode through the AirnodeRrp contract to
/// fulfill the request
/// @dev Note the `onlyAirnodeRrp` modifier. You should only accept RRP
/// fulfillments from this protocol contract. Also note that only
/// fulfillments for the requests made by this contract are accepted, and
/// a request cannot be responded to multiple times.
/// @param requestId Request ID
/// @param data ABI-encoded response
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);
}
/// @notice Requests a `uint256[]`
/// @param size Size of the requested array
function makeRequestUint256Array(uint256 size) external {
bytes32 requestId = airnodeRrp.makeFullRequest(
airnode,
endpointIdUint256Array,
address(this),
sponsorWallet,
address(this),
this.fulfillUint256Array.selector,
// Using Airnode ABI to encode the parameters
abi.encode(bytes32("1u"), bytes32("size"), size)
);
expectingRequestWithIdToBeFulfilled[requestId] = true;
emit RequestedUint256Array(requestId, size);
}
/// @notice Called by the Airnode through the AirnodeRrp contract to
/// fulfill the request
/// @param requestId Request ID
/// @param data ABI-encoded response
function fulfillUint256Array(bytes32 requestId, bytes calldata data)
external
onlyAirnodeRrp
{
require(
expectingRequestWithIdToBeFulfilled[requestId],
"Request ID not known"
);
expectingRequestWithIdToBeFulfilled[requestId] = false;
uint256[] memory qrngUint256Array = abi.decode(data, (uint256[]));
// Do what you want with `qrngUint256Array` here...
emit ReceivedUint256Array(requestId, qrngUint256Array);
}
}
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.
FLEX_END_TAG