Skip to content

RNG Fallback #1782

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

Closed
wants to merge 4 commits into from
Closed

RNG Fallback #1782

wants to merge 4 commits into from

Conversation

jaybuidl
Copy link
Member

@jaybuidl jaybuidl commented Dec 11, 2024

⚠️ This PR has been recreated as #2054 which replaces it.


This PR is a redo of #966 as it has deviated too much from dev. It is based atop the feat/chainlink-vrf-as-rng2 branch (PR #1778).

This PR introduces a composite RNG called RNGWithFallback responsible for the fallback logic.

This PR breaks the storage layout of the SortitionModule so it cannot be upgraded and will require a full redeploy.

The RNGs are permissioned to prevent 3rd parties from using up the funds on the RNG oracle accounts with Chainlink or Randomizer.

The RNGs do not support concurrent requests, it is not necessary since only 1 consumer is allowed (the sortition module), with the notable exception of some governance function triggering a re-request, which invalidates the previous one.

This PR introduces several ABI changes:

  • RNG interface renamed IRNG
  • Removal of the _block parameter from the IRNG interface which is not necessary for VRFs, only for the BlockHashRNG which now tracks the block numbers internally

PR-Codex overview

This PR focuses on refactoring the random number generation system by introducing the IRNG interface, modifying contracts to utilize this interface, and updating deployment scripts accordingly. It enhances flexibility and standardizes random number generation across various implementations.

Detailed summary

  • Deleted RNG.solcspell.json.
  • Introduced IRNG interface in contracts/src/rng/IRNG.sol.
  • Updated SortitionModule and SortitionModuleNeo to use IRNG instead of RNG.
  • Changed RNG_LOOKAHEAD to RNG_LOOKAHEAD_TIME in deployment scripts.
  • Modified IncrementalNG, RandomizerRNG, ChainlinkRNG, and BlockHashRNG to implement IRNG.
  • Adjusted function signatures in RNG contracts to remove block parameters.
  • Updated test cases to reflect changes in randomness request and receipt methods.
  • Added RNGWithFallback contract to provide a fallback mechanism for RNG requests.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Introduced a modular random number generator (RNG) interface for improved flexibility.
    • Added support for Chainlink VRF and fallback RNG mechanisms.
    • Enhanced role management with distinct governor and consumer roles for RNG contracts.
  • Improvements

    • Simplified and unified RNG contract interfaces for easier integration.
    • Updated deployment scripts and contract initialization flows for the new RNG architecture.
    • Improved event logging and error handling during randomness requests.
  • Bug Fixes

    • Streamlined randomness lifecycle to prevent issues with outdated or missing parameters.
  • Documentation

    • Added new terms to the spell check dictionary for clarity.
  • Tests

    • Updated and expanded test coverage for new RNG contracts and interface changes.

Copy link
Contributor

coderabbitai bot commented Dec 11, 2024

Walkthrough

This update refactors the random number generation (RNG) system across contracts and deployment scripts. It replaces the old RNG interface with a new IRNG interface, updates all RNG implementations and consumers to use parameterless randomness requests, introduces new RNG contracts (including Chainlink and fallback variants), and revises deployment/test logic accordingly.

Changes

File(s) Change Summary
contracts/src/rng/IRNG.sol New interface IRNG with parameterless requestRandomness() and receiveRandomness() methods.
contracts/src/rng/RNG.sol Deleted old RNG interface with block-parameterized methods.
contracts/src/rng/BlockhashRNG.sol,
contracts/src/rng/IncrementalNG.sol,
contracts/src/rng/RandomizerRNG.sol
Refactored to implement IRNG instead of RNG; methods now parameterless; added/updated roles (governor, consumer); updated state variables and event logic.
contracts/src/rng/ChainlinkRNG.sol New contract implementing IRNG using Chainlink VRF v2.5; includes governance, consumer roles, and event tracking.
contracts/src/rng/RNGWithFallback.sol New contract providing automatic fallback across multiple RNGs, with governance and consumer roles, and event emission on fallback or failure.
contracts/src/arbitration/SortitionModule*.sol Updated to use IRNG instead of RNG; removed lookahead/block parameters from initialization and RNG change methods.
contracts/deploy/00-home-chain-arbitration-neo.ts,
contracts/deploy/00-home-chain-arbitration.ts,
contracts/deploy/00-rng.ts,
contracts/deploy/upgrade-sortition-module.ts
Deployment scripts updated for new RNG initialization, parameterless methods, and revised constructor arguments.
contracts/test/rng/index.ts Tests updated for parameterless RNG methods; new/updated tests for BlockhashRNG, ChainlinkRNG, IncrementalNG.
cspell.json Added "Chainlink", "IRNG", and "rngs" to spelling whitelist.

Sequence Diagram(s)

sequenceDiagram
    participant Governor
    participant Consumer
    participant RNG (IRNG)
    participant SortitionModule

    Governor->>RNG: changeConsumer(address)
    Consumer->>RNG: requestRandomness()
    RNG-->>Consumer: emits RequestSent event
    RNG-->>RNG: (generates random number asynchronously)
    Consumer->>RNG: receiveRandomness()
    RNG-->>Consumer: returns random number (if ready)
    Consumer->>SortitionModule: passPhase() or similar
    SortitionModule->>RNG: requestRandomness()
    RNG-->>SortitionModule: emits RequestSent event
    SortitionModule->>RNG: receiveRandomness()
    RNG-->>SortitionModule: returns random number
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • kleros/kleros-v2#1778: Integrates ChainlinkRNG into deployment and contracts, related by focus on RNG deployment and configuration, but targets different RNG implementations.

