diff --git a/images/entropy-1.png b/images/entropy-1.png
deleted file mode 100644
index 2227f9ff..00000000
Binary files a/images/entropy-1.png and /dev/null differ
diff --git a/images/entropy-2.png b/images/entropy-2.png
deleted file mode 100644
index 7b99a1ef..00000000
Binary files a/images/entropy-2.png and /dev/null differ
diff --git a/pages/entropy/create-your-first-entropy-app.mdx b/pages/entropy/create-your-first-entropy-app.mdx
index 143245c7..03163931 100644
--- a/pages/entropy/create-your-first-entropy-app.mdx
+++ b/pages/entropy/create-your-first-entropy-app.mdx
@@ -40,7 +40,7 @@ Create a new file `CoinFlip.sol` in `contracts/src` directory and add the follow
```solidity copy
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
-import "@pythnetwork/entropy-sdk-solidity/IEntropy.sol";
+import "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol";
import "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
contract CoinFlip is IEntropyConsumer {
@@ -48,11 +48,9 @@ contract CoinFlip is IEntropyConsumer {
event FlipResult(uint64 sequenceNumber, bool isHeads);
IEntropy entropy;
- address provider;
- constructor(address _entropy, address _provider) {
+ constructor(address _entropy) {
entropy = IEntropy(_entropy);
- provider = _provider;
}
// This method is required by the IEntropyConsumer interface
@@ -63,7 +61,7 @@ contract CoinFlip is IEntropyConsumer {
```
-The code implements a`CoinFlip` contract which inherits the `IEntropyConsumer` interface. We have also defined some events, properties and a constructor to instantiate the contract. One of the properties is of type `IEntropy` which is an interface imported from the Entropy SDK. The constructor also takes a `provider` argument. We will see how to populate these later.
+The code implements a`CoinFlip` contract which inherits the `IEntropyConsumer` interface. We have also defined some events, properties and a constructor to instantiate the contract. One of the properties is of type `IEntropy` which is an interface imported from the Entropy SDK.
### Request a coin flip
@@ -73,17 +71,14 @@ Copy the following code into `CoinFlip.sol`.
contract CoinFlip {
// ... prior code omitted
- function request(bytes32 userRandomNumber) external payable {
+ function request() external payable {
// get the required fee
- uint128 requestFee = entropy.getFee(provider);
+ uint128 requestFee = entropy.getFeeV2();
// check if the user has sent enough fees
if (msg.value < requestFee) revert("not enough fees");
// pay the fees and request a random number from entropy
- uint64 sequenceNumber = entropy.requestWithCallback{ value: requestFee }(
- provider,
- userRandomNumber
- );
+ uint64 sequenceNumber = entropy.requestV2{ value: requestFee }();
// emit event
emit FlipRequested(sequenceNumber);
@@ -92,7 +87,7 @@ contract CoinFlip {
```
-Users will invoke the `request` method to initiate a coin flip with a request fee and passes in a `userRandomNumber` argument — we’ll see how to generate this later. The method first retrieves the fee required to request a random number from Entropy. It then include the fee in the `requestWithCallback` method call to entropy. Finally, the method emits a `FlipRequested` event with a `sequenceNumber`. This event is also defined in the code snippet above.
+Users will invoke the `request` method to initiate a coin flip, paying a fee in the process. The method first retrieves the fee required to request a random number from Entropy. It then includes the fee in the `requestV2` method call to Entropy. Finally, the method emits a `FlipRequested` event with a `sequenceNumber`. This event is also defined in the code snippet above.
### Handle the callback
@@ -119,7 +114,7 @@ contract CoinFlip {
```
Implement `entropyCallback` method which is required by the `IEntropyConsumer` Interface. Entropy calls back this method to fulfill a request. Entropy will call back this
-method with the `sequenceNumber` of the request, the `providerAddress` from which the random number was requested and the generated `randomNumber`.
+method with the `sequenceNumber` of the request, the `_providerAddress` from which the random number was requested and the generated `randomNumber`.
Finally, the method emits a `FlipResult` event with the result of the flip.
Yay! you have successfully implemented a coin flip contract.
@@ -158,7 +153,6 @@ The final step before deploying is to get the arguments for the contract's const
```bash copy
export ENTROPY_ADDRESS=0x4821932D0CDd71225A6d914706A621e0389D7061
-export PROVIDER_ADDRESS=0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344
```
Finally, let's deploy the contracts. Run the following command:
@@ -167,7 +161,7 @@ Finally, let's deploy the contracts. Run the following command:
forge create src/CoinFlip.sol:CoinFlip \
--private-key $PRIVATE_KEY \
--rpc-url $RPC_URL \
---constructor-args $ENTROPY_ADDRESS $PROVIDER_ADDRESS
+--constructor-args $ENTROPY_ADDRESS
```
You should see an output similar to:
@@ -206,7 +200,7 @@ Create a `script.js` file in `app` and add the following code to the script.
```javascript copy
const { Web3 } = require("web3");
const CoinFlipAbi = require("../contracts/out/CoinFlip.sol/CoinFlip.json");
-const EntropyAbi = require("@pythnetwork/entropy-sdk-solidity/abis/IEntropy.json");
+const EntropyAbi = require("@pythnetwork/entropy-sdk-solidity/abis/IEntropyV2.json");
async function main() {
const web3 = new Web3(process.env["RPC_URL"]);
@@ -240,14 +234,11 @@ async main() {
// Request a random number
- // Generate user random number
- const userRandomNumber = web3.utils.randomHex(32);
-
- const fee = await entropyContract.methods.getFee(process.env["PROVIDER_ADDRESS"]).call()
+ const fee = await entropyContract.methods.getFeeV2().call()
console.log(`fee : ${fee}`);
const requestReceipt = await coinFlipContract.methods
- .request(userRandomNumber)
+ .request()
.send({
value: fee,
from: address,
diff --git a/pages/entropy/current-fees.mdx b/pages/entropy/current-fees.mdx
index 2dbc66af..7f8377c8 100644
--- a/pages/entropy/current-fees.mdx
+++ b/pages/entropy/current-fees.mdx
@@ -8,7 +8,7 @@ Note that the fees shown below will vary over time with prevailing gas prices on
## Mainnet
- The fees for mainnet are dynamically set. Always use the onchain method `entropy.getFee(entropyProvider){:solidity}` to get the current fee.
+ The fees for mainnet are dynamically set. Always use the on-chain method `entropy.getFee(entropyProvider){:solidity}` to get the current fee.
**Quick Debug Tool**: Use the [Entropy
Debugger](https://entropy-debugger.pyth.network/) to quickly diagnose and
diff --git a/pages/entropy/generate-random-numbers/evm.mdx b/pages/entropy/generate-random-numbers/evm.mdx
index a6ec0808..b834157a 100644
--- a/pages/entropy/generate-random-numbers/evm.mdx
+++ b/pages/entropy/generate-random-numbers/evm.mdx
@@ -36,114 +36,77 @@ Then add the following line to your `remappings.txt` :
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.
-- [`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.
+- [`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 `IEntropy` contract in your solidity contract:
+ Once you have a contract address, instantiate an `IEntropyV2` 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";
+import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol";
// @param entropyAddress The address of the entropy contract.
contract YourContract is IEntropyConsumer {
- IEntropy public entropy;
+ IEntropyV2 public entropy;
constructor(address entropyAddress) {
- entropy = IEntropy(entropyAddress);
+ entropy = IEntropyV2(entropyAddress);
}
}
```
-
-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](../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`](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();
-```
-
## Usage
To generate a random number, follow these steps.
-### 1. Generate a random number
-
-Generate a 32-byte random number on the client side.
+### 1. Request a number from Entropy
-
-
- ```javascript
- const userRandomNumber = web3.utils.randomHex(32);
- ```
-
-
-
- ```javascript
- const userRandomNumber = ethers.utils.randomBytes(32);
- ```
-
-
+# TODO: fix links and events
-### 2. 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` contract.
+The `requestV2` method requires paying a fee in native gas tokens which is configured per-provider.
-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.
-
-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:
+The fees 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` call:
```solidity copy
-function requestRandomNumber(bytes32 userRandomNumber) external payable {
- uint256 fee = entropy.getFee(entropyProvider);
+function requestRandomNumber() external payable {
+ uint256 fee = entropy.getFeeV2();
- uint64 sequenceNumber = entropy.requestWithCallback{ value: fee }(
- entropyProvider,
- userRandomNumber
- );
+ uint64 sequenceNumber = entropy.requestV2{ value: fee }();
}
```
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
+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.
+Please see the method documentation in the IEntropyV2 interface. TODO: link
+
+### 2. Implement the Entropy callback
```solidity {28-42} copy
pragma solidity ^0.8.0;
import { IEntropyConsumer } from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
-import { IEntropy } from "@pythnetwork/entropy-sdk-solidity/IEntropy.sol";
+import { IEntropyV2 } from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol";
contract YourContract is IEntropyConsumer {
- IEntropy entropy;
+ IEntropyV2 entropy;
// @param entropyAddress The address of the entropy contract.
constructor(address entropyAddress) {
- entropy = IEntropy(entropyAddress);
+ entropy = IEntropyV2(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);
+ function requestRandomNumber() external payable {
+ // Get the fee for the request
+ uint256 fee = entropy.getFeeV2();
// Request the random number with the callback
- uint64 sequenceNumber = entropy.requestWithCallback{ value: fee }(
- entropyProvider,
- userRandomNumber
- );
+ uint64 sequenceNumber = entropy.requestV2{ value: fee }();
// Store the sequence number to identify the callback request
}
@@ -154,6 +117,7 @@ contract YourContract is IEntropyConsumer {
// 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.
+ // TODO: point to debugger
// See the callback debugging guide here to identify the error https://docs.pyth.network/entropy/debug-callback-failures
function entropyCallback(
uint64 sequenceNumber,
@@ -200,3 +164,20 @@ Check the [Current Fees](../current-fees) to find the current fee for each provi
### 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.
+
+
+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](../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`](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/pages/entropy/protocol-design.mdx b/pages/entropy/protocol-design.mdx
index b8f52a19..98aa3b82 100644
--- a/pages/entropy/protocol-design.mdx
+++ b/pages/entropy/protocol-design.mdx
@@ -1,21 +1,20 @@
# Protocol Design
-The Entropy protocol is an extension of a classical commit/reveal protocol.
-The original version has the following steps:
+The Entropy protocol implements a secure 2-party random number generation procedure. The protocol
+is an extension of a simple commit/reveal protocol. The original version has the following steps:
-1. Two parties A and B each draw secret random numbers, $x_A$ and $x_B$.
-2. A and B hash their random numbers and share the hashes, $h_A = \mathrm{hash}(x_A)$ and $h_B = \mathrm{hash}(x_B)$
-3. A and B reveal $x_A$ and $x_B$
-4. Both parties verify that $\mathrm{hash}(x_A) = h_A$ and $\mathrm{hash}(x_B) = h_B$
-5. The random number $r = \mathrm{hash}(x_A, x_B)$
+1. Two parties A and B each randomly sample secret contributions to the random number, $x_A$ and $x_B$.
+2. A commits to their number by sharing $h_A = \mathrm{hash}(x_A)$
+3. B reveals $x_B$
+4. A reveals $x_A$
+5. B verifies that $\mathrm{hash}(x_{A}) == h_A$
+6. The random number $r = \mathrm{hash}(x_A, x_B)$
This protocol has the property that the result is random as long as either A or B are honest.
-Thus, neither party needs to trust the other -- as long as they are themselves honest, they can
+Honesty means that (1) they draw their value at random, and (2) for A, they keep $x_A$ a secret until
+step 4. Thus, neither party needs to trust the other -- as long as they are themselves honest, they can
ensure that the result $r$ is random.
-The diagram below shows the protocol flow:
-
-
Entropy implements a version of this protocol that is optimized for on-chain usage. The
key difference is that one of the participants (the provider) commits to a sequence of random numbers
up-front using a hash chain. Users of the protocol then simply grab the next random number in the sequence.
@@ -28,28 +27,23 @@ up-front using a hash chain. Users of the protocol then simply grab the next ran
The provider commits to $x_0$ by posting it to the Entropy contract.
Each random number in the sequence can then be verified against the previous one in the sequence by hashing it, i.e., $\mathrm{hash}(x_i) = x_{i - 1}$
-Pyth Entropy uses automatic callbacks to simplify the flow:
-
-- **Request**: To produce a random number, the following steps occur.
-
-1. The user U draws a random number $x_U$, and submits it to the contract. The contract generates the hash $h_U = \mathrm{hash}(x_U)$ and records both $x_U$ and $h_U$. The contract uses [`constructUserCommitment`](https://github.com/pyth-network/pyth-crosschain/blob/7bccde484f01c19844b7105d63df207a24018957/target_chains/ethereum/contracts/contracts/entropy/Entropy.sol#L628-L632) to generate the user's commitment.
-2. The contract [remembers $h_U$ and assigns it an incrementing **sequence number $i$**](https://github.com/pyth-network/pyth-crosschain/blob/7bccde484f01c19844b7105d63df207a24018957/target_chains/ethereum/contracts/contracts/entropy/Entropy.sol#L232-L246), representing which
- of the provider's random numbers the user will receive. $x_U$ is recorded in the [event logs](https://github.com/pyth-network/pyth-crosschain/blob/7bccde484f01c19844b7105d63df207a24018957/target_chains/ethereum/contracts/contracts/entropy/Entropy.sol#L300-L306).
-3. After sufficient block confirmations, the provider submits a reveal transaction with $x_i$ and $x_U$ to the contract.
-4. The contract verifies $\mathrm{hash}(x_U) = h_U$ and $\mathrm{hash}(x_i) = x_{i-1}$ to prove that $x_i$ is the $i$'th random number.
-5. If both of the above conditions are satisfied,
- the random number $r = \mathrm{hash}(x_i, x_U)$ is generated and a callback is made to the requesting contract.
-
-In this flow, providers can refuse revealing $x_i$ if the final random number $r$ is not in their favor, or
-they may be able to access $x_U$ before on-chain submission (e.g. via mempool) and rotate their commitments to influence the random number $r$.
-Of course, both of these behaviors are detectable and protocols can blacklist providers that exhibit them.
+**Request**: To produce a random number, the following steps occur.
-This protocol has the same security properties as the 2-party randomness protocol above: as long as either
-the provider or user is honest, the number $r$ is random.
+1. The user randomly samples their contribution $x_U$ and submits it to the contract.
+ (Users may also run this step using an on-chain PRNG if they trust the validator to not collude with the provider.)
+2. The contract remembers $x_U$ and assigns it an incrementing sequence number $i$, representing which
+ of the provider's random numbers the user will receive.
+3. After sufficient block confirmations, the provider submits a transaction to the contract revealing their contribution $x_i$ to the contract.
+4. The contract verifies $\mathrm{hash}(x_i) == x_{i-1}$ to prove that $x_i$ is the $i$'th random number.
+ The contract stores x_i as the i'th random number to reuse for future verifications.
+5. If the condition above is satisfied, the random number $r = \mathrm{hash}(x_i, x_U)$.
+6. The contract submits a callback to the calling contract with the random number $r$.
-The diagram below shows the user's interaction with the entropy contract to generate a random number:
-
+This flow is secure as long as several trust assumptions hold:
-Note that providers need to be careful to ensure their off-chain service isn't compromised to reveal the random numbers -- if this occurs, then users will be able to influence the random number $r$.
+- Providers are trusted to reveal their random number $x_i$ regardless of what the final result $r$ is. Providers can compute $r$ off-chain before they reveal $x_i$, which permits a censorship attack.
+- Providers are trusted not to front-run user transactions (via the mempool or colluding with the validator). Providers who observe user transactions can manipulate the result by inserting additional reuests or rotating their commitment.
+- Providers are trusted not to keep their hash chain a secret. Anyone with the hash chain can predict the result of a randomness request before it is requested,
+ and therefore manipulate the result. This applies both to users of the protocol as well as blockchain validators who can use this information to manipulate the on-chain PRNG or reorder user transactions.
The code of default deployed provider can be found [here](https://github.com/pyth-network/pyth-crosschain/tree/7bccde484f01c19844b7105d63df207a24018957/apps/fortuna).