diff --git a/components/EntropyDeployments.tsx b/components/EntropyDeployments.tsx index 4aa55905..d687ffe3 100644 --- a/components/EntropyDeployments.tsx +++ b/components/EntropyDeployments.tsx @@ -5,6 +5,7 @@ export interface EntropyDeployment { delay: string; gasLimit: string; rpc: string; + nativeCurrency: string; } export const EntropyDeployments: Record = { @@ -15,6 +16,7 @@ export const EntropyDeployments: Record = { delay: "1 block", gasLimit: "500K", rpc: "https://rpc.blast.io", + nativeCurrency: "ETH", }, "lightlink-phoenix": { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", @@ -23,6 +25,7 @@ export const EntropyDeployments: Record = { delay: "1 block", gasLimit: "500K", rpc: "https://replicator.phoenix.lightlink.io/rpc/v1", + nativeCurrency: "ETH", }, chiliz: { address: "0x0708325268dF9F66270F1401206434524814508b", @@ -31,6 +34,7 @@ export const EntropyDeployments: Record = { delay: "12 blocks", gasLimit: "500K", rpc: "https://rpc.ankr.com/chiliz", + nativeCurrency: "CHZ", }, arbitrum: { address: "0x7698E925FfC29655576D0b361D75Af579e20AdAc", @@ -39,6 +43,7 @@ export const EntropyDeployments: Record = { delay: "6 blocks", gasLimit: "2.5M", rpc: "https://arb1.arbitrum.io/rpc", + nativeCurrency: "ETH", }, optimism: { address: "0xdF21D137Aadc95588205586636710ca2890538d5", @@ -47,6 +52,7 @@ export const EntropyDeployments: Record = { delay: "2 blocks", gasLimit: "500K", rpc: "https://rpc.ankr.com/optimism", + nativeCurrency: "ETH", }, mode: { address: "0x8D254a21b3C86D32F7179855531CE99164721933", @@ -55,6 +61,7 @@ export const EntropyDeployments: Record = { delay: "2 blocks", gasLimit: "500K", rpc: "https://mainnet.mode.network/", + nativeCurrency: "ETH", }, zetachain: { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", @@ -63,6 +70,7 @@ export const EntropyDeployments: Record = { delay: "0 block", gasLimit: "500K", rpc: "https://zetachain-evm.blockpi.network/v1/rpc/public", + nativeCurrency: "ZETA", }, base: { address: "0x6E7D74FA7d5c90FEF9F0512987605a6d546181Bb", @@ -71,6 +79,7 @@ export const EntropyDeployments: Record = { delay: "1 block", gasLimit: "500K", rpc: "https://developer-access-mainnet.base.org/", + nativeCurrency: "ETH", }, "lightlink-pegasus": { rpc: "https://replicator.pegasus.lightlink.io/rpc/v1", @@ -79,6 +88,7 @@ export const EntropyDeployments: Record = { address: "0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a", explorer: "https://pegasus.lightlink.io/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "chiliz-spicy": { rpc: "https://spicy-rpc.chiliz.com", @@ -87,6 +97,7 @@ export const EntropyDeployments: Record = { address: "0xD458261E832415CFd3BAE5E416FdF3230ce6F134", explorer: "https://spicy-explorer.chiliz.com/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "CHZ", }, "conflux-espace-testnet": { rpc: "https://evmtestnet.confluxrpc.com", @@ -95,6 +106,7 @@ export const EntropyDeployments: Record = { address: "0xdF21D137Aadc95588205586636710ca2890538d5", explorer: "https://evmtestnet.confluxscan.io/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "CFX", }, "mode-sepolia": { rpc: "https://sepolia.mode.network/", @@ -103,6 +115,7 @@ export const EntropyDeployments: Record = { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", explorer: "https://sepolia.explorer.mode.network/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "sei-evm-testnet": { rpc: "https://evm-rpc-testnet.sei-apis.com", @@ -111,6 +124,7 @@ export const EntropyDeployments: Record = { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", explorer: "https://seitrace.com/address/$ADDRESS?chain=atlantic-2", gasLimit: "500K", + nativeCurrency: "SEI", }, "arbitrum-sepolia": { rpc: "https://sepolia-rollup.arbitrum.io/rpc", @@ -119,6 +133,7 @@ export const EntropyDeployments: Record = { address: "0x549Ebba8036Ab746611B4fFA1423eb0A4Df61440", explorer: "https://sepolia.arbiscan.io/address/$ADDRESS", gasLimit: "2.5M", + nativeCurrency: "ETH", }, "fantom-sonic": { rpc: "https://rpc.sonic.fantom.network/", @@ -127,6 +142,7 @@ export const EntropyDeployments: Record = { address: "0xb27e5ca259702f209a29225d0eDdC131039C9933", explorer: "https://public-sonic.fantom.network/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "S", }, "blast-testnet": { rpc: "https://sepolia.blast.io", @@ -135,6 +151,7 @@ export const EntropyDeployments: Record = { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", explorer: "https://testnet.blastscan.io/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "optimism-sepolia": { rpc: "https://sepolia.optimism.io", @@ -143,6 +160,7 @@ export const EntropyDeployments: Record = { address: "0x4821932D0CDd71225A6d914706A621e0389D7061", explorer: "https://optimism-sepolia.blockscout.com/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "base-sepolia": { rpc: "https://sepolia.base.org", @@ -151,6 +169,7 @@ export const EntropyDeployments: Record = { address: "0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c", explorer: "https://base-sepolia.blockscout.com/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "berachain-testnet-v2": { rpc: "https://evm-rpc-bera.rhino-apis.com/", @@ -159,6 +178,7 @@ export const EntropyDeployments: Record = { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", explorer: "https://bartio.beratrail.io/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "BERA", }, "coredao-testnet": { rpc: "https://rpc.test.btcs.network", @@ -167,6 +187,7 @@ export const EntropyDeployments: Record = { address: "0xf0a1b566B55e0A0CB5BeF52Eb2a57142617Bee67", explorer: "https://scan.test.btcs.network/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "tCORE", }, "zetachain-testnet": { rpc: "https://zetachain-athens-evm.blockpi.network/v1/rpc/public", @@ -175,6 +196,7 @@ export const EntropyDeployments: Record = { address: "0x4374e5a8b9C22271E9EB878A2AA31DE97DF15DAF", explorer: "https://explorer.zetachain.com/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ZETA", }, "taiko-hekla": { rpc: "https://rpc.hekla.taiko.xyz/", @@ -183,6 +205,7 @@ export const EntropyDeployments: Record = { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", explorer: "https://hekla.taikoscan.network/address/$ADDRESS", gasLimit: "500K", + nativeCurrency: "ETH", }, "orange-testnet": { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", @@ -191,6 +214,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://subnets.avax.network/orangetest/testnet/rpc", + nativeCurrency: "JUICE", }, "sei-evm-mainnet": { address: "0x98046Bd286715D3B0BC227Dd7a956b83D8978603", @@ -199,6 +223,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "mainnet", rpc: "https://evm-rpc.sei-apis.com", + nativeCurrency: "SEI", }, merlin: { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", @@ -207,6 +232,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "mainnet", rpc: "https://rpc.merlinchain.io", + nativeCurrency: "BTC", }, "merlin-testnet": { address: "0x5744Cbf430D99456a0A8771208b674F27f8EF0Fb", @@ -215,6 +241,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://testnet-rpc.merlinchain.io/", + nativeCurrency: "BTC", }, taiko: { address: "0x26DD80569a8B23768A1d80869Ed7339e07595E85", @@ -223,6 +250,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "mainnet", rpc: "https://rpc.mainnet.taiko.xyz", + nativeCurrency: "ETH", }, "etherlink-testnet": { address: "0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509", @@ -231,6 +259,7 @@ export const EntropyDeployments: Record = { gasLimit: "15M", network: "testnet", rpc: "https://node.ghostnet.etherlink.com", + nativeCurrency: "XTZ", }, etherlink: { address: "0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509", @@ -239,6 +268,7 @@ export const EntropyDeployments: Record = { gasLimit: "15M", network: "mainnet", rpc: "https://node.mainnet.etherlink.com/", + nativeCurrency: "XTZ", }, klaytn: { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", @@ -247,6 +277,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "mainnet", rpc: "https://rpc.ankr.com/klaytn", + nativeCurrency: "KLAY", }, "klaytn-testnet": { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", @@ -255,6 +286,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://rpc.ankr.com/klaytn_testnet", + nativeCurrency: "KLAY", }, "tabi-testnet": { address: "0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320", @@ -263,6 +295,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://rpc-internal.testnet.tabichain.com/", + nativeCurrency: "TABI", }, "b3-testnet": { address: "0x5744Cbf430D99456a0A8771208b674F27f8EF0Fb", @@ -271,6 +304,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://sepolia.b3.fun/http/", + nativeCurrency: "ETH", }, "b3-mainnet": { address: "0x5744Cbf430D99456a0A8771208b674F27f8EF0Fb", @@ -279,6 +313,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "mainnet", rpc: "https://mainnet-rpc.b3.fun/http", + nativeCurrency: "ETH", }, "apechain-testnet": { address: "0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509", @@ -287,6 +322,7 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://curtis.rpc.caldera.xyz/http", + nativeCurrency: "APE", }, "soneium-minato-testnet": { address: "0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509", @@ -295,5 +331,6 @@ export const EntropyDeployments: Record = { gasLimit: "500K", network: "testnet", rpc: "https://rpc.minato.soneium.org/", + nativeCurrency: "ETH", }, }; diff --git a/components/FeeTable.tsx b/components/FeeTable.tsx index b661d42b..d39b2088 100644 --- a/components/FeeTable.tsx +++ b/components/FeeTable.tsx @@ -51,7 +51,13 @@ const FeeTable = ({ - {fees[name] === undefined ? "Loading..." : fees[name]} + {fees[name] === undefined ? ( + "Loading..." + ) : ( + <> + {fees[name]} {deployment.nativeCurrency} + + )} ))} diff --git a/pages/entropy/contract-addresses.mdx b/pages/entropy/contract-addresses.mdx index cb61be61..adb380af 100644 --- a/pages/entropy/contract-addresses.mdx +++ b/pages/entropy/contract-addresses.mdx @@ -14,7 +14,7 @@ import EntropyDeploymentTable from "../../components/EntropyDeploymentTable"; showReveal={true} /> -The default provider for above mainnet chains is `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506`. +**The default provider for above mainnet chains is `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506`.** The default provider on mainnet has a reveal delay to avoid changes on the outcome of the Entropy request because of block reorgs. The reveal delay can be a number of blocks (measured from the `latest` block) or `safe` which means the reveal will be delayed until the request transaction is included in a block with `safe` tag. @@ -33,8 +33,8 @@ The default provider fulfills the request by sending a transaction with a gas li showReveal={false} /> -The default provider for above testnet chains is `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344`. +**The default provider for above testnet chains is `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344`.** -The default provider on testnet doesn't have a reveal delay. It reveals the commitment as soon as the request transaction is included in a block. +The default provider on testnet **doesn't have a reveal delay**. It reveals the commitment as soon as the request transaction is included in a block. The default provider fulfills the request by sending a transaction with a gas limit as mentioned in above table. Entropy callbacks the consumer as part of this transaction. diff --git a/pages/entropy/generate-random-numbers.mdx b/pages/entropy/generate-random-numbers.mdx index 4ada56c9..83561602 100644 --- a/pages/entropy/generate-random-numbers.mdx +++ b/pages/entropy/generate-random-numbers.mdx @@ -1,7 +1,5 @@ -# Generate Random Numbers +# How to Generate Random Numbers -Integrations simply call an on-chain function to request a random number from Entropy. -This function takes a random number that you have generated off-chain and returns a sequence number. -Entropy will then callback your contract with the generated random number once the request is fullfilled by the provider. +Integrating Pyth Entropy requires calling an onchain function to request a random number from Entropy. The function takes a random number that one can generate offchain and pass it to the Entropy contract which returns a sequence number. Pyth Entropy will then callback your contract with the generated random number once the request is fulfilled. See [How to Generate Random numbers in EVM dApps](generate-random-numbers/evm.mdx) to integrate your application with Pyth Entropy. diff --git a/pages/entropy/generate-random-numbers/evm.mdx b/pages/entropy/generate-random-numbers/evm.mdx index 5639569f..c3418d74 100644 --- a/pages/entropy/generate-random-numbers/evm.mdx +++ b/pages/entropy/generate-random-numbers/evm.mdx @@ -1,46 +1,68 @@ +import { Tabs, Callout } from "nextra/components"; + # How to Generate Random Numbers in EVM Contracts Using Pyth Entropy -This guide explains how to integrate Pyth Entropy into an EVM Contract to generate on-chain random numbers. +This guide explains how to integrate Pyth Entropy into EVM Contracts to generate on-chain random numbers. The intended audience for this guide is developers of any application that needs on-chain randomness, such as NFT mints or games. ## Install the SDK -Pyth Entropy has a Solidity SDK that lets your contract interact with the Entropy contract. +Pyth Entropy has a [Solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/entropy_sdk/solidity) that lets your contract interact with the Entropy contract. Install the SDK using your package manager: + + +```shell copy +npm install @pythnetwork/entropy-sdk-solidity +``` + + ```shell copy +npm init -y npm install @pythnetwork/entropy-sdk-solidity ``` +Then add the following line to your `remappings.txt` : + +```text copy +@pythnetwork/entropy-sdk-solidity/=node_modules/@pythnetwork/entropy-sdk-solidity +``` + + + + ## Setup -The SDK exports a `IEntropyConsumer` interface that your contract should implement. The interface -makes sure that your contract is compliant with the Entropy contract. +The Solidity SDK exports two interfaces: -The SDK also export `IEntropy` interface which you can use to interact with the Entropy contract. -You will need the address of an Entropy contract on your blockchain. -Consult the current [Entropy contract addresses](../contract-addresses) to find the address on your chain. -Once you have a contract address, instantiate an `IEntropy` contract in your solidity contract: +- [`IEntropyConsumer`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropyConsumer.sol) - The interface that your contract should implement. It makes sure that your contract is compliant with the Entropy contract. +- [`IEntropy`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol) - The interface to interact with the Entropy contract. + You will need the address of an Entropy contract on your blockchain. + Consult the current [Entropy contract addresses](../contract-addresses) to find the address on your chain. + Once you have a contract address, instantiate an `IEntropy` contract in your solidity contract: ```solidity copy import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; import { IEntropy } from "@pythnetwork/entropy-sdk-solidity/IEntropy.sol"; -contract YourContract is IEntropyConsumer { - IEntropy entropy = IEntropy(
); +// @param entropyAddress The address of the entropy contract. +contract YourContract(address entropyAddress) is IEntropyConsumer { + IEntropy entropy = IEntropy(entropyAddress); } - ``` -Entropy also requires selecting a randomness provider. The randomness provider is a third-party + +Entropy also requires selecting a **randomness provider**. The randomness provider is a third-party who participates in the generation process. Each provider is identified by an address and hosts a keeper service for fullfilling requests. -The simplest way to choose a provider is to use the default provider. +The simplest way to choose a provider is to use the [default provider](../contract-addresses). The default provider for each contract and their corresponding URI is also listed in the [Entropy contract addresses](../contract-addresses). -You can also get the default provider's address by calling the `getDefaultProvider` method: + + +You can also get the default provider's address by calling the [`getDefaultProvider`](https://github.com/pyth-network/pyth-crosschain/blob/f8ebeb6af31d98f94ce73edade6da2ebab7b2456/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L94) method: ```solidity copy address provider = entropy.getDefaultProvider(); @@ -53,49 +75,110 @@ To generate a random number, follow these steps. ### 1. Generate a random number Generate a 32-byte random number on the client side. -You can do this with typescript and web3.js as follows: -```typescript copy -const randomNumber = web3.utils.randomHex(32); -``` + + + ```typescript copy const userRandomNumber = web3.utils.randomHex(32); ``` + + + ```typescript copy const userRandomNumber = ethers.utils.randomBytes(32); + ``` + + ### 2. Request a number from Entropy -Invoke the `requestWithCallback` method of the `IEntropy` contract. +Invoke the [`requestWithCallback`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L83) method of the `IEntropy` contract. The `requestWithCallback` method requires paying a fee in native gas tokens which is configured per-provider. -Use the `getFee` method to calculate the fee and send it as the value of the `requestWithCallback` call: + +The fees differs for every chain and can be found at the [Current Fees](../current-fees) page. \ +You can use the onchain method [`getFee`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L101) to calculate the fee for the default provider and send it as the value of the `requestWithCallback` call: ```solidity copy -uint fee = entropy.getFee(provider); -uint64 sequenceNumber = entropy.requestWithCallback{value: fee}(provider, randomNumber); +function requestRandomNumber(bytes32 userRandomNumber) external payable { + uint256 fee = entropy.getFee(entropyProvider); + + uint64 sequenceNumber = entropy.requestWithCallback{ value: fee }( + entropyProvider, + userRandomNumber + ); +} + ``` -This method returns a sequence number and emits a `RequestedWithCallback` event. You can store this sequence number to identify the request in next step. +This method returns a sequence number and emits a [`RequestedWithCallback`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/EntropyEvents.sol#L10) event. You can store this sequence number to identify the request in next step. ### 3. Implement callback for Entropy -```solidity copy -// This method is required by the IEntropyConsumer interface. -// It returns the address of the entropy contract which will call the callback. -function getEntropy() internal view override returns (address) { - return address(entropy); -} +```solidity {28-38} copy +pragma solidity ^0.8.0; + +import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; +import { IEntropy } from "@pythnetwork/entropy-sdk-solidity/IEntropy.sol"; -// It is called by the entropy contract when a random number is generated. -function entropyCallback( - uint64 sequenceNumber, - // If your app uses multiple providers, you can use this argument to - // distinguish which one is calling the app back. - address provider, - bytes32 randomNumber -) internal override { - // Implement your callback logic here. +contract YourContract is IEntropyConsumer { + IEntropy entropy; + + // @param entropyAddress The address of the entropy contract. + constructor(address entropyAddress) { + entropy = IEntropy(entropyAddress); + } + + // @param userRandomNumber The random number generated by the user. + function requestRandomNumber(bytes32 userRandomNumber) external payable { + // Get the default provider and the fee for the request + address entropyProvider = entropy.getDefaultProvider(); + uint256 fee = entropy.getFee(entropyProvider); + + // Request the random number with the callback + uint64 sequenceNumber = entropy.requestWithCallback{ value: fee }( + entropyProvider, + userRandomNumber + ); + // Store the sequence number to identify the callback request + } + + // @param sequenceNumber The sequence number of the request. + // @param provider The address of the provider that generated the random number. If your app uses multiple providers, you can use this argument to distinguish which one is calling the app back. + // @param randomNumber The generated random number. + // This method is called by the entropy contract when a random number is generated. + function entropyCallback( + uint64 sequenceNumber, + address provider, + bytes32 randomNumber + ) internal override { + // Implement your callback logic here. + } + + // This method is required by the IEntropyConsumer interface. + // It returns the address of the entropy contract which will call the callback. + function getEntropy() internal view override returns (address) { + return address(entropy); + } } ``` -When the final random number is ready to use, the entropyCallback function will be called by the Entropy contract. This will happen in a separate transaction submitted by the requested provider. The entropyCallback function should be implemented in the same contract that is requesting the random number. +When the final random number is ready to use, the entropyCallback function will be called by the Entropy contract. This will happen in a separate transaction submitted by the requested provider. + +**The entropyCallback function should be implemented in the same contract that is requesting the random number.** ## Additional Resources -If you are having trouble getting the callback to run, please see the guide on how to [Debug Callback Failures](/entropy/debug-callback-failures). +You may find these additional resources helpful while integrating Pyth Entropy into your EVM contract. + +### Debug Callback Failures + +Check how to [Debug Callback Failures](../debug-callback-failures) if you are having trouble getting the callback to run. + +### Pyth Entropy Contract Addresses + +Consult the [Entropy contract addresses](../contract-addresses) to find the Entropy contract address on your chain. + +### Current Fees + +Check the [Current Fees](../current-fees) to find the current fee for each provider on your chain. + +### Best Practices + +Check out the [Best Practices](../best-practices) guide for tips to limit gas usage, or generate multiple random numbers in a single transaction.