Suggested labels

Type: Feature🗿, Type: Maintenance :construction:

Poem

In the fields of code where the random winds blow,
Rabbits hop swiftly, letting old interfaces go.
With IRNG seeds and Chainlink in tow,
They sprinkle new contracts—let the randomness flow!
No more blocky burdens, just clear, simple calls,
As governance and consumers dance through the protocol halls.
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/rng-fallback

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Dec 11, 2024

Deploy Preview for kleros-v2-university failed. Why did it fail? →

Name Link
🔨 Latest commit f0746bd
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-university/deploys/6882699f1b96d50008b70e0f

Copy link

netlify bot commented Dec 11, 2024

Deploy Preview for kleros-v2-testnet failed. Why did it fail? →

Name Link
🔨 Latest commit f0746bd
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet/deploys/6882699f0882d30008ba15f2

Copy link

netlify bot commented Dec 11, 2024

Deploy Preview for kleros-v2-neo failed. Why did it fail? →

Name Link
🔨 Latest commit f0746bd
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-neo/deploys/6882699f4c69af00088d91ab

Copy link

codeclimate bot commented Dec 11, 2024

Code Climate has analyzed commit ec3cd79 and detected 11 issues on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 2
Duplication 6
Style 3

View more on Code Climate.

@jaybuidl jaybuidl linked an issue Dec 11, 2024 that may be closed by this pull request
Copy link

netlify bot commented Dec 11, 2024

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit f0746bd
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet-devtools/deploys/6882699f3e9695000892c3cf

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Outside diff range and nitpick comments (9)
prettier-config/index.js (1)

25-25: Consider pinning the plugin version

To ensure consistent formatting across different environments and prevent unexpected changes, consider importing the plugin with a specific version.

-  plugins: [require("prettier-plugin-solidity")],
+  plugins: [require("[email protected]")],
contracts/src/rng/RandomizerRNG.sol (1)

21-21: Specify visibility for lastRequestId variable

The variable lastRequestId does not have an explicit visibility modifier. In Solidity, it's best practice to explicitly declare the visibility of state variables to avoid confusion.

Apply this diff to specify the visibility:

-    uint256 lastRequestId; // The last request ID.
+    uint256 public lastRequestId; // The last request ID.
contracts/src/rng/IncrementalNG.sol (1)

11-11: Consider making the state variable private

The number variable could be made private since it's only used internally. This would prevent external contracts from directly accessing the current state.

-    uint256 public number;
+    uint256 private number;
contracts/deploy/00-chainlink-rng.ts (1)

15-29: Consider environment-based key hash configuration

Hardcoding key hashes in the deployment script makes updates difficult. Consider moving these to environment variables or a configuration file.

// config/chainlink.json
{
  "keyHashes": {
    "ARBITRUM_ONE": {
      "2": "0x9e9e...",
      // ...
    }
  }
}
contracts/deploy/00-home-chain-arbitration.ts (1)

Line range hint 113-119: Consider failing deployment on currency rate errors

Swallowing errors during currency rate configuration could lead to a partially initialized system. Consider either:

  1. Allowing the error to propagate to fail the deployment
  2. Adding a deployment flag to control whether currency rate errors should be fatal
-  try {
     await changeCurrencyRate(core, await pnk.getAddress(), true, 12225583, 12);
     await changeCurrencyRate(core, await dai.getAddress(), true, 60327783, 11);
     await changeCurrencyRate(core, await weth.getAddress(), true, 1, 1);
-  } catch (e) {
-    console.error("failed to change currency rates:", e);
-  }
contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol (2)

35-56: Consider adding reentrancy protection

The low-level call to the consumer could be exploited for reentrancy attacks. Although this is a mock contract, it's good practice to maintain security patterns.

 function fulfillRandomWords(uint256 _requestId, address _consumer, uint256[] memory _words) public {
+    // Save and delete request before the external call to prevent reentrancy
+    VRFV2PlusClient.RandomWordsRequest memory req = requests[_requestId];
+    delete requests[_requestId];
+
     if (requests[_requestId].subId == 0) {
         revert("nonexistent request");
     }
-    VRFV2PlusClient.RandomWordsRequest memory req = requests[_requestId];

     // ... rest of the function ...

-    delete (requests[_requestId]);
     emit RandomWordsFulfilled(_requestId, success);
 }

111-158: Consider making configuration values adjustable

The hardcoded configuration values might not cover all test scenarios. Consider making these values configurable through constructor parameters or setter functions to support diverse testing requirements.

+    uint16 private minimumRequestConfirmations = 3;
+    uint32 private maxGasLimit = 2000000;
+
+    function setRequestConfig(
+        uint16 _minimumRequestConfirmations,
+        uint32 _maxGasLimit
+    ) external {
+        minimumRequestConfirmations = _minimumRequestConfirmations;
+        maxGasLimit = _maxGasLimit;
+    }

     function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory) {
-        return (3, 2000000, new bytes32[](0));
+        return (minimumRequestConfirmations, maxGasLimit, new bytes32[](0));
     }
contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json (2)

216-228: Add events for critical parameter changes

The contract should emit events when critical parameters like keyHash and subscriptionId are modified to facilitate off-chain tracking and monitoring.

Add events for parameter changes:

+event KeyHashChanged(bytes32 oldKeyHash, bytes32 newKeyHash);
+event SubscriptionIdChanged(uint256 oldSubId, uint256 newSubId);

 function changeKeyHash(bytes32 _keyHash) external onlyByGovernor {
+    emit KeyHashChanged(keyHash, _keyHash);
     keyHash = _keyHash;
 }

 function changeSubscriptionId(uint256 _subscriptionId) external onlyByGovernor {
+    emit SubscriptionIdChanged(subscriptionId, _subscriptionId);
     subscriptionId = _subscriptionId;
 }

