From 19be573bc6b0d20aac3bab33d6617717fe593223 Mon Sep 17 00:00:00 2001 From: Aditya Arora Date: Thu, 4 Sep 2025 15:10:57 -0400 Subject: [PATCH 1/4] chore(dev-docs) Entropy Guide Edits - 1 --- .../entropy/generate-random-numbers-evm.mdx | 189 +++++++++++++++ .../docs/entropy/generate-random-numbers.mdx | 10 - .../docs/entropy/how-to-guides/index.mdx | 8 - .../content/docs/entropy/index.mdx | 26 +- .../content/docs/entropy/meta.json | 17 +- .../docs/entropy/set-custom-gas-limits.mdx | 222 ++++++++++++++---- .../docs/entropy/whats-new-entropyv2.mdx | 24 +- apps/developer-hub/src/source.ts | 2 + 8 files changed, 401 insertions(+), 97 deletions(-) create mode 100644 apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx delete mode 100644 apps/developer-hub/content/docs/entropy/generate-random-numbers.mdx delete mode 100644 apps/developer-hub/content/docs/entropy/how-to-guides/index.mdx diff --git a/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx new file mode 100644 index 0000000000..65f27d6e61 --- /dev/null +++ b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx @@ -0,0 +1,189 @@ +--- +title: Generate Random Numbers onchain +description: Learn how to integrate Pyth Entropy to generate random numbers in your dapp +--- + +import { Step, Steps } from "fumadocs-ui/components/steps"; + +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](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` file: + +```text copy +@pythnetwork/entropy-sdk-solidity/=node_modules/@pythnetwork/entropy-sdk-solidity +``` + + + + +## Setup + +The Solidity SDK exports two interfaces: + +- [`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. +- [`IEntropyV2`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropyV2.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 `console.log("IEntropyV2"){:bash}` contract in your solidity contract: + +```solidity copy +import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; +import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; + +// @param entropyAddress The address of the entropy contract. +contract YourContract is IEntropyConsumer { + IEntropyV2 public entropy; + + constructor(address entropyAddress) { + entropy = IEntropyV2(entropyAddress); + } +} + +``` + +## Usage + +To generate a random number, follow these steps. + + + +### 1. Request a number from Entropy + +Invoke the [`requestV2`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L83) method of the `IEntropyV2` interface. +The `console.log("requestV2"){:bash}` method requires paying a fee in native gas tokens which is configured per-provider. + +The fee differs for every chain and also varies over time depending on the chain's current gas price. +The current value for each chain can be found on the [Current Fees](../current-fees) page. +However, you should use the on-chain method [`getFeeV2`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L101) to compute the required fee and send it as the value of the `requestV2{:bash}` call. + +These methods use the default randomness provider ([see here](#randomness-providers) for more info on providers). + +```solidity copy +function requestRandomNumber() external payable { + uint256 fee = entropy.getFeeV2(); + + uint64 sequenceNumber = entropy.requestV2{ value: fee }(); +} + +``` + +This method returns a sequence number and emits a [`Requested`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/EntropyEventsV2.sol#L30) event. You can store this sequence number to identify the request in next step. + +Note that there are several variants of `requestV2` that allow the caller to configure the provider fulfilling the request and the gas limit for the callback. Refer [request callback variants](../request-callback-variants.mdx) for more details. + +Please see the method documentation in the [IEntropyV2 interface](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropyV2.sol). + + + + +### 2. Implement the Entropy callback + +```solidity {31-45} copy +pragma solidity ^0.8.0; + +import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; +import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; + +contract YourContract is IEntropyConsumer { + IEntropyV2 entropy; + + // @param entropyAddress The address of the entropy contract. + constructor(address entropyAddress) { + entropy = IEntropyV2(entropyAddress); + } + + function requestRandomNumber() external payable { + // Get the fee for the request + uint256 fee = entropy.getFeeV2(); + + // Request the random number with the callback + uint64 sequenceNumber = entropy.requestV2{ value: fee }(); + // 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. + // This method **must** be implemented on the same contract that requested the random number. + // This method should **never** return an error -- if it returns an error, then the keeper will not be able to invoke the callback. + // If you are having problems receiving the callback, the most likely cause is that the callback is erroring. + // See the callback debugging guide here to identify the error https://docs.pyth.network/entropy/debug-callback-failures + 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 on your contract should **never** return an + error. If it returns an error, the keeper will not be able to invoke the + callback. If you are having problems receiving the callback, please see + [Debugging Callback Failures](/entropy/debug-callback-failures). + + +## Additional Resources + +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. + +### Randomness providers + +Some methods on Entropy require 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. + +You can 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(); +``` diff --git a/apps/developer-hub/content/docs/entropy/generate-random-numbers.mdx b/apps/developer-hub/content/docs/entropy/generate-random-numbers.mdx deleted file mode 100644 index 873f402744..0000000000 --- a/apps/developer-hub/content/docs/entropy/generate-random-numbers.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: How to Generate Random Numbers -description: Learn how to integrate Pyth Entropy to generate random numbers in your application ---- - -# How to Generate Random Numbers - -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) to integrate your application with Pyth Entropy. diff --git a/apps/developer-hub/content/docs/entropy/how-to-guides/index.mdx b/apps/developer-hub/content/docs/entropy/how-to-guides/index.mdx deleted file mode 100644 index eebae79a09..0000000000 --- a/apps/developer-hub/content/docs/entropy/how-to-guides/index.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Entropy How-To Guide -description: A placeholder docs page ---- - -# How To - -Build secure smart contracts with provably random numbers from Pyth Entropy. Launch NFTs, games, and other unique experiences that your users trust with seamless UX. diff --git a/apps/developer-hub/content/docs/entropy/index.mdx b/apps/developer-hub/content/docs/entropy/index.mdx index 822353c1fa..d223592454 100644 --- a/apps/developer-hub/content/docs/entropy/index.mdx +++ b/apps/developer-hub/content/docs/entropy/index.mdx @@ -1,31 +1,33 @@ --- title: Entropy -description: Random number Generator for Ethereum smart contracts +description: Secure, Verifiable Random Number Generator for EVM-based smart contracts icon: DiceSix full: true --- -# Entropy +**Pyth Entropy** is an on-chain random number generator (RNG) designed for developers who need fair, unbiased, and cryptographically secure randomness. +Whether you're building a blockchain game, NFT mint, lottery, or simulation, Entropy delivers randomness that is: -Pyth Entropy allows developers to quickly and easily generate secure random numbers on the blockchain. -Entropy's rapid response time allows developers to build applications such as NFT mints and games with responsive UX. -Entropy also provides [strong security guarantees](protocol-design) to ensure that both users and application developers can trust that the results are random. +- **Trustless & verifiable** - built on commit-reveal(TODO: link to commit-reveal). +- **Low-latency** - randomness available within a few blocks(TODO: link to latency). +- **Easy to integrate** - Permissionless Integration, Visual Tx Explorer(TODO: link to explorer). +- **Cost-efficient** - designed for scalable production use(TODO: link to fees). +- **Native gas fees** - pay with chain native token. -Pyth Entropy is currently available on several [EVM networks](contract-addresses). -If you would like a deployment on another network, please [ask in Discord](https://discord.gg/invite/PythNetwork). +## What's New in Entropy v2 + +Entropy v2 introduces several improvements and new features to make random number generation more flexible and efficient. +See [What's New in Entropy v2](whats-new-entropyv2) for more details. +(TODO: This can be displayed in a banner above) (TODO: Add aan infographic here) ## Getting Started Using Pyth Entropy is permissionless and developers can integrate in a few minutes. Please see [How to Generate Random Numbers Using Pyth Entropy](generate-random-numbers) to start integrating Pyth Entropy into your application. -## Additional Resources - -To learn more about how the protocol works, please see [Protocol design](protocol-design). - ## Reference Material - [Protocol design](protocol-design) -- [Contract Addresses](contract-addresses) +- [Contract Addresses/Supported Networks](contract-addresses) - [Error Codes](error-codes) - [Entropy Debugger](https://entropy-debugger.pyth.network/) - Interactive tool for diagnosing callback issues diff --git a/apps/developer-hub/content/docs/entropy/meta.json b/apps/developer-hub/content/docs/entropy/meta.json index 7cbe03ce52..49040f31ab 100644 --- a/apps/developer-hub/content/docs/entropy/meta.json +++ b/apps/developer-hub/content/docs/entropy/meta.json @@ -4,21 +4,22 @@ "description": "Random number Generator for Ethereum smart contracts", "icon": "DiceSix", "pages": [ + "---Introduction---", "index", - "generate-random-numbers", - "create-your-first-entropy-app", - "protocol-design", + "whats-new-entropyv2", + "---How-To Guides---", + "generate-random-numbers-evm", + "set-custom-gas-limits", + "debug-callback-failures", + "---Reference Material---", "contract-addresses", "best-practices", "fees", + "protocol-design", "current-fees", "error-codes", - "debug-callback-failures", "examples", "request-callback-variants", - "set-custom-gas-limits", - "whats-new-entropyv2", - "---Guides---", - "how-to-guides" + "create-your-first-entropy-app" ] } diff --git a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx index 57ddf20f44..7501eefaaa 100644 --- a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx +++ b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx @@ -3,84 +3,202 @@ title: Set Custom Gas Limits description: How to set custom gas limits for Entropy callbacks --- -# Set Custom Gas Limits +import { Step, Steps } from "fumadocs-ui/components/steps"; -By default, Pyth Entropy uses a predefined gas limit for callback functions. However, you may need to adjust this limit based on the complexity of your callback implementation. +Custom gas limits are useful when your callback function requires more gas than the default provider limit, or when you want to optimize gas costs for simpler callbacks. -## When to Use Custom Gas Limits +## Prerequisites -### Use Higher Gas Limits When: +Before following this guide, you should first complete the basic setup from the [Generate Random Numbers in EVM Contracts](./generate-random-numbers-evm.mdx) guide. This guide builds upon that foundation and assumes you have: -- Your callback function performs complex calculations -- You need to update multiple storage variables -- Your callback interacts with other contracts -- You're implementing complex game logic +- Installed the Pyth Entropy Solidity SDK +- Set up your contract with the `IEntropyConsumer` interface +- Implemented the basic `entropyCallback` function -### Use Lower Gas Limits When: +## When to Use Custom Gas Limits -- Your callback function is simple (e.g., just stores a single value) -- You want to optimize for cost -- You want to prevent potential gas griefing +You might need custom gas limits in these scenarios: -## Implementation +- **Complex callback logic**: Your `entropyCallback` function performs computationally expensive operations +- **Gas optimization**: You want to use less gas for simple callbacks to reduce fees +- **Multiple operations**: Your callback needs to perform multiple state changes or external calls +- **Integration requirements**: Your application has specific gas requirements for reliability -### Using EntropyV2 Interface +## Implementation -```solidity -import "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; +### 1. Use requestV2 with Gas Limit Parameter -contract MyContract is IEntropyConsumer { - IEntropyV2 entropy; +Instead of the basic `requestV2()` method, use the variant that accepts a `gasLimit` parameter: - function requestWithCustomGas() external payable { - uint32 customGasLimit = 200000; // Adjust based on your needs +```solidity copy +function requestRandomNumberWithCustomGas( + uint32 customGasLimit +) external payable { + // Calculate the fee for the custom gas limit + uint256 fee = entropy.getFeeV2(customGasLimit); - // Get fee for custom gas limit - uint256 fee = entropy.getFeeV2(customGasLimit); - require(msg.value >= fee, "Insufficient fee"); + // Request random number with custom gas limit + uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); - // Request with custom gas limit - uint64 sequenceNumber = entropy.requestV2{value: fee}(customGasLimit); - } + // Store the sequence number for tracking if needed } + ``` -### Full Control Request +### 2. Calculate Fees with Custom Gas Limit + +When using custom gas limits, you must use the `getFeeV2` variant that accepts a `gasLimit` parameter: + +```solidity copy +// Get fee for custom gas limit +uint256 fee = entropy.getFeeV2(customGasLimit); + +// NOT: uint256 fee = entropy.getFeeV2(); // This uses default gas limit +``` + +### 3. Complete Example + +Here's a complete example showing how to implement custom gas limits: -```solidity -function requestWithFullControl() external payable { - address provider = entropy.getDefaultProvider(); - uint32 gasLimit = 150000; - bytes32 userRandomNumber = keccak256(abi.encode(block.timestamp, msg.sender)); +```solidity copy +pragma solidity ^0.8.0; + +import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; +import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; + +contract CustomGasLimitExample is IEntropyConsumer { + IEntropyV2 public entropy; + mapping(uint64 => bool) public processedRequests; + + constructor(address entropyAddress) { + entropy = IEntropyV2(entropyAddress); + } + + // Request with custom gas limit for complex callback + function requestComplexRandomNumber() external payable { + uint32 customGasLimit = 200000; // Higher limit for complex operations + uint256 fee = entropy.getFeeV2(customGasLimit); - uint256 fee = entropy.getFeeV2(provider, gasLimit); require(msg.value >= fee, "Insufficient fee"); - uint64 sequenceNumber = entropy.requestV2{value: fee}( - provider, - gasLimit, - userRandomNumber - ); + uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); + // Store sequence number if needed for tracking + } + + // Request with lower gas limit for simple callback + function requestSimpleRandomNumber() external payable { + uint32 customGasLimit = 50000; // Lower limit for simple operations + uint256 fee = entropy.getFeeV2(customGasLimit); + + require(msg.value >= fee, "Insufficient fee"); + + uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); + } + + // Complex callback that requires more gas + function entropyCallback( + uint64 sequenceNumber, + address provider, + bytes32 randomNumber + ) internal override { + // Prevent duplicate processing + require(!processedRequests[sequenceNumber], "Already processed"); + processedRequests[sequenceNumber] = true; + + // Complex operations that require more gas + for (uint i = 0; i < 10; i++) { + // Simulate complex state changes + // This would require more gas than the default limit + } + + // Use the random number for your application logic + uint256 randomValue = uint256(randomNumber); + // Your application logic here... + } + + function getEntropy() internal view override returns (address) { + return address(entropy); + } } + ``` ## Gas Limit Constraints -Each network has different gas limit constraints: +When setting custom gas limits, be aware of these constraints: + + + - Gas limits are automatically rounded up to the nearest multiple of 10,000. - + Example: 19,000 becomes 20,000, 25,500 becomes 30,000. - The minimum gas limit + is the provider's configured default limit. - The maximum gas limit is + 655,350,000 (uint16.max × 10,000). + + +### Recommended Gas Limits -| Network | Min Gas Limit | Max Gas Limit | Default | -| --------- | ------------- | ------------- | ------- | -| Ethereum | 50,000 | 100,000 | 100,000 | -| Arbitrum | 50,000 | 100,000 | 100,000 | -| Avalanche | 50,000 | 100,000 | 100,000 | -| Base | 50,000 | 100,000 | 100,000 | -| BNB Chain | 50,000 | 100,000 | 100,000 | -| Optimism | 50,000 | 100,000 | 100,000 | -| Polygon | 50,000 | 100,000 | 100,000 | +- **Simple callbacks**: 50,000 - 100,000 gas +- **Moderate complexity**: 100,000 - 200,000 gas +- **Complex operations**: 200,000 - 500,000 gas +- **Very complex logic**: 500,000+ gas (use with caution) ## Best Practices -1. **Test your callback function** to estimate gas usage before setting custom limits -2. **Add a buffer** of 10-20% to your estimated gas usage for safety -3. **Use the minimum necessary** gas limit to reduce costs -4. **Consider network differences** - some networks may have different gas costs for similar operations +### 1. Estimate Gas Usage + +Test your callback function to determine the actual gas usage: + +```solidity copy +// In your tests, measure gas usage +uint256 gasStart = gasleft(); +// Your callback logic here +uint256 gasUsed = gasStart - gasleft(); +console.log("Gas used:", gasUsed); +``` + +### 2. Add Safety Buffer + +Always add a safety buffer to your estimated gas usage: + +```solidity copy +uint32 estimatedGas = 150000; +uint32 safetyBuffer = 20000; +uint32 customGasLimit = estimatedGas + safetyBuffer; +``` + +### 3. Handle Gas Limit Errors + +Be prepared to handle cases where your gas limit is insufficient: + + + If your callback runs out of gas, the entropy provider will not be able to + complete the callback. Always test your gas limits thoroughly and include + adequate safety margins. + + +### 4. Consider Fee Implications + +Higher gas limits result in higher fees. Balance your gas needs with cost considerations: + +```solidity copy +// Compare fees for different gas limits +uint256 defaultFee = entropy.getFeeV2(); +uint256 customFee = entropy.getFeeV2(customGasLimit); +uint256 additionalCost = customFee - defaultFee; +``` + +## Troubleshooting + +If you're experiencing issues with custom gas limits: + +1. **Callback not executing**: Your gas limit might be too low +2. **High fees**: Consider optimizing your callback or using a lower gas limit +3. **Reverts**: Check that your gas limit doesn't exceed the maximum allowed + +For more debugging help, see the [Debug Callback Failures](/entropy/debug-callback-failures) guide. + +## Additional Resources + +- [Generate Random Numbers in EVM Contracts](/entropy/generate-random-numbers/evm) - Basic setup guide +- [Best Practices](/entropy/best-practices) - General optimization tips +- [Current Fees](/entropy/current-fees) - Fee information for different chains +- [Contract Addresses](/entropy/contract-addresses) - Entropy contract deployments diff --git a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx index ca1c5e934b..53f14655ad 100644 --- a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx +++ b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx @@ -1,14 +1,13 @@ --- title: What's New in Entropy v2 description: New features and improvements in Entropy v2 +icon: Sparkle --- -# What's New in Entropy v2 - -Entropy v2 introduces several improvements and new features to make random number generation more flexible and efficient. - ## Key Improvements +Pyth Entropy v2 brings new features and improvements that make random number generation more flexible, efficient, and easier to integrate. + ### 1. Multiple Request Variants Entropy v2 provides multiple ways to request random numbers: @@ -18,6 +17,8 @@ Entropy v2 provides multiple ways to request random numbers: - **Custom Provider**: Choose specific entropy providers - **Full Control**: Specify all parameters (provider, gas limit, user random number) +Each of these request types is described in more detail with examples in [Request Callback Variants](request-callback-variants). + ### 2. Improved Fee Structure The new version offers more granular fee calculation: @@ -33,17 +34,26 @@ uint256 customGasFee = entropy.getFeeV2(gasLimit); uint256 providerFee = entropy.getFeeV2(provider, gasLimit); ``` -### 3. Better Error Handling +### 3. Enhanced Callback Status + +Entropy V2 introduces callback statuses, which allow users to track the status of their callbacks. + +[Pyth Dev-Forum Announcement](https://dev-forum.pyth.network/t/announcing-entropy-v2/324#p-649-enhanced-callback-statuses-2) provides more details on enhanced callback statuses. + +### 4. Entropy Debugger + +Entropy V2 includes a public Entropy Explorer, that lets teams easily track the status of their callbacks and re-request them if they fail on-chain. -Enhanced error messages and more specific error codes help developers debug issues more effectively. +See [Entropy Explorer](https://entropy-debugger.pyth.network/) to search and debug your callbacks. -### 4. Gas Optimization +### 5. Gas Optimization Improved contract efficiency reduces overall gas costs for entropy requests. ## Migration Guide If you're upgrading from Entropy v1 to v2: +(TODO: Add links to the interface) 1. Update your imports to use `IEntropyV2` 2. Replace `request()` calls with `requestV2()` diff --git a/apps/developer-hub/src/source.ts b/apps/developer-hub/src/source.ts index 8d55e0c6f2..ad9e33634a 100644 --- a/apps/developer-hub/src/source.ts +++ b/apps/developer-hub/src/source.ts @@ -6,6 +6,7 @@ import { Lightning, Shuffle, DiceSix, + Sparkle, } from "@phosphor-icons/react/dist/ssr"; import type { InferMetaType, InferPageType } from "fumadocs-core/source"; import { loader } from "fumadocs-core/source"; @@ -20,6 +21,7 @@ const icons: Record = { Lightning, Shuffle, DiceSix, + Sparkle, }; export const source = loader({ From efb003ed626ed09318cba824ba2a92a72810db8b Mon Sep 17 00:00:00 2001 From: Aditya Arora Date: Fri, 5 Sep 2025 12:59:27 -0400 Subject: [PATCH 2/4] chore(dev-docs): update entropy edits --- .../docs/entropy/debug-callback-failures.mdx | 42 +++++++------ .../entropy/generate-random-numbers-evm.mdx | 50 ++++++++-------- .../docs/entropy/set-custom-gas-limits.mdx | 59 +++++++++---------- .../docs/entropy/whats-new-entropyv2.mdx | 6 +- apps/developer-hub/src/app/(docs)/layout.tsx | 2 +- .../src/app/(homepage)/layout.tsx | 2 +- 6 files changed, 81 insertions(+), 80 deletions(-) diff --git a/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx b/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx index c403d1ab31..5597cce6ba 100644 --- a/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx +++ b/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx @@ -2,65 +2,70 @@ title: Debug Callback Failures description: How to identify and resolve issues with Entropy callbacks --- +import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; -# Debug Callback Failures +This guide explains how to identify and resolve issues with the Entropy callback. +The intended audience for this guide is developers who have made an Entropy random number request, but their application hasn't received a callback. > 🔍 **Quick Debug Tool** +> > Use the [Entropy Explorer](https://entropy-debugger.pyth.network/) to quickly diagnose and resolve callback issues. -This guide explains how to identify and resolve issues with the Entropy callback. -The intended audience for this guide is developers who have made an Entropy random number request, but their application hasn't received a callback. ## Dependencies This guide uses [Foundry](https://book.getfoundry.sh/getting-started/installation) to submit transactions to the blockchain. Please install Foundry before continuing. - ## Run the Callback Developers can run the Entropy callback themselves to see the reason for the failure. To run the callback, invoke the `revealWithCallback` function on the Entropy contract on your blockchain. The function has the following signature: -```solidity -function revealWithCallback( + -This call requires the chain ID, contract address, and four arguments. +This call requires the chain ID, contract address, and four other arguments. The chain ID and contract address can be retrieved from [Contract Addresses](contract-addresses). Export these values as environment variables for later use: -```bash -export CHAIN_ID=blast + -Three of the arguments can be retrieved from the request transaction's event logs. +Three of the other arguments can be retrieved from the request transaction's event logs. Look at the event logs of the request transaction in a block explorer. You should see a `RequestedWithCallback` event emitted from the Entropy contract. Copy the following values from the event into environment variables: -```bash -export PROVIDER=0x52DeaA1c84233F7bb8C8A45baeDE41091c616506 + -The fourth argument (provider revelation) must be retrieved from the provider's API. +The fourth argument (provider contribution) must be retrieved from the provider's API. This value becomes available after the reveal delay has passed. ## Common Issues +There are a few common issues that can cause the callback to fail. + ### Gas Limit Exceeded If your callback function uses too much gas, the transaction will fail. Check the gas limit for your chain on the [contract addresses](contract-addresses) page and ensure your callback function uses less gas. +> 💡 **Tip** +> Refer to the [Set Custom Gas Limits](set-custom-gas-limits) guide to set a custom gas limit for your callback function. + ### Callback Function Errors Your callback function might contain logic that throws an error. Review your callback implementation for: @@ -73,3 +78,4 @@ Your callback function might contain logic that throws an error. Review your cal ### Transaction Timing Make sure you're attempting the callback after the reveal delay has passed. The reveal delay varies by network and helps prevent MEV attacks. +Refer to the [Contract Addresses](contract-addresses) page for the reveal delay for each network. \ No newline at end of file diff --git a/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx index 65f27d6e61..0e9bacb42d 100644 --- a/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx +++ b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx @@ -4,6 +4,7 @@ description: Learn how to integrate Pyth Entropy to generate random numbers in y --- import { Step, Steps } from "fumadocs-ui/components/steps"; +import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; 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. @@ -15,21 +16,19 @@ Install the SDK using your package manager: -```shell copy -npm install @pythnetwork/entropy-sdk-solidity -``` + -```shell copy -npm init -y + Then add the following line to your `remappings.txt` file: -```text copy -@pythnetwork/entropy-sdk-solidity/=node_modules/@pythnetwork/entropy-sdk-solidity -``` + @@ -44,8 +43,8 @@ The Solidity SDK exports two interfaces: Consult the current [Entropy contract addresses](../contract-addresses) to find the address on your chain. Once you have a contract address, instantiate an `console.log("IEntropyV2"){:bash}` contract in your solidity contract: -```solidity copy -import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol"; + ## Usage @@ -65,7 +63,7 @@ To generate a random number, follow these steps. -### 1. Request a number from Entropy +### Request a number from Entropy Invoke the [`requestV2`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol#L83) method of the `IEntropyV2` interface. The `console.log("requestV2"){:bash}` method requires paying a fee in native gas tokens which is configured per-provider. @@ -76,14 +74,13 @@ However, you should use the on-chain method [`getFeeV2`](https://github.com/pyth These methods use the default randomness provider ([see here](#randomness-providers) for more info on providers). -```solidity copy -function requestRandomNumber() external payable { + This method returns a sequence number and emits a [`Requested`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/entropy_sdk/solidity/EntropyEventsV2.sol#L30) event. You can store this sequence number to identify the request in next step. @@ -94,10 +91,10 @@ Please see the method documentation in the [IEntropyV2 interface](https://github -### 2. Implement the Entropy callback +### Implement the Entropy callback -```solidity {31-45} copy -pragma solidity ^0.8.0; + 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 on your contract should **never** return an error. If it returns an error, the keeper will not be able to invoke the callback. If you are having problems receiving the callback, please see @@ -184,6 +180,6 @@ a keeper service for fullfilling requests. You can 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(); -``` + diff --git a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx index 7501eefaaa..50ed58f6f4 100644 --- a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx +++ b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx @@ -4,8 +4,9 @@ description: How to set custom gas limits for Entropy callbacks --- import { Step, Steps } from "fumadocs-ui/components/steps"; +import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; -Custom gas limits are useful when your callback function requires more gas than the default provider limit, or when you want to optimize gas costs for simpler callbacks. +Custom gas limits are useful when your callback function requires more gas than the [default provider limit]TODO(../contract-addresses), or when you want to optimize gas costs for simpler callbacks. ## Prerequisites @@ -30,8 +31,8 @@ You might need custom gas limits in these scenarios: Instead of the basic `requestV2()` method, use the variant that accepts a `gasLimit` parameter: -```solidity copy -function requestRandomNumberWithCustomGas( + ### 2. Calculate Fees with Custom Gas Limit When using custom gas limits, you must use the `getFeeV2` variant that accepts a `gasLimit` parameter: -```solidity copy -// Get fee for custom gas limit + ### 3. Complete Example Here's a complete example showing how to implement custom gas limits: -```solidity copy -pragma solidity ^0.8.0; + ## Gas Limit Constraints When setting custom gas limits, be aware of these constraints: - - - Gas limits are automatically rounded up to the nearest multiple of 10,000. - - Example: 19,000 becomes 20,000, 25,500 becomes 30,000. - The minimum gas limit - is the provider's configured default limit. - The maximum gas limit is - 655,350,000 (uint16.max × 10,000). + +Gas limits are automatically rounded up to the nearest multiple of **10,000**. +Example: 19,000 becomes 20,000 25,500 becomes 30,000. The minimum gas limit +is the provider's configured default limit. The maximum gas limit is +655,350,000 (`uint16.max` \* 10,000). ### Recommended Gas Limits @@ -147,44 +146,44 @@ When setting custom gas limits, be aware of these constraints: Test your callback function to determine the actual gas usage: -```solidity copy -// In your tests, measure gas usage + ### 2. Add Safety Buffer Always add a safety buffer to your estimated gas usage: -```solidity copy -uint32 estimatedGas = 150000; + ### 3. Handle Gas Limit Errors Be prepared to handle cases where your gas limit is insufficient: - - If your callback runs out of gas, the entropy provider will not be able to - complete the callback. Always test your gas limits thoroughly and include - adequate safety margins. + +If your callback **runs out of gas**, the entropy provider will **not** be able to +complete the callback. Always test your gas limits thoroughly and include +adequate safety margins. ### 4. Consider Fee Implications Higher gas limits result in higher fees. Balance your gas needs with cost considerations: -```solidity copy -// Compare fees for different gas limits + ## Troubleshooting diff --git a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx index 53f14655ad..067063f52c 100644 --- a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx +++ b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx @@ -3,6 +3,7 @@ title: What's New in Entropy v2 description: New features and improvements in Entropy v2 icon: Sparkle --- +import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; ## Key Improvements @@ -23,8 +24,7 @@ Each of these request types is described in more detail with examples in [Reques The new version offers more granular fee calculation: -```solidity -// Get fee for default provider and gas limit + ### 3. Enhanced Callback Status diff --git a/apps/developer-hub/src/app/(docs)/layout.tsx b/apps/developer-hub/src/app/(docs)/layout.tsx index fa21b1c472..c5319f0a4a 100644 --- a/apps/developer-hub/src/app/(docs)/layout.tsx +++ b/apps/developer-hub/src/app/(docs)/layout.tsx @@ -5,7 +5,7 @@ import { docsOptions } from "../../config/layout.config"; export default function Layout({ children }: { children: ReactNode }) { return ( - + {children} ); diff --git a/apps/developer-hub/src/app/(homepage)/layout.tsx b/apps/developer-hub/src/app/(homepage)/layout.tsx index 6a05991a71..46e9fad9dd 100644 --- a/apps/developer-hub/src/app/(homepage)/layout.tsx +++ b/apps/developer-hub/src/app/(homepage)/layout.tsx @@ -5,7 +5,7 @@ import { baseOptions } from "../../config/layout.config"; export default function Layout({ children }: { children: ReactNode }) { return ( - + {children} ); From 86c3dfb750487a6285d0b95c780d0045b6226da8 Mon Sep 17 00:00:00 2001 From: Aditya Arora Date: Fri, 5 Sep 2025 15:02:16 -0400 Subject: [PATCH 3/4] chore(dev-docs) Entropy Contract Address table --- .../docs/entropy/contract-addresses.mdx | 26 +--- .../docs/entropy/debug-callback-failures.mdx | 33 +++-- .../entropy/generate-random-numbers-evm.mdx | 91 +++++++------ .../docs/entropy/set-custom-gas-limits.mdx | 107 ++++++++------- .../docs/entropy/whats-new-entropyv2.mdx | 3 +- apps/developer-hub/package.json | 1 + apps/developer-hub/src/app/(docs)/layout.tsx | 6 +- .../src/app/(homepage)/layout.tsx | 6 +- .../src/components/CopyAddress/index.tsx | 7 +- .../src/components/EntropyTable/constants.ts | 4 + .../EntropyTable/entropy-api-data-fetcher.tsx | 72 ++++++++++ .../entropy-deployments-config.ts | 25 ++++ .../src/components/EntropyTable/index.tsx | 125 ++++++++++++++++++ pnpm-lock.yaml | 3 + 14 files changed, 366 insertions(+), 143 deletions(-) create mode 100644 apps/developer-hub/src/components/EntropyTable/constants.ts create mode 100644 apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx create mode 100644 apps/developer-hub/src/components/EntropyTable/entropy-deployments-config.ts create mode 100644 apps/developer-hub/src/components/EntropyTable/index.tsx diff --git a/apps/developer-hub/content/docs/entropy/contract-addresses.mdx b/apps/developer-hub/content/docs/entropy/contract-addresses.mdx index 4132bf935e..d745ef6f8a 100644 --- a/apps/developer-hub/content/docs/entropy/contract-addresses.mdx +++ b/apps/developer-hub/content/docs/entropy/contract-addresses.mdx @@ -1,23 +1,15 @@ --- title: Contract Addresses -description: Entropy contract addresses on different networks +description: Pyth Entropy contract addresses on EVM networks --- -# Entropy Contract Addresses on EVM +import { EntropyTable } from "../../../src/components/EntropyTable"; ## Mainnets The Entropy contract is deployed on the following mainnet chains: -| Network | Contract Address | Gas Limit | Provider | -| --------- | -------------------------------------------- | --------- | -------------------------------------------- | -| Ethereum | `0x98046Bd286715D3B0BC227Dd7a956b83D8978603` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| Arbitrum | `0x23f0e8FAeE7bbb405E7A7C3d60138FCfd43d7509` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| Avalanche | `0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| Base | `0x98046Bd286715D3B0BC227Dd7a956b83D8978603` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| BNB Chain | `0x98046Bd286715D3B0BC227Dd7a956b83D8978603` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| Optimism | `0x98046Bd286715D3B0BC227Dd7a956b83D8978603` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | -| Polygon | `0x98046Bd286715D3B0BC227Dd7a956b83D8978603` | 100,000 | `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506` | + **The default provider for above mainnet chains is `0x52DeaA1c84233F7bb8C8A45baeDE41091c616506`.** @@ -30,18 +22,8 @@ The default provider fulfills the request by sending a transaction with a gas li The Entropy contract is deployed on the following testnet chains: -| Network | Contract Address | Gas Limit | Provider | -| ---------------- | -------------------------------------------- | --------- | -------------------------------------------- | -| Ethereum Sepolia | `0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| Arbitrum Sepolia | `0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| Avalanche Fuji | `0x36825bf3Fbdf5a29E2d5148bfe7Dcf7B5639e320` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| Base Sepolia | `0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| BNB Testnet | `0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| Optimism Sepolia | `0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | -| Polygon Amoy | `0x41c9e39574F40Ad34c79f1C99B66A45eFB830d4c` | 100,000 | `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344` | + **The default provider for above testnet chains is `0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344`.** The default provider on testnet has reveal delays identical to the corresponding mainnet chains to ensure consistent environment. - -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/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx b/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx index 5597cce6ba..97b0a8f2f6 100644 --- a/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx +++ b/apps/developer-hub/content/docs/entropy/debug-callback-failures.mdx @@ -2,43 +2,48 @@ title: Debug Callback Failures description: How to identify and resolve issues with Entropy callbacks --- -import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; + +import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"; This guide explains how to identify and resolve issues with the Entropy callback. The intended audience for this guide is developers who have made an Entropy random number request, but their application hasn't received a callback. > 🔍 **Quick Debug Tool** -> +> > Use the [Entropy Explorer](https://entropy-debugger.pyth.network/) to quickly diagnose and resolve callback issues. - ## Dependencies This guide uses [Foundry](https://book.getfoundry.sh/getting-started/installation) to submit transactions to the blockchain. Please install Foundry before continuing. + ## Run the Callback Developers can run the Entropy callback themselves to see the reason for the failure. To run the callback, invoke the `revealWithCallback` function on the Entropy contract on your blockchain. The function has the following signature: - +`} +/> This call requires the chain ID, contract address, and four other arguments. The chain ID and contract address can be retrieved from [Contract Addresses](contract-addresses). Export these values as environment variables for later use: - +`} +/> Three of the other arguments can be retrieved from the request transaction's event logs. Look at the event logs of the request transaction in a block explorer. @@ -46,11 +51,13 @@ You should see a `RequestedWithCallback` event emitted from the Entropy contract Copy the following values from the event into environment variables: - +`} +/> The fourth argument (provider contribution) must be retrieved from the provider's API. This value becomes available after the reveal delay has passed. @@ -78,4 +85,4 @@ Your callback function might contain logic that throws an error. Review your cal ### Transaction Timing Make sure you're attempting the callback after the reveal delay has passed. The reveal delay varies by network and helps prevent MEV attacks. -Refer to the [Contract Addresses](contract-addresses) page for the reveal delay for each network. \ No newline at end of file +Refer to the [Contract Addresses](contract-addresses) page for the reveal delay for each network. diff --git a/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx index 0e9bacb42d..a01e2fa0a6 100644 --- a/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx +++ b/apps/developer-hub/content/docs/entropy/generate-random-numbers-evm.mdx @@ -4,7 +4,7 @@ description: Learn how to integrate Pyth Entropy to generate random numbers in y --- import { Step, Steps } from "fumadocs-ui/components/steps"; -import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; +import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"; 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. @@ -26,9 +26,11 @@ npm install @pythnetwork/entropy-sdk-solidity Then add the following line to your `remappings.txt` file: - + @@ -49,11 +51,11 @@ import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; // @param entropyAddress The address of the entropy contract. contract YourContract is IEntropyConsumer { - IEntropyV2 public entropy; +IEntropyV2 public entropy; - constructor(address entropyAddress) { - entropy = IEntropyV2(entropyAddress); - } +constructor(address entropyAddress) { +entropy = IEntropyV2(entropyAddress); +} } `} /> @@ -78,7 +80,7 @@ These methods use the default randomness provider ([see here](#randomness-provid code={`function requestRandomNumber() external payable { uint256 fee = entropy.getFeeV2(); - uint64 sequenceNumber = entropy.requestV2{ value: fee }(); +uint64 sequenceNumber = entropy.requestV2{ value: fee }(); } `} /> @@ -100,43 +102,44 @@ import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyCons import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; contract YourContract is IEntropyConsumer { - IEntropyV2 entropy; +IEntropyV2 entropy; - // @param entropyAddress The address of the entropy contract. - constructor(address entropyAddress) { - entropy = IEntropyV2(entropyAddress); - } +// @param entropyAddress The address of the entropy contract. +constructor(address entropyAddress) { +entropy = IEntropyV2(entropyAddress); +} - function requestRandomNumber() external payable { - // Get the fee for the request - uint256 fee = entropy.getFeeV2(); +function requestRandomNumber() external payable { +// Get the fee for the request +uint256 fee = entropy.getFeeV2(); // Request the random number with the callback uint64 sequenceNumber = entropy.requestV2{ value: fee }(); // 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. - // This method **must** be implemented on the same contract that requested the random number. - // This method should **never** return an error -- if it returns an error, then the keeper will not be able to invoke the callback. - // If you are having problems receiving the callback, the most likely cause is that the callback is erroring. - // See the callback debugging guide here to identify the error https://docs.pyth.network/entropy/debug-callback-failures - 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); - } + +} + +// @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. +// This method **must** be implemented on the same contract that requested the random number. +// This method should **never** return an error -- if it returns an error, then the keeper will not be able to invoke the callback. +// If you are having problems receiving the callback, the most likely cause is that the callback is erroring. +// See the callback debugging guide here to identify the error https://docs.pyth.network/entropy/debug-callback-failures +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); +} } `} /> @@ -180,6 +183,8 @@ a keeper service for fullfilling requests. You can 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: - + diff --git a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx index 50ed58f6f4..358cfc0c68 100644 --- a/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx +++ b/apps/developer-hub/content/docs/entropy/set-custom-gas-limits.mdx @@ -4,7 +4,7 @@ description: How to set custom gas limits for Entropy callbacks --- import { Step, Steps } from "fumadocs-ui/components/steps"; -import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; +import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"; Custom gas limits are useful when your callback function requires more gas than the [default provider limit]TODO(../contract-addresses), or when you want to optimize gas costs for simpler callbacks. @@ -38,10 +38,10 @@ code={`function requestRandomNumberWithCustomGas( // Calculate the fee for the custom gas limit uint256 fee = entropy.getFeeV2(customGasLimit); - // Request random number with custom gas limit - uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); +// Request random number with custom gas limit +uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); - // Store the sequence number for tracking if needed +// Store the sequence number for tracking if needed } `} /> @@ -67,43 +67,45 @@ import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyCons import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol"; contract CustomGasLimitExample is IEntropyConsumer { - IEntropyV2 public entropy; - mapping(uint64 => bool) public processedRequests; +IEntropyV2 public entropy; +mapping(uint64 => bool) public processedRequests; - constructor(address entropyAddress) { - entropy = IEntropyV2(entropyAddress); - } +constructor(address entropyAddress) { +entropy = IEntropyV2(entropyAddress); +} - // Request with custom gas limit for complex callback - function requestComplexRandomNumber() external payable { - uint32 customGasLimit = 200000; // Higher limit for complex operations - uint256 fee = entropy.getFeeV2(customGasLimit); +// Request with custom gas limit for complex callback +function requestComplexRandomNumber() external payable { +uint32 customGasLimit = 200000; // Higher limit for complex operations +uint256 fee = entropy.getFeeV2(customGasLimit); require(msg.value >= fee, "Insufficient fee"); uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); // Store sequence number if needed for tracking - } - // Request with lower gas limit for simple callback - function requestSimpleRandomNumber() external payable { - uint32 customGasLimit = 50000; // Lower limit for simple operations - uint256 fee = entropy.getFeeV2(customGasLimit); +} + +// Request with lower gas limit for simple callback +function requestSimpleRandomNumber() external payable { +uint32 customGasLimit = 50000; // Lower limit for simple operations +uint256 fee = entropy.getFeeV2(customGasLimit); require(msg.value >= fee, "Insufficient fee"); uint64 sequenceNumber = entropy.requestV2{ value: fee }(customGasLimit); - } - - // Complex callback that requires more gas - function entropyCallback( - uint64 sequenceNumber, - address provider, - bytes32 randomNumber - ) internal override { - // Prevent duplicate processing - require(!processedRequests[sequenceNumber], "Already processed"); - processedRequests[sequenceNumber] = true; + +} + +// Complex callback that requires more gas +function entropyCallback( +uint64 sequenceNumber, +address provider, +bytes32 randomNumber +) internal override { +// Prevent duplicate processing +require(!processedRequests[sequenceNumber], "Already processed"); +processedRequests[sequenceNumber] = true; // Complex operations that require more gas for (uint i = 0; i < 10; i++) { @@ -114,11 +116,12 @@ contract CustomGasLimitExample is IEntropyConsumer { // Use the random number for your application logic uint256 randomValue = uint256(randomNumber); // Your application logic here... - } - function getEntropy() internal view override returns (address) { - return address(entropy); - } +} + +function getEntropy() internal view override returns (address) { +return address(entropy); +} } `} /> @@ -127,10 +130,10 @@ contract CustomGasLimitExample is IEntropyConsumer { When setting custom gas limits, be aware of these constraints: -Gas limits are automatically rounded up to the nearest multiple of **10,000**. -Example: 19,000 becomes 20,000 25,500 becomes 30,000. The minimum gas limit -is the provider's configured default limit. The maximum gas limit is -655,350,000 (`uint16.max` \* 10,000). + Gas limits are automatically rounded up to the nearest multiple of **10,000**. + Example: 19,000 becomes 20,000 25,500 becomes 30,000. The minimum gas limit is + the provider's configured default limit. The maximum gas limit is 655,350,000 + (`uint16.max` \* 10,000). ### Recommended Gas Limits @@ -146,44 +149,50 @@ is the provider's configured default limit. The maximum gas limit is Test your callback function to determine the actual gas usage: - +`} +/> ### 2. Add Safety Buffer Always add a safety buffer to your estimated gas usage: - +`} +/> ### 3. Handle Gas Limit Errors Be prepared to handle cases where your gas limit is insufficient: -If your callback **runs out of gas**, the entropy provider will **not** be able to -complete the callback. Always test your gas limits thoroughly and include -adequate safety margins. + If your callback **runs out of gas**, the entropy provider will **not** be + able to complete the callback. Always test your gas limits thoroughly and + include adequate safety margins. ### 4. Consider Fee Implications Higher gas limits result in higher fees. Balance your gas needs with cost considerations: - +`} +/> ## Troubleshooting diff --git a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx index 067063f52c..9fb63357e6 100644 --- a/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx +++ b/apps/developer-hub/content/docs/entropy/whats-new-entropyv2.mdx @@ -3,7 +3,8 @@ title: What's New in Entropy v2 description: New features and improvements in Entropy v2 icon: Sparkle --- -import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock'; + +import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"; ## Key Improvements diff --git a/apps/developer-hub/package.json b/apps/developer-hub/package.json index e7d14c824c..0e40d31587 100644 --- a/apps/developer-hub/package.json +++ b/apps/developer-hub/package.json @@ -33,6 +33,7 @@ "react": "catalog:", "react-aria": "catalog:", "react-dom": "catalog:", + "viem": "catalog:", "zod": "catalog:", "zod-validation-error": "catalog:" }, diff --git a/apps/developer-hub/src/app/(docs)/layout.tsx b/apps/developer-hub/src/app/(docs)/layout.tsx index c5319f0a4a..85917a2d94 100644 --- a/apps/developer-hub/src/app/(docs)/layout.tsx +++ b/apps/developer-hub/src/app/(docs)/layout.tsx @@ -4,9 +4,5 @@ import type { ReactNode } from "react"; import { docsOptions } from "../../config/layout.config"; export default function Layout({ children }: { children: ReactNode }) { - return ( - - {children} - - ); + return {children}; } diff --git a/apps/developer-hub/src/app/(homepage)/layout.tsx b/apps/developer-hub/src/app/(homepage)/layout.tsx index 46e9fad9dd..85274122b3 100644 --- a/apps/developer-hub/src/app/(homepage)/layout.tsx +++ b/apps/developer-hub/src/app/(homepage)/layout.tsx @@ -4,9 +4,5 @@ import type { ReactNode } from "react"; import { baseOptions } from "../../config/layout.config"; export default function Layout({ children }: { children: ReactNode }) { - return ( - - {children} - - ); + return {children}; } diff --git a/apps/developer-hub/src/components/CopyAddress/index.tsx b/apps/developer-hub/src/components/CopyAddress/index.tsx index 65f121b84f..36d13db062 100644 --- a/apps/developer-hub/src/components/CopyAddress/index.tsx +++ b/apps/developer-hub/src/components/CopyAddress/index.tsx @@ -3,21 +3,18 @@ import { CopyButton } from "@pythnetwork/component-library/CopyButton"; import { Link } from "@pythnetwork/component-library/Link"; -import TruncateToMiddle from "../TruncateToMiddle"; import styles from "./index.module.scss"; const CopyAddress = ({ address, url }: { address: string; url?: string }) => { return url ? (
- + {address}
) : ( - - - + {address} ); }; diff --git a/apps/developer-hub/src/components/EntropyTable/constants.ts b/apps/developer-hub/src/components/EntropyTable/constants.ts new file mode 100644 index 0000000000..922833267d --- /dev/null +++ b/apps/developer-hub/src/components/EntropyTable/constants.ts @@ -0,0 +1,4 @@ +export const FORTUNA_API_URLS = { + mainnet: "https://fortuna.dourolabs.app/v1/chains/configs", + testnet: "https://fortuna-staging.dourolabs.app/v1/chains/configs", +} as const; diff --git a/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx b/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx new file mode 100644 index 0000000000..2d7dbe54e2 --- /dev/null +++ b/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx @@ -0,0 +1,72 @@ +import * as chains from "viem/chains"; +import { z } from "zod"; + +import { EntropyDeploymentsConfig } from "./entropy-deployments-config"; + +const ApiChainConfigSchema = z.object({ + name: z.string(), + network_id: z.number(), + contract_addr: z.string(), + reveal_delay_blocks: z.number(), + gas_limit: z.number(), + default_fee: z.number(), +}); + +type ApiChainConfig = z.infer; + +const entropyDeploymentsSchema = z.array(ApiChainConfigSchema); + +export type EntropyDeployment = { + address: string; + delay: string; + gasLimit: string; + default_fee: number; + rpc?: string; + explorer?: string; + nativeCurrency?: string; +}; + +const getChainData = (network_id: number) => { + return Object.values(chains).find((chain) => chain.id === network_id); +}; + +const transformChainData = ( + chain: ApiChainConfig, +): [string, EntropyDeployment] => { + const viemChainData = getChainData(chain.network_id); + + const configOverride = EntropyDeploymentsConfig[chain.network_id]; + + const rpc = configOverride?.rpc ?? viemChainData?.rpcUrls.default.http[0]; + const explorer = + configOverride?.explorer ?? viemChainData?.blockExplorers?.default.url; + const nativeCurrency = + configOverride?.nativeCurrency ?? viemChainData?.nativeCurrency.symbol; + + const deployment: EntropyDeployment = { + address: chain.contract_addr, + delay: `${String(chain.reveal_delay_blocks)} block${ + chain.reveal_delay_blocks === 1 ? "" : "s" + }`, + gasLimit: String(chain.gas_limit), + default_fee: chain.default_fee, + ...(rpc ? { rpc } : {}), + ...(explorer ? { explorer } : {}), + ...(nativeCurrency ? { nativeCurrency } : {}), + }; + + return [chain.name, deployment]; +}; + +export const fetchEntropyDeployments = async ( + url: string, +): Promise> => { + try { + const response = await fetch(url); + const apiData = entropyDeploymentsSchema.parse(await response.json()); + + return Object.fromEntries(apiData.map((item) => transformChainData(item))); + } catch (error_) { + throw new Error(String(error_)); + } +}; diff --git a/apps/developer-hub/src/components/EntropyTable/entropy-deployments-config.ts b/apps/developer-hub/src/components/EntropyTable/entropy-deployments-config.ts new file mode 100644 index 0000000000..323d69c933 --- /dev/null +++ b/apps/developer-hub/src/components/EntropyTable/entropy-deployments-config.ts @@ -0,0 +1,25 @@ +export type ChainOverride = { + rpc?: string; + nativeCurrency?: string; + explorer?: string; +}; + +export const EntropyDeploymentsConfig: Record = { + // Example overrides - add your custom configurations here + // "network-id": { + // rpc: "https://custom-rpc-url.com", + // nativeCurrency: "CUSTOM" + // explorer: "https://custom-explorer.com" + // }, + + // Override examples (uncomment and modify as needed): + "998": { + rpc: "https://rpc.hyperliquid-testnet.xyz/evm", + nativeCurrency: "HYPE", + explorer: "https://testnet.purrsec.com/", + }, + "999": { + rpc: "https://rpc.hypurrscan.io", + nativeCurrency: "HYPE", + }, +}; diff --git a/apps/developer-hub/src/components/EntropyTable/index.tsx b/apps/developer-hub/src/components/EntropyTable/index.tsx new file mode 100644 index 0000000000..e6143ba5a9 --- /dev/null +++ b/apps/developer-hub/src/components/EntropyTable/index.tsx @@ -0,0 +1,125 @@ +"use client"; +import { InfoBox } from "@pythnetwork/component-library/InfoBox"; +import { Spinner } from "@pythnetwork/component-library/Spinner"; +import type { + ColumnConfig, + RowConfig, +} from "@pythnetwork/component-library/Table"; +import { Table } from "@pythnetwork/component-library/Table"; +import { useEffect, useRef, useState } from "react"; + +import { FORTUNA_API_URLS } from "./constants"; +import type { EntropyDeployment } from "./entropy-api-data-fetcher"; +import { fetchEntropyDeployments } from "./entropy-api-data-fetcher"; +import CopyAddress from "../CopyAddress"; + +export const EntropyTable = ({ isMainnet }: { isMainnet: boolean }) => { + const isLoading = useRef(false); + const [state, setState] = useState(State.NotLoaded()); + + useEffect(() => { + if (!isLoading.current) { + setState(State.Loading()); + isLoading.current = true; + getEntropyDeployments(isMainnet) + .then((chains) => { + setState(State.Loaded(chains)); + }) + .catch((error: unknown) => { + setState(State.Failed(error)); + }); + } + }, [isMainnet]); + + switch (state.type) { + case StateType.Loading: + case StateType.NotLoaded: { + return ; + } + case StateType.Error: { + return ( + +

Failed to fetch the list of entropy contracts.

+
+ ); + } + case StateType.Loaded: { + return ; + } + default: { + throw new Error(`Unknown state type: ${typeof state}`); + } + } +}; + +type Col = "chain" | "address" | "delay" | "gasLimit"; + +const EntropyTableContent = ({ + chains, +}: { + chains: Record; +}) => { + const columns: ColumnConfig[] = [ + { id: "chain", name: "Chain", isRowHeader: true }, + { id: "address", name: "Contract" }, + { id: "delay", name: "Reveal Delay" }, + { id: "gasLimit", name: "Default Gas Limit" }, + ]; + + const rows: RowConfig[] = Object.entries(chains).map( + ([chainName, d]) => ({ + id: chainName, + data: { + chain: chainName, + address: d.explorer ? ( + + ) : ( + + ), + delay: d.delay, + gasLimit: d.gasLimit, + }, + }), + ); + + return ( + + label="Entropy deployments" + columns={columns} + rows={rows} + isLoading={false} + rounded + fill + stickyHeader="top" + /> + ); +}; + +enum StateType { + NotLoaded, + Loading, + Loaded, + Error, +} + +const State = { + NotLoaded: () => ({ type: StateType.NotLoaded as const }), + Loading: () => ({ type: StateType.Loading as const }), + Loaded: (chains: Awaited>) => ({ + type: StateType.Loaded as const, + chains, + }), + Failed: (error: unknown) => ({ type: StateType.Error as const, error }), +}; + +type State = ReturnType<(typeof State)[keyof typeof State]>; + +const getEntropyDeployments = async ( + isMainnet: boolean, +): Promise> => { + const url = isMainnet ? FORTUNA_API_URLS.mainnet : FORTUNA_API_URLS.testnet; + return await fetchEntropyDeployments(url); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d51fb26dcf..934428f0f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -548,6 +548,9 @@ importers: react-dom: specifier: 'catalog:' version: 19.1.0(react@19.1.0) + viem: + specifier: 'catalog:' + version: 2.34.0(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@6.0.3)(zod@3.24.4) zod: specifier: 'catalog:' version: 3.24.4 From 2eb1ee80bb445900d6eda5d9f10e17e3fd8bc5e5 Mon Sep 17 00:00:00 2001 From: Aditya Arora Date: Mon, 8 Sep 2025 10:18:01 -0400 Subject: [PATCH 4/4] chore(dev-docs): update entropy edits-2 --- .../EntropyTable/entropy-api-data-fetcher.tsx | 35 +++++++------------ .../src/components/EntropyTable/index.tsx | 3 -- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx b/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx index 2d7dbe54e2..33c4ac7897 100644 --- a/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx +++ b/apps/developer-hub/src/components/EntropyTable/entropy-api-data-fetcher.tsx @@ -12,10 +12,6 @@ const ApiChainConfigSchema = z.object({ default_fee: z.number(), }); -type ApiChainConfig = z.infer; - -const entropyDeploymentsSchema = z.array(ApiChainConfigSchema); - export type EntropyDeployment = { address: string; delay: string; @@ -26,13 +22,11 @@ export type EntropyDeployment = { nativeCurrency?: string; }; -const getChainData = (network_id: number) => { +function getChainData(network_id: number) { return Object.values(chains).find((chain) => chain.id === network_id); -}; +} -const transformChainData = ( - chain: ApiChainConfig, -): [string, EntropyDeployment] => { +const apiChainConfigToEntrySchema = ApiChainConfigSchema.transform((chain) => { const viemChainData = getChainData(chain.network_id); const configOverride = EntropyDeploymentsConfig[chain.network_id]; @@ -55,18 +49,15 @@ const transformChainData = ( ...(nativeCurrency ? { nativeCurrency } : {}), }; - return [chain.name, deployment]; -}; + return [chain.name, deployment] as const; +}); -export const fetchEntropyDeployments = async ( - url: string, -): Promise> => { - try { - const response = await fetch(url); - const apiData = entropyDeploymentsSchema.parse(await response.json()); +const entropyDeploymentsSchema = z.array(apiChainConfigToEntrySchema); - return Object.fromEntries(apiData.map((item) => transformChainData(item))); - } catch (error_) { - throw new Error(String(error_)); - } -}; +export async function fetchEntropyDeployments( + url: string, +): Promise> { + const response = await fetch(url); + const entries = entropyDeploymentsSchema.parse(await response.json()); + return Object.fromEntries(entries); +} diff --git a/apps/developer-hub/src/components/EntropyTable/index.tsx b/apps/developer-hub/src/components/EntropyTable/index.tsx index e6143ba5a9..5c0f2076cf 100644 --- a/apps/developer-hub/src/components/EntropyTable/index.tsx +++ b/apps/developer-hub/src/components/EntropyTable/index.tsx @@ -46,9 +46,6 @@ export const EntropyTable = ({ isMainnet }: { isMainnet: boolean }) => { case StateType.Loaded: { return ; } - default: { - throw new Error(`Unknown state type: ${typeof state}`); - } } };