-
Notifications
You must be signed in to change notification settings - Fork 300
Chore(dev hub) entropy improvements #3031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
89ca550
48cc851
c0241af
a21a0a8
2a1da2c
cea3cea
3ba24c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,17 @@ | ||
--- | ||
title: Best Practices | ||
description: Best practices for using Pyth Entropy in your applications | ||
icon: Book | ||
--- | ||
|
||
# Best Practices | ||
|
||
## Limit gas usage on the callback | ||
|
||
Keeping the callback function simple is crucial because the entropy providers limit gas usage. | ||
This ensures gas usage is predictable and consistent, avoiding potential issues with the callback. | ||
|
||
For example, if you want to use entropy to generate a random number for each player in a round of game, | ||
you need to make sure that the callback function works for the maximum number of players that can be in each round. | ||
Otherwise, the callbacks will work for some rounds with fewer players, but will fail for rounds with more players. | ||
|
||
Multiple solutions are possible to address this problem. You can store the random number received from the callback and | ||
either ask users to submit more transactions after the callback to continue the flow or run a background crank service | ||
to submit the necessary transactions. | ||
|
||
The gas limit for each chain is listed on the [contract addresses](contract-addresses) page. | ||
|
||
## Handling callback failures | ||
|
||
While the default entropy provider is highly reliable, in rare cases a callback might not be received. This typically happens when there's an issue with your contract's callback implementation rather than with the provider itself. The most common causes are: | ||
|
||
1. The callback function is using more gas than the allowed limit | ||
2. The callback function contains logic that throws an error | ||
|
||
If you're not receiving a callback, you can manually invoke it to identify the specific issue. This allows you to: | ||
|
||
- See if the transaction fails and why | ||
- Check the gas usage against the chain's callback gas limit | ||
- Debug your callback implementation | ||
|
||
For detailed instructions on how to manually invoke and debug callbacks, refer to the [Debug Callback Failures](debug-callback-failures) guide. | ||
import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock"; | ||
|
||
## Generating random values within a specific range | ||
|
||
You can map the random number provided by Entropy into a smaller range using the solidity [modulo operator](https://docs.soliditylang.org/en/latest/types.html#modulo). | ||
Here is a simple example of how to map a random number provided by Entropy into a range between `minRange` and `maxRange` (inclusive). | ||
|
||
```solidity | ||
<DynamicCodeBlock lang="solidity" code={`\ | ||
// Maps a random number into a range between minRange and maxRange (inclusive) | ||
function mapRandomNumber( | ||
bytes32 randomNumber, | ||
|
@@ -53,5 +24,55 @@ function mapRandomNumber( | |
uint256 randomUint = uint256(randomNumber); | ||
|
||
return minRange + int256(randomUint % range); | ||
|
||
} | ||
`} /> | ||
|
||
Notice that using the modulo operator can distort the distribution of random numbers if it's not a power of 2. This is | ||
negligible for small and medium ranges, but it can be noticeable for large ranges. | ||
For example, if you want to generate a random number between 1 and 52, the probability of having value 5 is approximately | ||
`10^-77` higher than the probability of having value 50 which is infinitesimal. | ||
|
||
## Generating multiple random values in a single transaction | ||
|
||
If you need to generate multiple random values in a single transaction, you can hash the random input provided by Entropy with a unique identifier for each random number. | ||
|
||
In the following example, `mapRandomNumber` is used to generate 6 random attributes for a character. | ||
|
||
<DynamicCodeBlock | ||
lang="solidity" | ||
code={`\ | ||
function generateAttributes(bytes32 randomNumber) internal { | ||
int256 strength = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "strength")), | ||
15, | ||
20 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. feel free to ignore but I'm curious if this would work with just doing the triple quotes like ```solidity .... Feels a bit cumbersome to have to use <DynamicCodeBlock .../> every time we write code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the same thing that we were discussing yesterday @aditya520 as in don't see any difference in the look and feel of these two methods. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This component support shiki styles. I want to experiment with them in future. |
||
); | ||
int256 stamina = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "stamina")), | ||
10, | ||
15 | ||
); | ||
int256 agility = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "agility")), | ||
5, | ||
15 | ||
); | ||
int256 stealth = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "stealth")), | ||
0, | ||
5 | ||
); | ||
int256 positionX = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "positionX")), | ||
-100, | ||
100 | ||
); | ||
int256 positionY = mapRandomNumber( | ||
keccak256(abi.encodePacked(randomNumber, "positionY")), | ||
-100, | ||
100 | ||
); | ||
} | ||
``` | ||
`} | ||
/> |
Uh oh!
There was an error while loading. Please reload this page.