Skip to content
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

Fix Randomness Precompile Gas #701

Merged
merged 6 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .snippets/code/randomness/Lottery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ contract Lottery is RandomnessConsumer {
// there will be enough fee to pay for the gas used by the fulfillment.
// Ideally it should be over-estimated considering possible fluctuation of
// the gas price. Additional fee will be refunded to the caller
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 1 gwei;
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 150 gwei;

// A string used to allow having different salt than other contracts
bytes32 public SALT_PREFIX = "my_demo_salt_change_me";
bytes32 public SALT_PREFIX = "INSERT_ANY_STRING_FOR_SALT";

// Stores the global number of requests submitted. This number is used as a
// salt to make each request unique
Expand Down
59 changes: 59 additions & 0 deletions .snippets/code/randomness/RandomNumber.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.0;

import "https://github.com/PureStake/moonbeam/blob/master/precompiles/randomness/Randomness.sol";
import {RandomnessConsumer} from "https://github.com/PureStake/moonbeam/blob/master/precompiles/randomness/RandomnessConsumer.sol";

contract RandomNumber is RandomnessConsumer {
// The Randomness Precompile Interface
Randomness public randomness =
Randomness(0x0000000000000000000000000000000000000809);

// Variables required for randomness requests
uint256 public requiredDeposit = randomness.requiredDeposit();
uint64 public FULFILLMENT_GAS_LIMIT = 100000;
// The fee can be set to any value as long as it is enough to cover
// the fulfillment costs. Any leftover fees will be refunded to the
// refund address specified in the requestRandomness function below.
// 150 Gwei should be sufficient for all networks.
// For Moonbase Alpha and Moonriver, you can specify 5 Gwei
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 150 gwei;
uint32 public VRF_BLOCKS_DELAY = MIN_VRF_BLOCKS_DELAY;
bytes32 public SALT_PREFIX = "INSERT_ANY_STRING_FOR_SALT";

// Storage variables for the current request
uint256 public requestId;
uint256[] public random;

constructor() payable RandomnessConsumer() {
// Because this contract can only perform 1 random request at a time,
// We only need to have 1 required deposit
require(msg.value >= requiredDeposit);
}

function requestRandomness() public payable {
// Make sure that the value sent is enough
require(msg.value >= MIN_FEE);
// Request local VRF randomness
requestId = randomness.requestLocalVRFRandomWords(
msg.sender, // Refund address
msg.value, // Fulfillment fee
FULFILLMENT_GAS_LIMIT, // Gas limit for the fulfillment
SALT_PREFIX ^ bytes32(requestId++), // A salt to generate unique results
1, // Number of random words
VRF_BLOCKS_DELAY // Delay before request can be fulfilled
);
}

function fulfillRequest() public {
randomness.fulfillRequest(requestId);
}

function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
// Save the randomness results
random = randomWords;
}
}
62 changes: 3 additions & 59 deletions builders/pallets-precompiles/precompiles/randomness.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ keywords: solidity, ethereum, randomness, VRF, moonbeam, precompiled, contracts

![Randomness Moonbeam Banner](/images/builders/pallets-precompiles/precompiles/randomness/randomness-banner.png)

## Introduction {: #introduction }
## Introduction {: #introduction }

Moonbeam utilizes verifiable random functions (VRF) to generate randomness that can be verified on-chain. A VRF is a cryptographic function that takes some input and produces random values, along with a proof of authenticity that these random values were generated by the submitter. The proof can be verified by anyone to ensure the random values generated were calculated correctly.

Expand Down Expand Up @@ -180,63 +180,7 @@ The contract will include the following functions:
Without further ado, the contract is as follows:

```sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.0;

import "https://github.com/PureStake/moonbeam/blob/master/precompiles/randomness/Randomness.sol";
import {RandomnessConsumer} from "https://github.com/PureStake/moonbeam/blob/master/precompiles/randomness/RandomnessConsumer.sol";

contract RandomNumber is RandomnessConsumer {
// The Randomness Precompile Interface
Randomness public randomness =
Randomness(0x0000000000000000000000000000000000000809);

// Variables required for randomness requests
uint256 public requiredDeposit = randomness.requiredDeposit();
uint64 public FULFILLMENT_GAS_LIMIT = 100000;
// The fee can be set to any value as long as it is enough to cover
// the fulfillment costs. Any leftover fees will be refunded to the
// refund address specified in the requestRandomness function below
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 5 gwei;
uint32 public VRF_BLOCKS_DELAY = MIN_VRF_BLOCKS_DELAY;
bytes32 public SALT_PREFIX = "change-me-to-anything";

// Storage variables for the current request
uint256 public requestId;
uint256[] public random;

constructor() payable RandomnessConsumer() {
// Because this contract can only perform 1 random request at a time,
// We only need to have 1 required deposit.
require(msg.value >= requiredDeposit);
}

function requestRandomness() public payable {
// Make sure that the value sent is enough
require(msg.value >= MIN_FEE);
// Request local VRF randomness
requestId = randomness.requestLocalVRFRandomWords(
msg.sender, // Refund address
msg.value, // Fulfillment fee
FULFILLMENT_GAS_LIMIT, // Gas limit for the fulfillment
SALT_PREFIX ^ bytes32(requestId++), // A salt to generate unique results
1, // Number of random words
VRF_BLOCKS_DELAY // Delay before request can be fulfilled
);
}

function fulfillRequest() public {
randomness.fulfillRequest(requestId);
}

function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
// Save the randomness results
random = randomWords;
}
}
--8<-- 'code/randomness/RandomNumber.sol'
```

As you can see, there are also some constants in the contract that can be edited as you see fit, especially the `SALT_PREFIX` which can be used to produce unique results.
Expand Down Expand Up @@ -287,7 +231,7 @@ The **RANDOMNUMBER** contract will appear in the list of **Deployed Contracts**.

To request randomness, you're going to use the `requestRandomness` function of the contract, which will require you to submit a deposit as defined in the Randomness Precompile. You can submit the randomness request and pay the deposit by taking these steps:

1. Enter an amount in the **VALUE** field for the fulfillment fee, it must be equal to or greater than the minimum fee specified in the `RandomNumber` contract, which is `500000` Gwei
1. Enter an amount in the **VALUE** field for the fulfillment fee, it must be equal to or greater than the minimum fee specified in the `RandomNumber` contract, which is `15000000` Gwei.
2. Expand the **RANDOMNUMBER** contract
3. Click on the **requestRandomness** button
4. Confrm the transaction in MetaMask
Expand Down
9 changes: 4 additions & 5 deletions tutorials/eth-api/randomness-lottery.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ description: Looking to create a lottery smart contract? Follow this step-by-ste

![Randomness Moonbeam Banner](/images/builders/pallets-precompiles/precompiles/randomness/randomness-banner.png)

_March 15, 2023 | by Erin Shaben_
_By Erin Shaben_

## Introduction {: #introduction }
## Introduction {: #introduction }

Moonbeam utilizes verifiable random functions (VRF) to generate randomness that can be verified on-chain. A VRF is a cryptographic function that takes some input and produces random values, along with a proof of authenticity that these random values were generated by the submitter. The proof can be verified by anyone to ensure the random values generated were calculated correctly.

Expand Down Expand Up @@ -133,7 +133,7 @@ We will also need to define some parameters specifically related to requesting r
- The minimum fee needed to start the lottery and request the random words. Each request for randomness requires a fulfillment fee. The purpose of this fee is to pay for the fulfillment of a randomness request, which allows anyone to fulfill a request since the request will already have been paid for. When submitting a randomness request, a refund account can be specified, where any excess fees will be returned to. Our contract will be set up so that the owner of the lottery contract will receive the refund
- A salt prefix and the global request count, both of which will be used to generate unique randomness requests

You can go ahead and add these parameters:
You can go ahead and add these parameters:

```
// The gas limit allowed to be used for the fulfillment, which depends on the
Expand All @@ -146,7 +146,7 @@ uint64 public FULFILLMENT_GAS_LIMIT = 100000;
// there will be enough fee to pay for the gas used by the fulfillment.
// Ideally it should be over-estimated considering possible fluctuation of
// the gas price. Additional fee will be refunded to the caller
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 1 gwei;
uint256 public MIN_FEE = FULFILLMENT_GAS_LIMIT * 150 gwei;

// A string used to allow having different salt than other contracts
bytes32 public SALT_PREFIX = "my_demo_salt_change_me";
Expand Down Expand Up @@ -331,7 +331,6 @@ For fulfilled requests, the cost of execution will be refunded from the request

Our `fulfillRandomWords` function defines a callback, the `pickWinners` function, that is responsible for handling the fulfillment. So, in our case, the callback will use the random words to select a winner and payout the winnings. The signature of our `fulfillRandomWords` function must match the signature of the Randomness Consumer's `fulfillRandomWords` function.


```
function fulfillRequest() public {
randomness.fulfillRequest(requestId);
Expand Down
Loading