Also applies to: 242-254


558-568: Enhance constructor documentation

The constructor documentation should include information about the recommended ranges or constraints for the parameters.

Add parameter constraints to the documentation:

 * @param _callbackGasLimit The limit for how much gas to use for the callback request to the contract's fulfillRandomWords() function.
+* @dev Recommended range: 100,000-300,000 based on operation complexity
 * @param _requestConfirmations How many confirmations the Chainlink node should wait before responding.
+* @dev Recommended range: 3-200 confirmations. Higher values increase security but also latency
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8cde978 and ec3cd79.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (25)
  • contracts/deploy/00-chainlink-rng.ts (1 hunks)
  • contracts/deploy/00-home-chain-arbitration-neo.ts (5 hunks)
  • contracts/deploy/00-home-chain-arbitration-university.ts (3 hunks)
  • contracts/deploy/00-home-chain-arbitration.ts (5 hunks)
  • contracts/deploy/00-rng.ts (4 hunks)
  • contracts/deploy/upgrade-sortition-module.ts (0 hunks)
  • contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json (1 hunks)
  • contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json (1 hunks)
  • contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json (1 hunks)
  • contracts/package.json (1 hunks)
  • contracts/src/arbitration/SortitionModule.sol (1 hunks)
  • contracts/src/arbitration/SortitionModuleBase.sol (5 hunks)
  • contracts/src/arbitration/SortitionModuleNeo.sol (1 hunks)
  • contracts/src/rng/BlockhashRNG.sol (1 hunks)
  • contracts/src/rng/ChainlinkRNG.sol (1 hunks)
  • contracts/src/rng/IRNG.sol (1 hunks)
  • contracts/src/rng/IncrementalNG.sol (1 hunks)
  • contracts/src/rng/RNG.sol (0 hunks)
  • contracts/src/rng/RNGWithFallback.sol (1 hunks)
  • contracts/src/rng/RandomizerRNG.sol (6 hunks)
  • contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol (1 hunks)
  • contracts/test/rng/index.ts (3 hunks)
  • cspell.json (2 hunks)
  • prettier-config/index.js (1 hunks)
💤 Files with no reviewable changes (2)
  • contracts/src/rng/RNG.sol
  • contracts/deploy/upgrade-sortition-module.ts
✅ Files skipped from review due to trivial changes (2)
  • cspell.json
  • contracts/deployments/arbitrum/ChainlinkVRFCoordinator.json
👮 Files not reviewed due to content moderation or server errors (3)
  • contracts/src/arbitration/SortitionModuleBase.sol
  • contracts/deployments/arbitrumSepolia/ChainlinkVRFCoordinator.json
  • contracts/deployments/arbitrumSepoliaDevnet/ChainlinkVRFCoordinator.json
🔇 Additional comments (22)
prettier-config/index.js (1)

25-25: Verify prettier-plugin-solidity installation

The plugin needs to be available as a dev dependency for the configuration to work.

✅ Verification successful

Plugin is properly installed and available

The prettier-plugin-solidity is correctly installed as a dependency in both prettier-config/package.json and contracts/package.json with version ^1.4.1. The plugin will be available when Prettier runs since it's properly declared in the dependencies.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if prettier-plugin-solidity is properly installed
# Expected: Find the plugin in package.json and node_modules

# Check package.json for the dependency
echo "Checking package.json for prettier-plugin-solidity..."
jq '.devDependencies["prettier-plugin-solidity"]' package.json

# Check if the plugin exists in node_modules
echo "Checking if plugin directory exists..."
fd -t d "prettier-plugin-solidity$" node_modules

Length of output: 424


Script:

#!/bin/bash
# Let's check if package.json exists and examine its dependencies section
echo "Checking if package.json exists and its content..."
if [ -f "package.json" ]; then
    cat package.json
else
    echo "package.json not found"
fi

# Let's also check if there are any other package.json files in the repository
echo -e "\nSearching for all package.json files..."
fd "package.json$"

Length of output: 2874


Script:

#!/bin/bash
# Let's check the prettier-config package.json and its dependencies
echo "Checking prettier-config/package.json..."
cat prettier-config/package.json

# Also check if the plugin is mentioned in any other workspace package.json files
echo -e "\nChecking for prettier-plugin-solidity in other package.json files..."
rg "prettier-plugin-solidity" --type json

Length of output: 1003

contracts/src/rng/RNGWithFallback.sol (1)

86-109: Ensure secure governor address updates

When changing the governor via changeGovernor, it's crucial to validate the new address to prevent assigning an unintended or malicious address.

Run the following script to check for proper governor address assignment:

✅ Verification successful

Governor address update is properly secured

The changeGovernor function already implements the necessary security check by validating that the new governor address is not zero (require(_newGovernor != address(0), "Invalid governor")), and the function is protected by the onlyByGovernor modifier which ensures only the current governor can execute this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the governor address is not zero and is correctly updated.

# Search for instances where governor is set. Expect validations against zero address.
rg -A 2 'function changeGovernor' contracts/src/rng/RNGWithFallback.sol

Length of output: 247

contracts/src/rng/ChainlinkRNG.sol (1)

159-162: Confirm secure access control in fulfillRandomWords

While fulfillRandomWords relies on inherited access control, it's important to ensure that only the Chainlink VRF Coordinator can invoke it.

Run the following script to verify access control inheritance:

✅ Verification successful

Access control for fulfillRandomWords is properly implemented

