This repository is a part of the On-chain Distributed Random Beacon (DRB) project. We're currently using Pietrzak VDF verifier for EVM. The related technical details are presented in our preprint (Arxiv).
- The next round can only be executed after the previous round has been recovered or refunded.
- git
- You'll know you did it right if you can run
git --versionand you see a response likegit version x.x.x
- You'll know you did it right if you can run
- Nodejs
- You'll know you've installed nodejs right if you can run:
node --versionand get an output like:vx.x.x- It'll need to be at least
18.16.0of node
- You'll know you've installed nodejs right if you can run:
- Yarn instead of
npm- You'll know you've installed yarn right if you can run:
yarn --versionand get an output like:x.x.x- You might need to install it with
npmorcorepack
- You'll know you've installed yarn right if you can run:
git clone https://github.com/tokamak-network/VDF-RNG-verifier.git
cd VDF-RNG-verifier
yarn
- Refer to .env.example to set up your .env file
- Get INFURA_API_KEY from infura dashbord
- Need two private keys to test the DRB by scripts.
- Get ETHERSCAN_API_KEY from etherscan myapikey
- Get OP_ETHERSCAN_API_KEY from opetherscan myapikey
- Get COINMARKETCAP_API_KEY from coinmarketcap
npx hardhat node --no-deploy
#Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
npx hardhat deploy --network localhost --tags cancun --reset## CHANGE in hardhat.config.ts files at network :{} section
npx hardhat deploy --network <NETWORK_NAME> --tags cancun --resetnpx hardhat deploy --network titan --tags paris --resetnpx hardhat test#It runs test/CommitRevealRecoverRNG.test.ts
npx hardhat node
#Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
npx hardhat test --network localhostnpx hardhat coverage- Guide(login required) : https://www.notion.so/onther/verify-contract-4b72acaa7e6c4dd0a8ee09fddfa6c539
slither .
- Solc Version: 0.8.24
- We are managing contracts by splitting evmVersion into paris and cancun.
- cancun is for using transient storage.
- paris is for network Titan network (legacy optimism fork).
- Chain(s) to deploy contract to: Ethereum, Sepolia, opSepolia, titan, titansepolia
- Owner: The user who setSettingVariables
- setting variables: disputePeriod, minimumDepositAmount, avgL2GasUsed, avgL1GasUsed, avgL1GasUsedForTitan, premiumPercentage, penaltyPercentage, flatFee
- Decentralizing this Owner is not yet in the scope of this project.
-
DirectFundingPrice
-
The cost of requesting a random number is calculated based on the optimistic case.
- Optimistic case of one round:
- 3 commits, 1 recover, 1 fulfill transaction fees.
- Calculation formula:
((tx.gasPrice * (callbackGasLimit + avgL2GasUsed)) * (premiumPercentage + 100)) / 100) + flatFee + getCurrentTxL1GasFee()- Definitions:
tx.gasPrice: Gas price when the current transaction is executed.callbackGasLimit: Gas limit of thefulfillRandomWordfunction set by the Consumer. When the Coordinator contract calls thefulfillRandomWordfunction of the Consumer contract, if the gas usage exceeds thecallbackGasLimit, the random number is stored in the Coordinator contract only, and the random number to the Consumer contract is canceled. (The transaction does not revert).avgL2GasUsed: Commit 3 average gas used + recover 1 average gas used + fulfillRandomWord 1 average gas used.premiumPercentage: The cost can be multiplied by a percentage to increase the cost. It is currently set to 0 and not used.flatFee: Flat fee.getCurrentTxL1GasFee(): For L2, we need to calculate L1 gas.
- Optimistic case of one round:
-
CurrentTxL1GasFee
- For L2, the size of the calldata determines the L1 gas cost, and different Optimism versions calculate the L1 gas cost differently. (Arbitrum is not considered.)
- Legacy versions (Titan, Titan Sepolia)
- In the Predeploy contract, the
OVM_GasPriceOraclecontract, values likebaseFeeare taken from theOVM_GasPriceOraclecontract and calculated based oncalldata_size. - Fixed address of
OVM_GasPriceOraclecontract:0x420000000000000000000000000000000000000000000000000F
- In the Predeploy contract, the
- Bedrock version, Ecotone version
- Both Bedrock and Ecotone versions get
baseFeeand blob-related values from a predeploy contract calledL1_Block_Attributesand calculate them based oncalldata_size. L1_Block_Attributescontract at fixed address:0x4200000000000000000000000000000000000000000000000015
- Both Bedrock and Ecotone versions get
- Legacy versions (Titan, Titan Sepolia)
- For L2, the size of the calldata determines the L1 gas cost, and different Optimism versions calculate the L1 gas cost differently. (Arbitrum is not considered.)
-
CalculateDirectFundingPrice example on Titan network
tx.gasPrice: Fixed to 0.001 Gwei.callbackGasLimit: Assumed to be 100,000.avgL2GasUsed:- 3 Commit: 554690 + 539184 + 558154 = 1,652,028
- 1 Recover: 337,913
- 1 FulfillRandomWord: Approx. 118,000
- Total: 2,107,941
flatFee: Assumed to be 0.001 ETH.getCurrentTxL1GasFee():avgL1GasUsed(proportional to calldata size):- 3 Commit: 10,508 + 10,496 + 10,496
- 1 Recover: 10,484
- 1 FulfillRandomWord: 5,840
- Total: 47,824
l1BaseFee: 23.433261599 Gwei (fixed).
- Calculation:
0.001 Gwei * (100,000 + 2,107,941) + 0.001 ETH + 23.433261599 Gwei * 47,824= 2,207,941,000,000 + 1,000,000,000,000,000 + 1,120,672,302,710,576 wei= 2,122,880,243,710,576 wei=> 0.002122880243710576 ETH=> 11,003 KRW=> 8.03 USD
-
-
EstimateDirectFundingPrice
- How to calculate how much to send when requesting a
requestRandomWordoff-chain:- Get the
gasPriceof the current network. - Use the
EstimateDirectFundingPriceview function of the Coordinator contract to get the corresponding cost by providing thegasPriceandcallbackGasLimitas parameters. - Add a buffer to the cost and include it as a value when calling
requestRandomWord.- Reason for buffer: The
gasPricecan fluctuate (thegasPriceobtained off-chain and thegasPricewhen the transaction is executed can be very different). - A buffer of 10% is a good rule of thumb.
- What happens to the amount left over after giving a buffer?
- The remaining amount will stay in the Consumer contract. In a single transaction of
requestRandomWord, thecalculateDirectFundingPricefunction is executed twice (once by the Consumer and once by the Coordinator).- We should provide guidance for Consumer contract developers to implement logic that allows the requestor to withdraw the remaining amount, or handle it differently.
- When implementing the Consumer, we will guide developers to implement it by inheriting from an abstract contract called
RNGConsumerBase. By declaring an empty function to handle the remaining amount, Consumer developers will be required to implement it to avoid abstract contract errors.
- When implementing the Consumer, we will guide developers to implement it by inheriting from an abstract contract called
- We should provide guidance for Consumer contract developers to implement logic that allows the requestor to withdraw the remaining amount, or handle it differently.
- The remaining amount will stay in the Consumer contract. In a single transaction of
- Reason for buffer: The
- Get the
- How to calculate how much to send when requesting a
-
minimumDepositAmount
- Since the rounds run in some degree of parallel, it is possible to be penalized simultaneously at a given point. Therefore, logic needs to be added to check if the minimumDepositAmount of the operators is appropriate for each round.
- This will be fixed after the RandomDay event.
- Incentive mechanisms (not updated yet):
- What if the leader doesn't recover for 2 minutes?
- Any other operators who committed to this round should recover.
- There should be a recovery gas cost plus some reward. The leader's reward should go to the recoverer (first come, first served).
- What if the leader doesn't recover for 2 minutes?
- Since the rounds run in some degree of parallel, it is possible to be penalized simultaneously at a given point. Therefore, logic needs to be added to check if the minimumDepositAmount of the operators is appropriate for each round.
-
reRequestRandomWordAtRound
- The function may be executed when the commitPhase is over and there are less than 2 commits.
- This function was created to ensure that the specific round to be fulfilled. However, this function requires additional gas to run, which will be addressed in the future.
- Function descriptions
- In a round that is reRequested when there is already a single commit, the existing committed commit and its operator are expected to participate normally in that round. However, the existing commit count is ignored and counted from zero again.
- Reason: We implemented this because if the reRequested round creates one more commit, resulting in a total of two commits to recover, it may not be a safe random number.
- Who runs it?
- Functions can be executed by anyone, but the operator (who wants to participate in the round) will be the one to run it.
- We are aware the Coordinator is owned by a single user who can set fee related variables, aka it is centralized.
- We are missing some zero address checks/input validation intentionally to save gas.
