Secret Network
WebsiteDiscordGithub
  • ๐Ÿ‘‹INTRODUCTION
    • Secret Network Introduction
    • Secret Network Techstack
      • Private transactions - A quick summary
      • Blockchain Technology
        • Cosmos Basics
        • Tendermint
        • Cosmos SDK
        • IBC
        • CosmWasm
      • Privacy Technology
        • Encryption - Key Management
          • Overview
          • Key Derivation & Encryption Techniques
          • The Initialization Of Secret Network
          • Full Node Boostrap
          • Contract State Encryption
          • Transaction Encryption
          • Consensus seed rotation
        • Trusted Execution Environmentsโ€Š (TEE) โ€”โ€Š Intel SGX
          • How Secret Network Uses SGX
          • SGX-SPS Security & Reliabillity
          • Remote Attestation
          • Trusted & Untrusted Core
          • Sealing
        • Private smart contracts - overview
  • ๐Ÿ’ปDevelopment
    • ๐Ÿ Getting Started
      • Setting Up Your Environment
        • Cargo.toml Best Practices (Crates vs Dependencies)
      • Compile and Deploy
      • Running the Application
      • Compile and Deploy on Secret testnet (best for Javascript devs)
      • Fullstack dApp Integration
    • ๐Ÿค“Secret Contracts
      • Secret Contracts & CosmWasm
        • Framework overview
        • Secret Contract Components
          • Instantiation Message
          • Execution Message
          • Query Message
          • Deps/DepsMut
          • Storage
            • Prefixed Storage
            • Singleton
            • Keymap
            • Append Store
            • Best practices
        • CosmWasm vs Secret CosmWasm
      • Secret Tokens (SNIP-20)
      • Contract - module call
      • Secret contract - Design Space/Features
        • Secret Contracts introduction
        • Gas/Fee usage
        • TPS and scalability
        • Privacy Essentials
        • Access Control
          • Viewing Keys
          • Permits
        • Trusted and untrusted data
        • Secret-VRF - on-chain Randomness
        • Privacy design
          • Mitigate privacy risks - full guide
          • Gas Evaporation & Tracking
        • Confidential Computing Layer
        • Fiat/Crypto Onboarding
        • Account abstraction
        • Fee abstraction
        • Wallet support
        • Bridge (messaging/tokens)
        • IBC (Hooks, PFM, Wasm)
        • Price Oracles
        • Auto Restaking
      • Permissioned Viewing
        • Viewing Keys
        • Permits
      • Cross Contract Communication
      • Submessages
        • get_contract_code_hash
      • Randomness API - Secret VRF
        • Native On-chain randomness
        • Randomness over IBC
      • Execution Finalization
      • Factory Contracts
      • Contract Migration
        • Manual - < v1.11
        • Native - from v1.11
      • Cross-deploy Vanilla CW and Secret Contracts
      • Testing Secret Contracts
        • Unit Tests
        • Continuous Integration
        • Datatype Handling - Uint, floats etc.
    • ๐Ÿ‘€Secret Contract - Reference, Guides, Examples
      • Starter guide - Millionaire's Problem
      • Reference Contracts
      • Open source dApps
      • Tools & Libraries
        • Network interaction SDKs
          • Secret.js (JavaScript)
          • SecretPy (Python)
          • SecretK (Kotlin)
          • Secret.NET
            • Snippets
              • Deploying a Contract
              • Send Native Coin
              • Query a Contract
              • Create a new Wallet
              • Permits
              • SNIP20
              • SNIP721
          • Shade.Js
        • LocalSecret - Devnet docker
        • Smart contract - Tools/Utils
          • Secret Toolkit
          • CW-Plus
          • Fadroma - SC framework
          • Hidden Gems
          • Other
            • Secret IDE
            • Polar
    • ๐Ÿ–ผ๏ธFrontend Development
      • Getting Started with SecretJS
        • Usage Examples
          • Sending Queries
          • Sending Messages
          • Contract Migration
          • Wallet Integrations
          • Query Permits
          • SNIP20 (SCRT Tokens)
          • SNIP721 (Secret NFTs)
      • Feegrant
        • Understanding Feegrant allowances
        • Grant allowances
        • Using grant allowances to execute transactions
        • Using the Fee Grant Faucet
    • ๐Ÿ“ฌDeployment Addresses/ API Endpoints
      • Secret (SNIP 20) token contracts list
        • SNIP Asset naming guidelines
      • Connecting to the Network
        • API Endpoints Mainnet (Secret-4)
        • API Endpoints Testnet (Pulsar-3)
        • Usage examples
        • Comparison of endpoint types
      • Create your own SNIP-25 IBC Token
  • Secret AI
    • ๐ŸคIntroduction
    • ๐Ÿ—๏ธArchitecture
    • ๐Ÿ‘ฉโ€๐Ÿ’ปSecret AI SDK
      • Setting Up Your Environment
      • Running the Application
    • ๐Ÿช™Economics
    • Smart Contract Reference
      • SubscriptionManager
      • WorkerManager
      • RewardsManager
  • ๐ŸŒSecretVM - Confidential Virtual Machines
    • ๐ŸคIntroduction
    • ๐Ÿ—๏ธArchitecture
    • โ˜‘๏ธAttestation
      • What is Attestation
      • Obtaining Attestation Data
      • Attestation Report - Key Fields
      • Chain of Trust
    • ๐ŸLaunching a SecretVM
    • ๐Ÿ› ๏ธManaging SecretVM Lifecycle
    • โœ…Verifying a SecretVM
    • ๐Ÿ’กBest Practices for Developers
    • ๐Ÿ“–Glossary
  • ๐Ÿ”“Confidential Computing Layer
    • ๐Ÿง‘โ€๐Ÿš€IBC Developer Toolkit
      • Basics
        • Overview
        • Cross-chain Messaging with IBC Hooks
          • Functions, Methods, and Data Structures
          • Typescript SDK
          • IBC-Hooks
        • IBC Relaying with Go Relayer
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-Value store Developer Tutorial
        • Secret VRF for IBC with IBC-Hooks
        • Confidential Voting
        • Sealed Bid Auctions
      • Supported Networks
        • Mainnet
        • Testnet
    • ๐ŸคEthereum (EVM) Developer Toolkit
      • Basics
        • Overview
        • Connecting Metamask to Secret Network
        • SecretPath + Reown integration
        • Cross-chain Messaging
          • SecretPath
            • Architecture Overview
            • Detailed Architecture
            • SecretPath Developer Tutorials
            • Public EVM Gateway Architecture
            • How to deploy SecretPath on your chain
          • Axelar GMP
            • Architecture Overview
            • Axelar GMP Developer Tutorial
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-Value store Developer Tutorial
        • Sealed Bid Auction
          • Sealed Bid Auction Developer Tutorial
        • Confidential Voting
          • Confidential Voting Developer Tutorial with SecretPath
        • VRF
          • Implementing VRF into any EVM Contract
          • VRF Developer Tutorial
          • Performance figures of SecretVRF vs competitors
          • Using encrypted payloads for VRF
          • Converting from Chainlink VRF to Secret VRF in four steps
        • Confidential Document Sharing
        • Tokens
          • From EVM to Secret
      • Supported Networks
        • EVM
          • EVM Mainnet
          • EVM Testnet
          • Gateway Contract ABI
        • Secret Gateway
          • SecretPath mainnet (secret-4) contracts
          • SecretPath testnet (pulsar-3) contracts
    • ๐Ÿ™ŒSolana Developer Toolkit
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-value Store Developer Tutorial
        • VRF
          • VRF Developer Tutorial
      • Program IDs
        • Solana Mainnet & Testnet
        • Gateway Contract IDL
  • ๐ŸคซOverview, Ecosystem and Technology
    • ๐Ÿš€Secret Network Overview
      • The SCRT coin
      • Private Tokens
      • Use Cases
        • Decentralized Finance (DeFi)
        • Art And Digital Media
        • Gaming
        • Data Privacy
        • Payments And Transactions
        • Communication
      • The technology
      • History
      • Roadmap (Core development)
        • Secret 2.0
      • Where To Buy SCRT?
      • Using the Testnet
    • ๐ŸธEcosystem Overview
      • Wallets
      • Applications
      • Explorers & tools
      • Funding
        • SCRT Labs Grants
        • Dilutive funding/VC raise
        • Community Pool
        • Developer bounties
          • SCRT Labs bounties [on-hold]
          • CCBL [on-hold]
          • CCR [On-hold]
        • Application specific
          • Shade Grants
      • Contributors & Entities
        • Validators
        • SCRT Labs
        • Secret Foundation
        • Secret Committees
          • Support
          • Governance
      • Secret Network Dictionary
  • ๐Ÿ”งInfrastructure
    • ๐Ÿ”“Use SecretCLI
      • Secretcli vs. Secretd
      • Install
      • Configuration
      • Address Types
      • Key Types
      • Generating Keys
      • Viewing Keys
      • Query Transactions
      • Send Tokens
      • Multisig Keys
      • Multisig Transactions
      • Transaction Broadcasting
      • Fees & Gas
      • Fee Distribution
      • Secret Contracts
      • Slashing
      • Minting
      • Delegating
      • Restake
      • Nodes
      • Governance
        • Creating Governance Proposals
        • Query Proposals
        • Deposits
        • Voting
    • ๐Ÿ”Use Ledger hardware wallet
      • ๐Ÿ”Ledger with SecretCLI
    • ๐Ÿ–ฅ๏ธRunning a node/validator
      • Setting up a node/validator
        • Hardware setup
          • Hardware Compliance
          • VPS/Bare-Metal Compliance
            • Leaseweb Setup
            • PhoenixNAP Setup
            • Psychz Setup
            • nForce Setup
            • Vultr Setup
            • OVHCloud Setup
            • Microsoft Azure Setup
          • Patching your Node
          • Enclave verification
          • Registration troubleshooting
        • Testnet Setup
          • Install SGX
          • Install secretd
          • Setup Full Node
          • Testnet State Sync
          • Becoming a Testnet Validator
          • Installing CLI & Creating A New Address
        • Mainnet Setup
          • Install SGX
          • Install secretd
          • Setup Full Node
          • Quicksync / Snapshot
          • Statesync
          • Becoming A Validator
          • Installing CLI & Creating A New Address
      • Maintaining a node/validator
        • Slashing information
        • Migrating a Validator
        • Troubleshooting
        • Validator Backup
        • Server security
          • SSH authentication
          • Server configuration
          • Uncomplicated-Firewall (UFW)
          • Local CLI
        • Node Monitoring
          • Prometheus
            • Environment Preperation
            • Install Node Exporter
            • Install Prometheus
            • Configuring Prometheus
          • Grafana
            • Install Grafana
            • Grafana Dashboard
            • Next Steps
          • Docker
            • Install Docker
            • Configuration
            • Start Containers
            • Grafana Dashboard
            • Application Ports
            • Stop Containers
          • Goaccess
            • Install Goaccess
            • Setup Goaccess
        • Helpful commands
          • Query Validators
          • Bond Tokens
          • Withdraw Rewards
          • Query Delegations
          • Unbond Tokens
          • Query Unbonding-Delegations
          • Redelegate Tokens
          • Query Redelegations
          • Query Parameters
          • Query Pool
          • Query Delegations To Validator
      • API Noderunning
        • Running Multiple Nodes on the Same Server
        • Node Loadbalancing using Nginx
          • Setup Nginx
          • Example Nginx config
        • Using Auto heal to improve cluster uptime for Nginx
      • Sentry and Archive nodes
        • Mantlemint
        • Sentry Nodes
        • Archive Nodes
    • โ›“๏ธIBC Relayers
      • Hermes
      • RLY
      • IBC channel database
    • ๐Ÿ†™Upgrade Instructions
      • v1.13
      • v1.12
      • v1.11
      • v1.10
      • v1.9
      • v1.8
      • v1.7
      • Shockwave Omega v1.6
      • v1.5
      • Shockwave Delta v1.4
      • Shockwave Delta v1.4 (Testnet)
      • Shockwave Alpha v1.3
      • Cosmovisor
      • Vulcan Network Upgrade (OLD)
    • โ˜ ๏ธPostmortems
      • SNIP-20 leaks
      • xApic
      • Secpk-Verifications Bloat
      • Earn Contract Exploit
      • Testnet Halt 95
    • โœ๏ธContribute to the documentation
      • Report Bugs
      • Suggest Enhancements
      • First Contribution Guide
      • Pull Request Templates
        • Update Documentation
        • Bug Fix
        • Improve Performance
        • Change Functionality
      • Style Guide
    • ๐ŸŒŠVersioning & Changelog
      • Secret Network v1.13
      • Secret Network v1.12
      • Secret Network v1.11
      • Secret Network v1.10
      • Secret network v1.9
      • Secret Network v1.7/1.8
      • Secret Network v1.6
      • Secret Network v1.5
      • Secret Network v1.4 (CosmWasm 1.0)