The function is correctly protected through multiple security layers:

  1. It's declared as internal override, meaning it can only be called from within the contract or inherited contracts
  2. The contract inherits from VRFConsumerBaseV2Plus, which implements the core access control in rawFulfillRandomWords
  3. The implementation matches Chainlink's VRF v2.5 security model where only the verified VRF Coordinator can call this function
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Confirm that fulfillRandomWords is correctly protected.

# Expect: fulfillRandomWords is declared internal and cannot be called externally.
ast-grep --pattern 'function fulfillRandomWords$_(uint256 $_, uint256[] calldata $_) internal override' contracts/src/rng/ChainlinkRNG.sol

Length of output: 140


Script:

#!/bin/bash
# Let's try a broader pattern to catch the function declaration
ast-grep --pattern 'function fulfillRandomWords' contracts/src/rng/ChainlinkRNG.sol

# Also get the full context of the contract to understand inheritance
cat contracts/src/rng/ChainlinkRNG.sol

Length of output: 7893

contracts/src/rng/IRNG.sol (1)

10-12: ⚠️ Potential issue

Add view modifier to receiveRandomness

The receiveRandomness function should be marked as view since it does not modify state.

Apply this diff:

     /// @dev Receive the random number.
     /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.
-    function receiveRandomness() external returns (uint256 randomNumber);
+    function receiveRandomness() external view returns (uint256 randomNumber);

Likely invalid or redundant comment.

contracts/src/rng/IncrementalNG.sol (1)

25-27: Verify unchecked arithmetic safety

The unchecked increment is safe here since:

  1. It's used for generating sequential numbers
  2. Even if it overflows, it would continue the sequence from 0
contracts/src/arbitration/SortitionModule.sol (2)

40-42: Storage layout changes require redeployment

The removal of _rngLookahead parameter and change from RNG to IRNG affects storage layout. As mentioned in PR objectives, this requires redeployment of the module.

✅ Verification successful

Based on the code analysis, I can now generate the final response:

Storage layout changes require redeployment - Confirmed

The removal of _rngLookahead parameter and change from RNG to IRNG affects storage layout as evidenced by:

  1. The rngLookahead storage variable is marked as deprecated with a warning comment: // uint256 public rngLookahead; // Deprecated - WARNING: it breaks the storage layout of the contract, beta cannot be upgraded!
  2. The base contract's storage layout has been modified by removing this variable.
  3. The initialization function signature has been changed to remove this parameter.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify storage layout changes

# Check storage layout in current implementation
ast-grep --pattern 'contract SortitionModuleBase {
  $$$
  IRNG $_;
  $$$
}'

# Check for any remaining references to RNG interface
rg "RNG[^I]" --type sol

Length of output: 132


Script:

#!/bin/bash
# Let's try a different approach to verify storage layout changes

# Check for RNG-related storage variables and inheritance
ast-grep --pattern 'contract SortitionModule$_? {
  $$$
}'

# Look for storage variables in base contracts
ast-grep --pattern 'contract SortitionModuleBase {
  $$$
}'

# Search for RNG-related code with proper file extension
rg "RNG[^I]" -t solidity

# Check inheritance chain
rg "contract SortitionModule.*is.*" -t solidity

Length of output: 265


Script:

#!/bin/bash
# Let's try without file type filtering since ripgrep doesn't recognize solidity extension

# Find all Solidity files first
fd "\.sol$" contracts/src/

# Then use these patterns on all files
rg "contract SortitionModule.*is.*"
rg "RNG[^I]"

# Look for storage-related changes in git diff
git diff origin/main -- contracts/src/arbitration/SortitionModule.sol

Length of output: 86560


Script:

#!/bin/bash
# Let's check the file content directly to verify storage layout changes

# Check the current file content
cat contracts/src/arbitration/SortitionModule.sol

# Check the base contract content
cat contracts/src/arbitration/SortitionModuleBase.sol

# Check the interface definition
cat contracts/src/arbitration/interfaces/ISortitionModule.sol

Length of output: 35127


Line range hint 48-52: Verify upgrade safety

The UUPS upgrade pattern is correctly implemented with governor-only access. However, ensure that all contracts in the inheritance chain are upgrade-safe.

contracts/deploy/00-rng.ts (2)

44-44: Verify network check logic change

The deployment skip condition has been modified to use isMainnet. Ensure this doesn't accidentally enable deployments on unintended networks.

✅ Verification successful

Let me analyze the network validation logic further by checking the implementation of these utility functions.


Network validation logic is safe and correctly implemented

The change to use isMainnet is actually more restrictive than the previous validation. The isMainnet function checks for the presence of a "production" tag, which means deployments will only run on networks explicitly tagged as production environments. This is safer than the previous approach that was using HomeChains enum check, as it adds an additional layer of protection against accidental deployments.

Key validation points:

  • isMainnet relies on explicit production tags rather than chain IDs
  • The skip condition in the RNG deployment will prevent deployment on any network tagged as production
  • Other deployment scripts use complementary validation with HomeChains enum for additional safety
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check network validation

# Look for network validation patterns
rg "isMainnet|HomeChains" --type ts

Length of output: 6938


Script:

#!/bin/bash
# Check the implementation of isSkipped and related network validation functions
cat contracts/deploy/utils/index.ts

Length of output: 1080


18-19: Verify SortitionModule deployment prerequisite

The script assumes SortitionModuleNeo is already deployed. Ensure deployment dependencies are properly ordered.

contracts/src/rng/BlockhashRNG.sol (2)

13-15: ⚠️ Potential issue

Storage layout changes require careful migration

