Get VRF Value from different networks
This section showcases how to get a random value inside a smart contract from different blockchain networks like BSC and Fantom, etc.
How VRF values are generated from different netw
How VRF values are generated from a different network
VRF execution flow from Binance Smart Chain (BSC), Avalanche (AVAX) and Fantom (FTM):
VRF execution flow from BNB Chain (formerly Binance Smart Chain), Avalanche (AVAX) and Fantom (FTM):
  • First of all, smart contract users must pay fees (in OraiToken with BSC network and native tokens with AVAX and FTM) and make a request to generate random numbers with VRFOracleOraichain contract
  • Next, the VRFOracleOraichain contract checks the request of the user and the fee, if everything is verified, the VRFOracleOraichain will generate a corresponding reqId and return it to the user.
  • A keeper bridge will listen for events on the VRFOracleOraichain smart contract and make a random generated request to Oraichain network. The random value takes the input from the seed provided by the smart contract user.
  • Oraichain Mainnet uses submitted information to generate random numbers and proofs. After generating a random number and proof, the Oraichain Mainnet sends that data back to the keeper bridge.
  • The keeper bridge receives the information and fullfills the VRFOracleOraichain contract, then the random number will be sent back to the user via consumer address and reqId.
  • Note: Only authorized keepers can fulfill the VRFOracleOraichain smart contract. The random number is guaranteed by the signatures of Oraichain mainnet's validators.
  • First of all, smart contract users must pay fees (in OraiToken with BSC network and native tokens with AVAX and FTM) and make a request to generate random numbers with VRFOracleOraichain contract
  • Next, the VRFOracleOraichain contract checks the request of the user and the fee, if everything is verified, the VRFOracleOraichain will generate a corresponding reqId and return it to the user.
  • A keeper bridge will listen for events on the VRFOracleOraichain smart contract and make a random generated request to Oraichain network. The random value takes the input from the seed provided by the smart contract user.
  • Oraichain Mainnet uses submitted information to generate random numbers and proofs. After generating a random number and proof, the Oraichain Mainnet sends that data back to the keeper bridge.
  • The keeper bridge receives the information and fullfills the VRFOracleOraichain contract, then the random number will be sent back to the user via consumer address and reqId.
  • Note: Only authorized keepers can fulfill the VRFOracleOraichain smart contract. The random number is guaranteed by the signatures of Oraichain mainnet's validators.
To generate a VRF value from your blockchain of choice, your contract needs to inherit VrfOracleOraichain and define 2 required functions:
To generate a VRF value from your blockchain of choice, your contract needs to inherit VrfOracleOraichain and define 2 required functions:
  1. 1.
    randomnessRequest: initiate a request to generate random numbers
  2. 2.
    fulfillRandomness: will perform receiving and verifying data.
  • Your contract needs to have enough ORAI or the needed token to make the request for a random number.
  • Some of the values in the example below need to be particularly correct for each network.

Examples for best practices

ORAI token based VRF Oracle (BNB Chain)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.5.16;
3
4
5
interface IERC20 {
6
7
function transfer(address recipient, uint256 amount) external returns (bool);
8
9
function approve(address spender, uint256 amount) external returns (bool);
10
}
11
12
13
interface IVRFOracleOraichain {
14
function randomnessRequest(uint256 _seed, bytes calldata _data) external returns (bytes32 reqId);
15
16
function getFee() external returns (uint256);
17
}
18
19
contract VRFConsumerExample {
20
21
address public orai;
22
address public oracle;
23
uint256 public random;
24
bytes32 public reqId;
25
26
constructor (address _oraiToken, address _oracle) public {
27
orai = _oraiToken;
28
oracle = _oracle;
29
}
30
31
function randomnessRequest(uint256 _seed) public {
32
IERC20(orai).approve(oracle, IVRFOracleOraichain(oracle).getFee());
33
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
34
reqId = IVRFOracleOraichain(oracle).randomnessRequest(_seed, data);
35
}
36
37
function fulfillRandomness(bytes32 _reqId, uint256 _random) external {
38
require(msg.sender == oracle, "Caller must is oracle");
39
random = _random;
40
}
41
42
function setOracle(address _oracle) public {
43
oracle = _oracle;
44
}
45
46
function clearERC20(IERC20 token, address to, uint256 amount) external {
47
token.transfer(to, amount);
48
}
49
}
50
Copied!