Powered by GitBook
On this page
  • Removing Chainlink bloat
  • Simplifying the Constructor
  • Change request randomness function
  • Add a check for the Secret VRF Gateway
  • Conclusion

Was this helpful?

Edit on GitHub
Export as PDF
  1. Confidential Computing Layer
  2. Ethereum (EVM) Developer Toolkit
  3. Usecases
  4. VRF

Converting from Chainlink VRF to Secret VRF in four steps

PreviousUsing encrypted payloads for VRFNextConfidential Document Sharing

Last updated 7 months ago

Was this helpful?

Got improvements or suggestions on how to convert your ChainlinkVRF contract to SecretVRF ? Please ask in the Secret Network or Discord.

Converting from Chainlink VRF to Secret VRF is easier than you expect. Within four easy steps you can free your contract from bloat and use the lightweight and faster Secret VRF solution.

We start off with the example code from Chainlink from :

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import {VRFCoordinatorV2Interface} from "@chainlink/contracts@1.0.0/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol";
import {VRFConsumerBaseV2} from "@chainlink/contracts@1.0.0/src/v0.8/vrf/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    uint256 private constant ROLL_IN_PROGRESS = 42;

    VRFCoordinatorV2Interface COORDINATOR;

    // Your subscription ID.
    uint64 s_subscriptionId;

    // Sepolia coordinator. For other networks,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625;

    // The gas lane to use, which specifies the maximum gas price to bump to.
    // For a list of available gas lanes on each network,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    bytes32 s_keyHash =
        0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;

    // Depends on the number of requested values that you want sent to the
    // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
    // so 40,000 is a safe default for this example contract. Test and adjust
    // this limit based on the network that you select, the size of the request,
    // and the processing of the callback request in the fulfillRandomWords()
    // function.
    uint32 callbackGasLimit = 40000;

    // The default is 3, but you can set this higher.
    uint16 requestConfirmations = 3;

    // For this example, retrieve 1 random value in one request.
    // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
    uint32 numWords = 1;
    address s_owner;

    // map rollers to requestIds
    mapping(uint256 => address) private s_rollers;
    // map vrf results to rollers
    mapping(address => uint256) private s_results;

    event DiceRolled(uint256 indexed requestId, address indexed roller);
    event DiceLanded(uint256 indexed requestId, uint256 indexed result);

    constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_owner = msg.sender;
        s_subscriptionId = subscriptionId;
    }

    function rollDice(
        address roller
    ) public onlyOwner returns (uint256 requestId) {
        require(s_results[roller] == 0, "Already rolled");
        // Will revert if subscription is not set and funded.
        requestId = COORDINATOR.requestRandomWords(
            s_keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );

        s_rollers[requestId] = roller;
        s_results[roller] = ROLL_IN_PROGRESS;
        emit DiceRolled(requestId, roller);
    }

    function fulfillRandomWords(
        uint256 requestId,
        uint256[] memory randomWords
    ) internal override {
        uint256 d20Value = (randomWords[0] % 20) + 1;
        s_results[s_rollers[requestId]] = d20Value;
        emit DiceLanded(requestId, d20Value);
    }

    function house(address player) public view returns (string memory) {
        require(s_results[player] != 0, "Dice not rolled");
        require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");
        return getHouseName(s_results[player]);
    }

    function getHouseName(uint256 id) private pure returns (string memory) {
        string[20] memory houseNames = [
            "Targaryen",
            "Lannister",
            "Stark",
            "Tyrell",
            "Baratheon",
            "Martell",
            "Tully",
            "Bolton",
            "Greyjoy",
            "Arryn",
            "Frey",
            "Mormont",
            "Tarley",
            "Dayne",
            "Umber",
            "Valeryon",
            "Manderly",
            "Clegane",
            "Glover",
            "Karstark"
        ];
        return houseNames[id - 1];
    }

    modifier onlyOwner() {
        require(msg.sender == s_owner);
        _;
    }
}