The contract's storage layout has changed significantly with the introduction of new state variables:

  • lookahead (immutable)
  • requestBlock
  • randomNumbers mapping

This change makes the contract incompatible with upgrades and requires redeployment, as mentioned in the PR objectives.


23-24: ⚠️ Potential issue

Potential race condition in requestRandomness

The function overwrites requestBlock without checking if there's an existing pending request. This could lead to a race condition if governance functions trigger a re-request.

contracts/src/arbitration/SortitionModuleNeo.sol (1)

50-54: ⚠️ Potential issue

Storage layout changes require redeployment

The change from RNG to IRNG type and removal of _rngLookahead parameter alters the storage layout, making this contract incompatible with upgrades.

Let's verify the storage layout changes:

contracts/deploy/00-home-chain-arbitration-university.ts (2)

56-56: LGTM: Safe placeholder usage

Using ZeroAddress as a placeholder is acceptable here since the comment indicates that KlerosCore is configured later.


Line range hint 66-73: Improved core change handling with validation

Good improvement to check the current core before making changes, avoiding unnecessary transactions.

contracts/package.json (1)

107-109: Verify dependency versions for security

New dependencies added:

  • @chainlink/contracts@^1.3.0
  • @openzeppelin/contracts@^5.1.0

Let's check for known vulnerabilities:

✅ Verification successful

Based on the results from the verification scripts, I can now generate a final response:

Dependencies appear to be properly integrated and used

The verification shows:

  1. Chainlink contracts are used appropriately for VRF (Verifiable Random Function) implementation in ChainlinkRNG.sol
  2. OpenZeppelin contracts are widely used across the codebase in a standard way
  3. No immediate security concerns are visible in the implementation

The dependencies are:

  • @chainlink/contracts@^1.3.0 - Used for VRF functionality
  • @openzeppelin/contracts@^5.1.0 - Used for standard contract patterns
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for known vulnerabilities in new dependencies

# Check npm for known vulnerabilities
npm audit --json @chainlink/contracts@^1.3.0 @openzeppelin/contracts@^5.1.0 | jq '.vulnerabilities'

# Check GitHub security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "chainlink__contracts") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 811


Script:

#!/bin/bash
# Let's try a different approach to check the dependencies

# First, let's check if these packages are actually used in the codebase
echo "=== Checking @chainlink/contracts usage ==="
rg -l "@chainlink/contracts" --type-add 'sol:*.sol'

echo -e "\n=== Checking @openzeppelin/contracts usage ==="
rg -l "@openzeppelin/contracts" --type-add 'sol:*.sol'

# Let's also check the package versions in the lock file if it exists
echo -e "\n=== Checking package-lock.json ==="
if [ -f "contracts/package-lock.json" ]; then
    cat contracts/package-lock.json | jq '.packages["@chainlink/contracts"], .packages["@openzeppelin/contracts"]'
fi

# Let's check if there's a yarn.lock
echo -e "\n=== Checking yarn.lock ==="
if [ -f "contracts/yarn.lock" ]; then
    cat contracts/yarn.lock | grep -A 5 "@chainlink/contracts"
    echo "---"
    cat contracts/yarn.lock | grep -A 5 "@openzeppelin/contracts"
fi

Length of output: 4908


Script:

#!/bin/bash
# Let's examine the actual usage of these dependencies in the code

echo "=== Checking Chainlink contracts usage patterns ==="
rg -C 2 "VRFCoordinator" --type-add 'sol:*.sol' contracts/

echo -e "\n=== Checking OpenZeppelin contracts usage patterns ==="
# Look for common OZ patterns
rg -l "import.*@openzeppelin/contracts/(access|token|utils|security)/" --type-add 'sol:*.sol' contracts/

# Check specific versions in use
echo -e "\n=== Checking current dependency versions ==="
if [ -f "contracts/package.json" ]; then
    jq '.dependencies | select(has("@chainlink/contracts") or has("@openzeppelin/contracts"))' contracts/package.json
fi

# Let's also check the commit history for any recent security-related changes
echo -e "\n=== Checking recent security-related commits ==="
git log --oneline -n 10 contracts/package.json

Length of output: 66699

contracts/deploy/00-home-chain-arbitration.ts (2)

104-110: LGTM! Efficient configuration update

The conditional update of the RNG's consumer prevents unnecessary transactions and gas costs by checking the current state before making changes.


39-41: Verify initialization sequence for RandomizerRNG

The deployment uses ZeroAddress as a placeholder for SortitionModule, which is configured later. This is a safe approach, but we should verify that the contract cannot be used before proper initialization.

✅ Verification successful

Initialization sequence for RandomizerRNG is properly secured

The contract has adequate safeguards for initialization and usage:

  • The initialize function properly sets the consumer address during initialization
  • The onlyByConsumer modifier ensures only the authorized consumer can request randomness
  • The consumer can only be changed by the governor through changeConsumer
  • The requestRandomness function is protected by onlyByConsumer modifier
  • The callback function is protected by checking the sender is the randomizer contract
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if RandomizerRNG has safeguards against usage before initialization
ast-grep --pattern 'function $FUNC($$$) {
  $$$
  require($CONSUMER != address(0), $$$);
  $$$
}'

Length of output: 99


Script:

#!/bin/bash
# Let's first find the RandomizerRNG contract implementation
fd -e sol -e vy "RandomizerRNG"

# Then examine its content for zero address checks and initialization patterns
rg -l "RandomizerRNG" --type sol

Length of output: 128


Script:

#!/bin/bash
# Search for require statements and modifiers in RandomizerRNG
rg "require\(" -A 2 -B 2 --type sol