Native token based VRF Oracle (Avalanche, Fantom, etc.)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.6.12;
3
4
5
interface IVRFOracleOraichain {
6
function randomnessRequest(uint256 _seed, bytes calldata _data) external payable returns (bytes32 reqId);
7
8
function getFee() external returns (uint256);
9
}
10
11
contract VRFConsumerExampleNativeFee {
12
13
address public oracle;
14
uint256 public random;
15
bytes32 public reqId;
16
17
constructor (address _oracle) public payable {
18
oracle = _oracle;
19
}
20
21
fallback() external payable {}
22
23
function randomnessRequest(uint256 _seed) public {
24
uint256 fee = IVRFOracleOraichain(oracle).getFee();
25
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
26
reqId = IVRFOracleOraichain(oracle).randomnessRequest.value(fee)(_seed, data);
27
}
28
29
function fulfillRandomness(bytes32 _reqId, uint256 _random) external {
30
require(msg.sender == oracle, "Caller must is oracle");
31
random = _random;
32
}
33
34
function clearNativeCoin(address payable _to, uint256 amount) public payable {
35
_to.transfer(amount);
36
}
37
38
}
39
Copied!

Here are more tested examples for Fantom and Avalanche developers.

General guideline for smart contract users

  • There are currently two payment methods for Oraichain VRF service, the first of which requires Orai token for Binance Smart Chain; the latter requires native token for Avalanche and Fantom Opera. You must therefore use your wallet accordingly.
  • Next, copy either of the example codes above (respective to your network of choice) into Remix IDE to compile and deploy your smart contract.
  • After the contract is deployed, you need to transfer an amount of fee into it in order to request VRF value(s).
  • You will find yourself using 2 important functions namely randomnessRequest and fulfillRandomness
  • Run randomnessRequest function to request a random value. Each request is equivalent to a byte32 requestId retrieved from the oracle.
  • fulfillRandomness is a callback function, which serves as a VRF value receiver. It is imperative that your smart contract has a fulfillRandomness function with the input that resembles the examples above. Otherwise, the VRF value generating process shall be reverted.
  • require(msg.sender == oracle, "Caller must is oracle"): your fulfillRandomness function neecds to make sure your VRF caller is affiliated to Oraichain.
  • ⚠️Note: You may need to use the function clearERC20 or clearNativeCoin to keep your asset from getting stuck
  • There are currently two payment methods for Oraichain VRF service, the first of which requires Orai token for Binance Smart Chain; the latter requires native token for Avalanche and Fantom Opera. You must therefore use your wallet accordingly.
  • Next, copy either of the example codes above (respective to your network of choice) into Remix IDE to compile and deploy your smart contract.
  • After the contract is deployed, you need to transfer an amount of fee into it in order to request VRF value(s).
  • You will find yourself using 2 important functions namely randomnessRequest and fulfillRandomness
  • Run randomnessRequest function to request a random value. Each request is equivalent to a byte32 requestId retrieved from the oracle.
  • fulfillRandomness is a callback function, which serves as a VRF value receiver. It is imperative that your smart contract has a fulfillRandomness function with the input that resembles the examples above. Otherwise, the VRF value generating process shall be reverted.
  • require(msg.sender == oracle, "Caller must is oracle"): your fulfillRandomness function neecds to make sure your VRF caller is affiliated to Oraichain.
  • ⚠️Note: You may need to use the function clearERC20 or clearNativeCoin to keep your asset from getting stuck

Specific example

Say you have to pick 3 winners out of 1000 participants. First, number the 1000 participants (from 1 to 1000). Then use fuction randomPlayer like the example below after getting a VRF value from Oraichain.
1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.5.16;
3
4
5
interface IVRFOracleOraichain {
6
function randomnessRequest(uint256 _seed, bytes calldata _data) external payable returns (bytes32 reqId);
7
8
function getFee() external returns (uint256);
9
}
10
11
contract VrfOracleOraichainExample {
12
13
address public oracle;
14
uint256 public random1;
15
uint256 public random2;
16
uint256 public random3;
17
bytes32 public reqId;
18
19
constructor (address _oracle) public {
20
oracle = _oracle;
21
}
22
23
function randomnessRequest(uint256 _seed) public {
24
uint256 fee = IVRFOracleOraichain(oracle).getFee();
25
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
26
reqId = IVRFOracleOraichain(oracle).randomnessRequest.value(fee)(_seed, data);
27
}
28
29
// get three randomnesses range(0:1000) from Oraichain randomness
30
function fulfillRandomness(bytes32 _reqId, uint256 oraichainRandomness) public {
31
random1 = random(oraichainRandomness, 1000);
32
random2 = random(random1, 1000);
33
random3 = random(random2, 1000);
34
}
35
36
function random(uint256 _oraiNumber, uint256 _weight) public returns (uint256){
37
return uint256(keccak256(abi.encodePacked(_oraiNumber, block.difficulty, block.timestamp, block.coinbase, block.number, msg.sender))) % (_weight);
38
}
39
}
Copied!