Removing Chainlink bloat

In the first step, we remove the imports and the inheritance of the VRFConsumerBaseV2 and add our SecretVRF interface from this. There is no

import {VRFCoordinatorV2Interface} from "@chainlink/contracts@1.0.0/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol";
import {VRFConsumerBaseV2} from "@chainlink/contracts@1.0.0/src/v0.8/vrf/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    uint256 private constant ROLL_IN_PROGRESS = 42;

    VRFCoordinatorV2Interface COORDINATOR;

    // Your subscription ID.
    uint64 s_subscriptionId;

    // Sepolia coordinator. For other networks,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625;

    // The gas lane to use, which specifies the maximum gas price to bump to.
    // For a list of available gas lanes on each network,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    bytes32 s_keyHash =
        0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;
        
    // Depends on the number of requested values that you want sent to the
    // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
    // so 40,000 is a safe default for this example contract. Test and adjust
    // this limit based on the network that you select, the size of the request,
    // and the processing of the callback request in the fulfillRandomWords()
    // function.
    uint32 callbackGasLimit = 40000;
    //...
}

to get to this:

interface ISecretVRF { 
    function requestRandomness(uint32 _numWords, uint32 _callbackGasLimit) external payable returns (uint256 requestId); 
}
contract VRFD20 {
    uint256 private constant ROLL_IN_PROGRESS = 42;
    //...
    
    // Depends on the number of requested values that you want sent to the
    // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
    // so 40,000 is a safe default for this example contract. Test and adjust
    // this limit based on the network that you select, the size of the request,
    // and the processing of the callback request in the fulfillRandomWords()
    // function.
    uint32 callbackGasLimit = 40000;
    
    // Sepolia Gateway. For other networks,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address public VRFGateway = 0x3879E146140b627a5C858a08e507B171D9E43139;
}