Length of output: 65


Script:

#!/bin/bash
# Look for initialization or setup functions
ast-grep --pattern 'function set$_($$$) {
  $$$
}'

Length of output: 52


Script:

#!/bin/bash
# Search for constructor implementation
ast-grep --pattern 'constructor($$$) {
  $$$
}'

Length of output: 49


Script:

#!/bin/bash
# Let's examine the RandomizerRNG contract content directly
cat contracts/src/rng/RandomizerRNG.sol

Length of output: 5380


Script:

#!/bin/bash
# Search for require statements without file type specification
rg "require\(" -A 2 -B 2

Length of output: 66851


Script:

#!/bin/bash
# Look for functions that might use the consumer address
rg "consumer" -A 2 -B 2 contracts/src/rng/RandomizerRNG.sol

Length of output: 1011

contracts/deploy/00-home-chain-arbitration-neo.ts (1)

98-104: Same issues as in home-chain-arbitration.ts

This file contains the same patterns as 00-home-chain-arbitration.ts:

  1. The RNG consumer configuration pattern is correct
  2. The error handling for currency rates should be improved

Also applies to: 107-112

contracts/src/rng/mock/ChainlinkVRFCoordinatorMock.sol (2)

1-30: LGTM! Well-structured mock implementation

The contract properly implements the VRF coordinator interface with appropriate storage and events.


58-73: LGTM! Clean implementation

The request handling is straightforward and appropriate for testing purposes.

contracts/deployments/arbitrumSepoliaDevnet/ChainlinkRNG.json (2)

490-491: Review the callback gas limit configuration

The callback gas limit is set to 100,000 which might be insufficient for complex operations in the fulfillRandomWords function, especially if the consumer contract performs significant computation or storage operations.

Consider:

  1. Analyzing gas usage in test environments
  2. Implementing a safety margin (e.g., 200,000-300,000) to handle varying gas costs
  3. Documenting the gas requirement analysis
✅ Verification successful

Callback gas limit of 100,000 is sufficient for this implementation

The current callback gas limit of 100,000 is adequate for the ChainlinkRNG contract's fulfillRandomWords implementation because:

  1. The function performs minimal operations:

    • A single storage write to randomNumbers[_requestId]
    • Emitting a single event with two parameters
  2. The implementation has no complex computations, loops, or external calls that would require significant gas.

  3. Similar storage operations typically consume around 20,000-25,000 gas, and event emissions around 2,000-3,000 gas, leaving a comfortable safety margin for the VRF callback.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check typical gas usage patterns for VRF callbacks

# Search for fulfillRandomWords implementations to analyze complexity
ast-grep --pattern 'function fulfillRandomWords($_, $_) {
  $$$
}'

# Look for storage operations in fulfillRandomWords
rg -A 5 "fulfillRandomWords.*{" 

Length of output: 208


Script:

#!/bin/bash
# Let's try a different approach to analyze the VRF callback implementation

# Search for fulfillRandomWords function implementation
ast-grep --pattern 'function fulfillRandomWords'

# Search for VRF-related files and contracts
fd -e sol -e json . | xargs rg -l "fulfillRandomWords"

# Check for gas-related configurations in source files
rg -i "callbackgas|gaslimit" -A 3

Length of output: 68149


Script:

#!/bin/bash
# Let's analyze the fulfillRandomWords implementation in ChainlinkRNG contract

# Search for fulfillRandomWords implementation
rg -p "function fulfillRandomWords.*\{" contracts/src/rng/ChainlinkRNG.sol -A 10

# Check for storage operations in the implementation
rg -p "randomNumbers\[.*\].*=" contracts/src/rng/ChainlinkRNG.sol

# Look for any gas-related comments or documentation
rg -p "gas|Gas" contracts/src/rng/ChainlinkRNG.sol

Length of output: 1771


484-491: Verify the governor configuration

The governor and sortitionModule are set to the same address in the constructor arguments, which might indicate a misconfiguration.

@jaybuidl jaybuidl changed the base branch from dev to feat/chainlink-vrf-as-rng2 December 11, 2024 11:41
@jaybuidl jaybuidl removed a link to an issue Dec 12, 2024
@jaybuidl jaybuidl force-pushed the feat/chainlink-vrf-as-rng2 branch 2 times, most recently from 770d1c0 to 9e0f05b Compare December 13, 2024 19:02
Base automatically changed from feat/chainlink-vrf-as-rng2 to dev December 13, 2024 21:11
@jaybuidl jaybuidl linked an issue Mar 19, 2025 that may be closed by this pull request
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
contracts/src/rng/BlockhashRNG.sol (1)

95-101: Consider improving randomness quality and transparency.

The current implementation always uses blockhash(block.number - 1) regardless of when receiveRandomness() is called within the time window. This could lead to predictable patterns. Additionally, there's no indication when randomness is unavailable (returns 0).

Consider:

  1. Using a combination of block.timestamp and blockhash for better entropy
  2. Emitting events when randomness is unavailable
     // Use last block hash for randomness
-    randomNumber = uint256(blockhash(block.number - 1));
+    randomNumber = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)));
     if (randomNumber != 0) {
         randomNumbers[expectedTimestamp] = randomNumber;
+    } else {
+        emit RandomnessUnavailable(expectedTimestamp);
     }
contracts/src/rng/RNGWithFallback.sol (1)

169-173: Consider the impact of emergency reset on underlying RNG states.

The emergencyReset() function resets the contract's internal state but doesn't consider that underlying RNG contracts might still have pending requests. This could lead to unexpected behavior if those RNGs later provide responses.

