Oraichain
Search
K

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)

// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
interface IERC20 {
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IVRFOracleOraichain {
function randomnessRequest(uint256 _seed, bytes calldata _data) external returns (bytes32 reqId);
function getFee() external returns (uint256);
}
contract VRFConsumerExample {
address public orai;
address public oracle;
uint256 public random;
bytes32 public reqId;
constructor (address _oraiToken, address _oracle) public {
orai = _oraiToken;
oracle = _oracle;
}
function randomnessRequest(uint256 _seed) public {
IERC20(orai).approve(oracle, IVRFOracleOraichain(oracle).getFee());
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
reqId = IVRFOracleOraichain(oracle).randomnessRequest(_seed, data);
}
function fulfillRandomness(bytes32 _reqId, uint256 _random) external {
require(msg.sender == oracle, "Caller must is oracle");
random = _random;
}
function setOracle(address _oracle) public {
oracle = _oracle;
}
function clearERC20(IERC20 token, address to, uint256 amount) external {
token.transfer(to, amount);
}
}

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
interface IVRFOracleOraichain {
function randomnessRequest(uint256 _seed, bytes calldata _data) external payable returns (bytes32 reqId);
function getFee() external returns (uint256);
}
contract VRFConsumerExampleNativeFee {
address public oracle;
uint256 public random;
bytes32 public reqId;
constructor (address _oracle) public payable {
oracle = _oracle;
}
fallback() external payable {}
function randomnessRequest(uint256 _seed) public {
uint256 fee = IVRFOracleOraichain(oracle).getFee();
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
reqId = IVRFOracleOraichain(oracle).randomnessRequest.value(fee)(_seed, data);
}
function fulfillRandomness(bytes32 _reqId, uint256 _random) external {
require(msg.sender == oracle, "Caller must is oracle");
random = _random;
}
function clearNativeCoin(address payable _to, uint256 amount) public payable {
_to.transfer(amount);
}
}

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.
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
interface IVRFOracleOraichain {
function randomnessRequest(uint256 _seed, bytes calldata _data) external payable returns (bytes32 reqId);
function getFee() external returns (uint256);
}
contract VrfOracleOraichainExample {
address public oracle;
uint256 public random1;
uint256 public random2;
uint256 public random3;
bytes32 public reqId;
constructor (address _oracle) public {
oracle = _oracle;
}
function randomnessRequest(uint256 _seed) public {
uint256 fee = IVRFOracleOraichain(oracle).getFee();
bytes memory data = abi.encode(address(this), this.fulfillRandomness.selector);
reqId = IVRFOracleOraichain(oracle).randomnessRequest.value(fee)(_seed, data);
}
// get three randomnesses range(0:1000) from Oraichain randomness
function fulfillRandomness(bytes32 _reqId, uint256 oraichainRandomness) public {
random1 = random(oraichainRandomness, 1000);
random2 = random(random1, 1000);
random3 = random(random2, 1000);
}
function random(uint256 _oraiNumber, uint256 _weight) public returns (uint256){
return uint256(keccak256(abi.encodePacked(_oraiNumber, block.difficulty, block.timestamp, block.coinbase, block.number, msg.sender))) % (_weight);
}
}