Here, the behavior of the callbackGasLimit is different than in ChainlinkVRF. The callback Gas limit is simply all of the gas that you need to pay in order to make callback, which includes the verification of the result as well. The callback gas is the amount of gas that you have to pay for the message coming on the way back. We recommend at least using 100_000+ in Callback gas to ensure that enough gas is available. In case you did not pay enough gas, the contract callback execution will fail.

Simplifying the Constructor

Next, we can also simplify the constructor since we do not need to define any extra variables or subscriptionIds. Going from this:

constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_owner = msg.sender;
        s_subscriptionId = subscriptionId;
}

to this

constructor()  {
        s_owner = msg.sender;
}

Change request randomness function

Next, we need to slightly adjust the behavior of the function rollDice(address roller) function and how it calls the Request Randomness function within Secret VRF. Here, we need to use the Secret VRF gateway and call it directly instead.

Make sure to now mark this function as payable!

function rollDice(
        address roller
    ) public payable onlyOwner returns (uint256 requestId) {
        require(s_results[roller] == 0, "Already rolled");
        // Will revert if subscription is not set and funded.

        // Get the VRFGateway contract interface 
        ISecretVRF vrfContract = ISecretVRF(VRFGateway);
    
        // Call the VRF contract to request random numbers. 
        // Returns requestId of the VRF request. A  contract can track a VRF call that way.
        uint256 requestId = vrfContract.requestRandomness{value: msg.value}(_numWords, _callbackGasLimit);

        s_rollers[requestId] = roller;
        s_results[roller] = ROLL_IN_PROGRESS;
        emit DiceRolled(requestId, roller);
    }
}