Consider adding a comment or documentation about the implications of emergency reset, or potentially add logic to notify the current RNG about the reset if possible.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec3cd79 and f0746bd.

📒 Files selected for processing (5)
  • contracts/deploy/00-home-chain-arbitration.ts (3 hunks)
  • contracts/deploy/00-rng.ts (2 hunks)
  • contracts/src/rng/BlockhashRNG.sol (1 hunks)
  • contracts/src/rng/RNGWithFallback.sol (1 hunks)
  • contracts/test/rng/index.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • contracts/deploy/00-home-chain-arbitration.ts
  • contracts/deploy/00-rng.ts
  • contracts/test/rng/index.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: jaybuidl
PR: kleros/kleros-v2#1778
File: contracts/src/rng/ChainlinkRNG.sol:135-153
Timestamp: 2024-12-07T11:39:10.927Z
Learning: In the `contracts/src/rng/ChainlinkRNG.sol` contract, the `requestRandomness` function is restricted to being called only by the `SortitionModule`, which does not send concurrent requests. Therefore, it's acceptable not to handle multiple random number requests concurrently in this context.
Learnt from: jaybuidl
PR: kleros/kleros-v2#1778
File: contracts/src/rng/RandomizerRNG.sol:21-21
Timestamp: 2024-12-07T11:41:15.835Z
Learning: Only the `SortitionModule` can call `requestRandomness`, and it doesn't send concurrent requests, so handling multiple concurrent random number requests is unnecessary in this context.
contracts/src/rng/RNGWithFallback.sol (2)

Learnt from: jaybuidl
PR: #1778
File: contracts/src/rng/ChainlinkRNG.sol:135-153
Timestamp: 2024-12-07T11:39:10.927Z
Learning: In the contracts/src/rng/ChainlinkRNG.sol contract, the requestRandomness function is restricted to being called only by the SortitionModule, which does not send concurrent requests. Therefore, it's acceptable not to handle multiple random number requests concurrently in this context.

Learnt from: jaybuidl
PR: #1778
File: contracts/src/rng/RandomizerRNG.sol:21-21
Timestamp: 2024-12-07T11:41:15.835Z
Learning: Only the SortitionModule can call requestRandomness, and it doesn't send concurrent requests, so handling multiple concurrent random number requests is unnecessary in this context.

contracts/src/rng/BlockhashRNG.sol (2)

Learnt from: jaybuidl
PR: #1778
File: contracts/src/rng/ChainlinkRNG.sol:135-153
Timestamp: 2024-12-07T11:39:10.927Z
Learning: In the contracts/src/rng/ChainlinkRNG.sol contract, the requestRandomness function is restricted to being called only by the SortitionModule, which does not send concurrent requests. Therefore, it's acceptable not to handle multiple random number requests concurrently in this context.

Learnt from: jaybuidl
PR: #1778
File: contracts/src/rng/RandomizerRNG.sol:21-21
Timestamp: 2024-12-07T11:41:15.835Z
Learning: Only the SortitionModule can call requestRandomness, and it doesn't send concurrent requests, so handling multiple concurrent random number requests is unnecessary in this context.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Redirect rules - kleros-v2-university
  • GitHub Check: Header rules - kleros-v2-university
  • GitHub Check: Pages changed - kleros-v2-university
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
🔇 Additional comments (4)
contracts/src/rng/BlockhashRNG.sol (3)

42-50: Constructor implementation looks correct.

The previously reported constructor bug where lookahead was being added to itself has been fixed. The implementation now correctly assigns the constructor parameters.


28-66: Access control implementation is secure and well-structured.

The contract properly implements role-based access control with governor and consumer roles, including governance functions to update these roles.


107-119: View functions are well-implemented.

The view functions properly handle edge cases and provide clear information about randomness readiness and availability timing.

contracts/src/rng/RNGWithFallback.sol (1)

1-185: Well-designed composite RNG with robust fallback mechanism.

The contract implements a solid architectural pattern for RNG management with fallback capabilities. The design aligns well with the learned context that only the SortitionModule uses these functions without concurrent requests, making the single-request state management appropriate.

Comment on lines +42 to +49
constructor(address _governor, address _consumer, uint256 _fallbackTimeoutSeconds, IRNG _defaultRng) {
require(address(_defaultRng) != address(0), "Invalid default RNG");

governor = _governor;
consumer = _consumer;
fallbackTimeoutSeconds = _fallbackTimeoutSeconds;
rngs.push(_defaultRng);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation for governor and consumer addresses.

The constructor validates the default RNG but doesn't validate the governor and consumer addresses, which could lead to issues if zero addresses are passed.

 constructor(address _governor, address _consumer, uint256 _fallbackTimeoutSeconds, IRNG _defaultRng) {
+    require(_governor != address(0), "Invalid governor");
+    require(_consumer != address(0), "Invalid consumer");
     require(address(_defaultRng) != address(0), "Invalid default RNG");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constructor(address _governor, address _consumer, uint256 _fallbackTimeoutSeconds, IRNG _defaultRng) {
require(address(_defaultRng) != address(0), "Invalid default RNG");
governor = _governor;
consumer = _consumer;
fallbackTimeoutSeconds = _fallbackTimeoutSeconds;
rngs.push(_defaultRng);
}
constructor(address _governor, address _consumer, uint256 _fallbackTimeoutSeconds, IRNG _defaultRng) {
require(_governor != address(0), "Invalid governor");
require(_consumer != address(0), "Invalid consumer");
require(address(_defaultRng) != address(0), "Invalid default RNG");
governor = _governor;
consumer = _consumer;
fallbackTimeoutSeconds = _fallbackTimeoutSeconds;
rngs.push(_defaultRng);
}
🤖 Prompt for AI Agents
In contracts/src/rng/RNGWithFallback.sol around lines 42 to 49, the constructor
validates the default RNG address but does not validate the governor and
consumer addresses. Add require statements to check that both governor and
consumer addresses are not zero addresses to prevent invalid initialization.
This ensures the contract is deployed with valid critical addresses.

Comment on lines +94 to +108
// If the timeout is exceeded, try next RNG
if (block.timestamp > requestTimestamp + fallbackTimeoutSeconds) {
uint256 nextIndex = currentRngIndex + 1;

// If we have another RNG to try, switch to it and request again
if (nextIndex < rngs.length) {
emit RNGFallback(currentRngIndex, nextIndex);
currentRngIndex = nextIndex;
_requestRandomness(nextIndex);
} else {
// No more RNGs to try
emit RNGFailure();
}
}
return randomNumber;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix timeout logic for fallback RNG requests.

When switching to a fallback RNG, the code doesn't reset requestTimestamp, causing subsequent timeout checks to be based on the original request time rather than the new fallback request time. This could lead to immediate timeouts for subsequent fallbacks.

         // If the timeout is exceeded, try next RNG
         if (block.timestamp > requestTimestamp + fallbackTimeoutSeconds) {
             uint256 nextIndex = currentRngIndex + 1;

             // If we have another RNG to try, switch to it and request again
             if (nextIndex < rngs.length) {
                 emit RNGFallback(currentRngIndex, nextIndex);
-                currentRngIndex = nextIndex;
-                _requestRandomness(nextIndex);
+                _requestRandomness(nextIndex); // This will update requestTimestamp
             } else {
                 // No more RNGs to try
                 emit RNGFailure();
             }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// If the timeout is exceeded, try next RNG
if (block.timestamp > requestTimestamp + fallbackTimeoutSeconds) {
uint256 nextIndex = currentRngIndex + 1;
// If we have another RNG to try, switch to it and request again
if (nextIndex < rngs.length) {
emit RNGFallback(currentRngIndex, nextIndex);
currentRngIndex = nextIndex;
_requestRandomness(nextIndex);
} else {
// No more RNGs to try
emit RNGFailure();
}
}
return randomNumber;
// If the timeout is exceeded, try next RNG
if (block.timestamp > requestTimestamp + fallbackTimeoutSeconds) {
uint256 nextIndex = currentRngIndex + 1;
// If we have another RNG to try, switch to it and request again
if (nextIndex < rngs.length) {
emit RNGFallback(currentRngIndex, nextIndex);
_requestRandomness(nextIndex); // This will update requestTimestamp
} else {
// No more RNGs to try
emit RNGFailure();
}
}
return randomNumber;
🤖 Prompt for AI Agents
In contracts/src/rng/RNGWithFallback.sol around lines 94 to 108, the timeout
logic for fallback RNG requests does not reset the requestTimestamp after
switching to a fallback RNG, causing subsequent timeout checks to use the
original request time. To fix this, update the code to reset requestTimestamp to
the current block.timestamp immediately after switching to the fallback RNG and
making the new request, ensuring timeout checks are based on the new request
time.

Comment on lines +147 to +158
function removeLastRngFallback() external onlyByGovernor {
require(rngs.length > 1, "No fallback RNG");

// If the removed RNG is the current one, reset the fallback index
if (currentRngIndex > rngs.length - 2) {
currentRngIndex = DEFAULT_RNG;
}

IRNG removedRng = rngs[rngs.length - 1];
rngs.pop();
emit RNGFallbackRemoved(address(removedRng));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle active requests when removing the current RNG.

If the currently active RNG is removed while a request is in progress, the contract should reset the request state to avoid inconsistencies.

     // If the removed RNG is the current one, reset the fallback index
     if (currentRngIndex > rngs.length - 2) {
+        // If we're removing the current RNG and there's an active request, reset state
+        if (isRequesting) {
+            isRequesting = false;
+            requestTimestamp = 0;
+        }
         currentRngIndex = DEFAULT_RNG;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function removeLastRngFallback() external onlyByGovernor {
require(rngs.length > 1, "No fallback RNG");
// If the removed RNG is the current one, reset the fallback index
if (currentRngIndex > rngs.length - 2) {
currentRngIndex = DEFAULT_RNG;
}
IRNG removedRng = rngs[rngs.length - 1];
rngs.pop();
emit RNGFallbackRemoved(address(removedRng));
}
function removeLastRngFallback() external onlyByGovernor {
require(rngs.length > 1, "No fallback RNG");
// If the removed RNG is the current one, reset the fallback index
if (currentRngIndex > rngs.length - 2) {
// If we're removing the current RNG and there's an active request, reset state
if (isRequesting) {
isRequesting = false;
requestTimestamp = 0;
}
currentRngIndex = DEFAULT_RNG;
}
IRNG removedRng = rngs[rngs.length - 1];
rngs.pop();
emit RNGFallbackRemoved(address(removedRng));
}
🤖 Prompt for AI Agents
In contracts/src/rng/RNGWithFallback.sol around lines 147 to 158, the function
removeLastRngFallback does not handle the case where the current RNG is removed
while a request is active. To fix this, add logic to check if there is an active
request when removing the current RNG and reset the request state accordingly to
prevent inconsistencies. This may involve clearing or resetting any variables
that track the request status before or after updating the currentRngIndex and
removing the RNG.

@jaybuidl jaybuidl mentioned this pull request Jul 24, 2025
@jaybuidl
Copy link
Member Author

Superseded by #2054

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RNG fallback mechanism
1 participant