Please make sure to actually prepay the right amount of callback gas directly as a value transfer into the contract. The callback gas is the amount of gas that you have to pay for the message coming on the way back. If you do pay less than the amount specified below, your Gateway TX will fail:

/// @notice Increase the task_id to check for problems 
/// @param _callbackGasLimit the Callback Gas Limit

function estimateRequestPrice(uint32 _callbackGasLimit) private view returns (uint256) {
    uint256 baseFee = _callbackGasLimit*block.basefee;
    return baseFee;
}
//Then calculate how much gas you have to pay for the callback
//Forumla: callbackGasLimit*block.basefee.
//Use an appropriate overhead for the transaction, 1,5x = 3/2 is recommended since gasPrice fluctuates.

const gasFee = await provider.getGasPrice();
const amountOfGas = gasFee.mul(callbackGasLimit).mul(3).div(2);

Add a check for the Secret VRF Gateway

Lastly, we'll add a small check to ensure that we actually got an incoming call from the SecretVRF gateway contract. For this, remove the internal and override flags on the function and add the require:

function fulfillRandomWords(
        uint256 requestId,
        uint256[] memory randomWords
    ) external {
        require(msg.sender == address(VRFGateway), "only Secret Gateway can fulfill");

        uint256 d20Value = (randomWords[0] % 20) + 1;
        s_results[s_rollers[requestId]] = d20Value;
        emit DiceLanded(requestId, d20Value);
}

Conclusion

That's all that you need to convert your contract from ChainlinkVRF to SecretVRF.

Since this check is dependent on the current block.basefee of the block it is included in, it is recommended that you estimate the gas fee beforehand and add some extra overhead to it. An example of how this can be implemented in your frontend can be found in this and here:

๐Ÿ”“
๐Ÿค
Telegram
here
example