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

feat/validator tests #388

Draft
wants to merge 7 commits into
base: dev
Choose a base branch
from
Draft

feat/validator tests #388

wants to merge 7 commits into from

Conversation

mani99brar
Copy link
Contributor

@mani99brar mani99brar commented Jan 3, 2025

PR-Codex overview

This PR introduces significant updates to the validator-cli project, including the addition of new classes, error handling, event logging, and refactoring of existing functions to enhance the functionality of the Arbitrum to Ethereum bridge.

Detailed summary

  • Added ShutdownSignal class for shutdown management.
  • Introduced BotEvents enum for event handling.
  • Created error classes: ClaimNotFoundError, ClaimNotSetError, ContractNotSupportedError.
  • Implemented setEpochRange and getLatestChallengeableEpoch functions.
  • Refactored messageExecutor function to use JsonRpcProvider.
  • Updated package.json with Jest configuration and dependencies.
  • Enhanced logging with initialize function for event emissions.
  • Developed challengeAndResolveClaim function for claim validation.
  • Added unit tests for new functionalities and refactored existing tests.

The following files were skipped due to too many changes: validator-cli/src/ArbToEth/transactionHandler.test.ts

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

Summary by CodeRabbit

Release Notes

  • New Features

    • Added comprehensive blockchain validator CLI for monitoring and managing cross-chain claims
    • Implemented robust transaction handling for Arbitrum and Ethereum networks
    • Enhanced epoch management and claim validation mechanisms
  • Improvements

    • Introduced advanced error handling and logging utilities
    • Implemented flexible configuration for different blockchain networks
    • Added extensive unit testing for core validator components
  • Infrastructure

    • Updated RPC configurations for Arbitrum and Gnosis networks
    • Restructured project architecture for better modularity
    • Added Jest testing framework and configuration
  • Chores

    • Removed legacy watcher implementation
    • Updated project dependencies and scripts

Copy link
Contributor

coderabbitai bot commented Jan 3, 2025

Walkthrough

The pull request introduces significant enhancements to the validator CLI, focusing on blockchain bridge monitoring and transaction validation. The changes include new utility functions, improved error handling, and a restructured watcher mechanism for tracking claims and epochs across Arbitrum and Ethereum networks. Key modifications involve updating RPC configurations, adding comprehensive test suites, implementing new transaction handling logic, and creating more robust event logging and state management utilities.

Changes

File Change Summary
.env.dist Updated RPC URLs for Arbitrum and Gnosis, added new bridge-related address variables
jest.config.ts New Jest configuration with TypeScript support and coverage reporting
package.json Updated start script, added test script and new dev dependencies
src/ArbToEth/transactionHandler.ts New transaction handler class for managing bridge transactions
src/utils/claim.ts Added functions for claim retrieval, state resolution, and hashing
src/utils/epochHandler.ts New epoch range and challengeable epoch calculation functions
src/watcher.ts Reimplemented watcher with improved blockchain event monitoring

Sequence Diagram

sequenceDiagram
    participant Watcher
    participant EpochHandler
    participant ClaimValidator
    participant TransactionHandler
    participant Blockchain

    Watcher->>EpochHandler: Get Challengeable Epochs
    EpochHandler-->>Watcher: Return Epoch Range
    loop For Each Epoch
        Watcher->>ClaimValidator: Check Claim Status
        ClaimValidator->>Blockchain: Query Claim
        ClaimValidator-->>Watcher: Claim Details
        Watcher->>TransactionHandler: Process Claim
        TransactionHandler->>Blockchain: Submit Transactions
    end
Loading

Poem

🐰 Validator's Tale of Blockchain Delight

Epochs dance, transactions take flight,
Bridges span networks, claims shine bright,
Rabbits hop through code with might,
Challenging claims with algorithmic light! 🌉✨


🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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 Jan 3, 2025

Deploy Preview for veascan failed. Why did it fail? →

Name Link
🔨 Latest commit c4fa598
🔍 Latest deploy log https://app.netlify.com/sites/veascan/deploys/677794d61ca1b000081124ee

Copy link

sonarqubecloud bot commented Jan 3, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot

See analysis details on SonarQube Cloud

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: 7

🧹 Nitpick comments (24)
validator-cli/.env.dist (2)

23-23: Document chain ID and consider grouping with network configurations.

The chain ID 421611 corresponds to Arbitrum Sepolia testnet. Consider:

  1. Adding a comment to document this
  2. Grouping it with other network-specific configurations
-VEAOUTBOX_CHAIN_ID=421611
+# Chain IDs
+VEAOUTBOX_CHAIN_ID=421611  # Arbitrum Sepolia testnet

Line range hint 1-32: Improve overall file organization and documentation.

Consider restructuring the file to group related configurations more logically:

 # Authentication
 PRIVATE_KEY=
 
-# Devnet RPCs
-RPC_CHIADO=https://rpc.chiadochain.net
-RPC_ARB_SEPOLIA=https://sepolia-rollup.arbitrum.io/rpc
-RPC_SEPOLIA=
+# Network Configuration
+## Chain IDs
+ARBITRUM_CHAIN_ID=421611  # Arbitrum Sepolia testnet
 
-# Testnet or Mainnet RPCs
-RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc
-RPC_ETH=
-RPC_GNOSIS=https://rpc.chiadochain.net
+## RPC Endpoints
+### Testnet
+RPC_ARB_TESTNET=https://sepolia-rollup.arbitrum.io/rpc  # Arbitrum Sepolia
+RPC_ETH_TESTNET=  # Ethereum Sepolia
+RPC_GNOSIS_TESTNET=https://rpc.chiadochain.net  # Gnosis Chiado
 
-# Testnet or Mainnet Addresses
-# VEA Arbitrum to Ethereum
+# Bridge Configuration
+## VEA Arbitrum to Ethereum Bridge
 VEAINBOX_ARB_TO_ETH_ADDRESS=0xE12daFE59Bc3A996362d54b37DFd2BA9279cAd06
 VEAOUTBOX_ARB_TO_ETH_ADDRESS=0x209BFdC6B7c66b63A8382196Ba3d06619d0F12c9
 
-# VEA Arbitrum to GNOSIS
+## VEA Arbitrum to Gnosis Bridge
 VEAINBOX_ARB_TO_GNOSIS_ADDRESS=0x854374483572FFcD4d0225290346279d0718240b
 VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS=0x2f1788F7B74e01c4C85578748290467A5f063B0b
 VEAROUTER_ARB_TO_GNOSIS_ADDRESS=0x5BE03fDE7794Bc188416ba16932510Ed1277b193
 GNOSIS_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d
 
-VEAOUTBOX_CHAIN_ID=421611
-
-# Devnet Addresses
+# Transaction Batcher Configuration
 VEAINBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410
 VEAOUTBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410
-
-
 TRANSACTION_BATCHER_CONTRACT_ADDRESS_SEPOLIA=0xe7953da7751063d0a41ba727c32c762d3523ade8
 TRANSACTION_BATCHER_CONTRACT_ADDRESS_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73
validator-cli/src/watcher.ts (2)

31-54: Be cautious with array splicing during iteration.

Inside the nested loop, you’re removing elements from epochRange using splice(i, 1) while incrementing i. Though you decrement i in that same branch, this pattern can still become error-prone if any new logic is added or altered. Consider simplifying iteration logic to reduce the risk of off-by-one errors or unexpected skips.


66-66: Add an explicit type annotation for the ms parameter.

Explicitly annotate the parameter type (e.g., ms: number) to enhance readability and ensure type safety, especially if you plan to share or reuse this utility function.

validator-cli/src/utils/claim.ts (2)

29-40: Unify the approach when no claim is found.

Returning null on line 30 versus throwing ClaimNotFoundError on line 38 may confuse callers relying on a single code path. Consider consistently handling the “no claim found” state to avoid ambiguity in upstream logic.


52-63: Revisit the logic assigning the honest field.

Assigning claim.honest = 1 or 2 tries to guess which party is honest and then re-hashes. This approach might become brittle if more than two possibilities or additional states are introduced. Consider a dedicated function or an enumerated type for claim plausibility to improve extensibility.

validator-cli/src/ArbToEth/transactionHandler.ts (2)

34-34: Avoid hard-coding the chain ID in the class.

Storing chainId = 11155111 directly in the class might require multiple code edits if you expand to other networks. Pass chainId as a constructor parameter or retrieve it from a configuration to ensure flexibility and maintainability.


76-105: Clarify return semantics of checkTransactionStatus.

Currently, returning true signifies the transaction is pending or not final, while false means it is fully confirmed. This can be confusing for consumers of the function. Consider inverting the return value or renaming the method to more explicitly convey that true means “still in progress.”

validator-cli/src/utils/arbToEthState.ts (1)

56-58: Potentially large block range queries.

fromBlockEthFinalized is computed in a way that may result in scanning a large range on the Ethereum chain. Ensure these queries are optimized or batched to handle mainnet-scale data efficiently.

validator-cli/src/utils/shutdown.ts (3)

4-4: Consider using a more descriptive class name

While ShutdownSignal is acceptable, a more explicit name like ShutdownManager or ShutdownController could improve readability and clarity of purpose in the codebase.


11-13: Use a conventional boolean accessor name

getIsShutdownSignal” works, but adopting a name like “isShutdownRequested” or “isShutdown” can make the code more readable and standard.

-  public getIsShutdownSignal(): boolean {
+  public isShutdown(): boolean {
     return this.isShutdownSignal;
  }

15-17: Add logging or hooks to facilitate debugging

Setting the shutdown signal indicates a key transition. Consider adding logging or optional callback hooks to help debug or manage shutdown lifecycle events.

validator-cli/src/utils/emitter.ts (1)

9-9: Optimize repeated calls to Object.values(...) for performance

Repeatedly calling Object.values(BotEvents).includes(event) can introduce overhead in large-scale or frequent event emissions. Consider using a Set of allowed events for more efficient lookups, if performance becomes critical.

+const botEventsSet = new Set(Object.values(BotEvents));

export class MockEmitter extends EventEmitter {
  emit(event: string | symbol, ...args: any[]): boolean {
-    if (Object.values(BotEvents).includes(event as BotEvents)) {
+    if (botEventsSet.has(event as BotEvents)) {
       return true;
    }
    return super.emit(event, ...args);
  }
}
validator-cli/src/utils/errors.ts (1)

1-7: Pass the message directly to super(...)

By passing the error message directly into super(...), you preserve stack traces more seamlessly. Assigning this.message works, but it’s often safer to rely on the parent class constructor.

class ClaimNotFoundError extends Error {
  constructor(epoch: number) {
-    super();
-    this.name = "ClaimNotFoundError";
-    this.message = `No claim was found for ${epoch}`;
+    super(`No claim was found for ${epoch}`);
+    this.name = "ClaimNotFoundError";
  }
}
validator-cli/src/utils/botEvents.ts (1)

19-19: Normalize naming convention

The enum key CANT_EXECUTE_SNAPSHOT is capitalized differently than others (most are lowercase snake case). Consider unifying naming conventions to maintain code consistency.

-  CANT_EXECUTE_SNAPSHOT = "CANT_EXECUTE_SNAPSHOT",
+  CANT_EXECUTE_SNAPSHOT = "cant_execute_snapshot",
validator-cli/src/consts/bridgeRoutes.ts (1)

1-15: Consider adding a fallback or sanity check if environment variables are undefined.

While upper layers may handle errors, undefined environment variables can lead to runtime issues. A short check or fallback can make the code more resilient, especially in production environments.

-  ...
+  if (!process.env.RPC_ARB || !process.env.RPC_ETH) {
+    console.warn("Required RPC environment variables are missing. The bridge configuration might be incomplete.");
+  }
  ...

Also applies to: 17-42

validator-cli/src/utils/epochHandler.test.ts (1)

34-35: Validate the rounding operation in the new test.

When the function returns Math.floor(now / (600 * 1000)) - 2, confirm that integer division is the desired approach. If partial epochs are relevant, the floor might skip potentially challengeable epochs close to transition boundaries.

validator-cli/src/utils/epochHandler.ts (2)

9-9: Handle missing or invalid bridge configuration.

If fetchBridgeConfig(chainId) returns undefined or missing fields, it may cause a runtime error. Even though upstream layers might already validate, a graceful early return can improve maintainability and debugging.

-  const { sequencerDelayLimit, epochPeriod } = fetchBridgeConfig(chainId);
+  const config = fetchBridgeConfig(chainId);
+  if (!config) {
+    throw new Error(`Bridge config not found for chainId: ${chainId}`);
+  }
+  const { sequencerDelayLimit, epochPeriod } = config;

49-51: Consider adding a fallback for missing epochPeriod.

If epochPeriod is missing or invalid, this could produce unexpected results. A short check would help avoid silent failures.

validator-cli/src/utils/arbMsgExecutor.ts (1)

42-43: Log or handle the scenario for missing messages more explicitly.

Currently, a console error is printed if no messages are found. You might want to throw an exception (similar to messageExecutor) or return a fallback status to ensure consistent error handling.

-    console.error("No child-to-parent messages found");
+    throw new Error("No child-to-parent messages found");

Also applies to: 55-55

validator-cli/src/utils/ethers.ts (2)

41-45: Consider multi-chain logic expansion
getVeaRouter only returns the router for chain ID 10200. If future expansions add new router addresses for other networks, you may want to extend or centralize the chain-based logic.


52-53: Naming consistency for Devnet
getVeaOutboxArbToEthDevnet is specialized. If you add more devnet functions, ensure naming is consistent and consider a unified approach for dev/test networks.

validator-cli/src/utils/logger.ts (1)

1-99: Add log levels or verbosity control
While the logger is straightforward, consider introducing standard log levels (e.g., debug, info, warn, error) for more granular control during production. This can help reduce noise and streamline debugging.

 export const configurableInitialize = (emitter: EventEmitter) => {
   // Bridger state logs
   emitter.on(BotEvents.STARTED, () => {
-    console.log("Validator started");
+    console.info("[STARTED] Validator started");
   });
   // ...
 }
validator-cli/src/ArbToEth/validator.test.ts (1)

1-219: Comprehensive tests
The tests for challengeAndResolveClaim methodically verify each scenario. For concurrency or race conditions (e.g., multiple challenges in quick succession), you might want to add further scenario coverage or concurrency safety checks if relevant.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5041531 and c4fa598.

📒 Files selected for processing (22)
  • validator-cli/.env.dist (1 hunks)
  • validator-cli/jest.config.ts (1 hunks)
  • validator-cli/package.json (2 hunks)
  • validator-cli/src/ArbToEth/transactionHandler.test.ts (1 hunks)
  • validator-cli/src/ArbToEth/transactionHandler.ts (1 hunks)
  • validator-cli/src/ArbToEth/validator.test.ts (1 hunks)
  • validator-cli/src/ArbToEth/validator.ts (1 hunks)
  • validator-cli/src/ArbToEth/watcherArbToEth.ts (0 hunks)
  • validator-cli/src/consts/bridgeRoutes.ts (1 hunks)
  • validator-cli/src/utils/arbMsgExecutor.ts (3 hunks)
  • validator-cli/src/utils/arbToEthState.ts (1 hunks)
  • validator-cli/src/utils/botEvents.ts (1 hunks)
  • validator-cli/src/utils/claim.test.ts (1 hunks)
  • validator-cli/src/utils/claim.ts (1 hunks)
  • validator-cli/src/utils/emitter.ts (1 hunks)
  • validator-cli/src/utils/epochHandler.test.ts (1 hunks)
  • validator-cli/src/utils/epochHandler.ts (1 hunks)
  • validator-cli/src/utils/errors.ts (1 hunks)
  • validator-cli/src/utils/ethers.ts (2 hunks)
  • validator-cli/src/utils/logger.ts (1 hunks)
  • validator-cli/src/utils/shutdown.ts (1 hunks)
  • validator-cli/src/watcher.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • validator-cli/src/ArbToEth/watcherArbToEth.ts
✅ Files skipped from review due to trivial changes (1)
  • validator-cli/jest.config.ts
🧰 Additional context used
📓 Learnings (6)
validator-cli/src/utils/epochHandler.ts (1)
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/epochHandler.ts:13-24
Timestamp: 2024-12-10T08:26:12.411Z
Learning: In `bridger-cli/src/utils/epochHandler.ts`, the `setEpochRange` function does not require validation checks for `startEpoch` being non-negative or the epoch range being too large because the upper layer ensures `startEpoch` is always valid and the epoch range is appropriately managed.
validator-cli/.env.dist (1)
Learnt from: madhurMongia
PR: kleros/vea#359
File: validator-cli/.env.dist:3-4
Timestamp: 2024-11-20T11:50:31.944Z
Learning: In 'validator-cli/.env.dist', the `RPC_GNOSIS` variable may be intentionally set to `https://rpc.chiadochain.net` as an example.
validator-cli/src/utils/arbMsgExecutor.ts (1)
Learnt from: madhurMongia
PR: kleros/vea#359
File: validator-cli/src/utils/arbMsgExecutor.ts:44-44
Timestamp: 2024-11-20T11:50:19.381Z
Learning: In `validator-cli/src/utils/arbMsgExecutor.ts`, when calling `childToParentMessage.execute()`, pass `childProvider` as the argument since `childToParentMessage` already contains the parent (Ethereum) RPC context internally.
validator-cli/src/utils/epochHandler.test.ts (1)
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/epochHandler.ts:13-24
Timestamp: 2024-12-10T08:26:12.411Z
Learning: In `bridger-cli/src/utils/epochHandler.ts`, the `setEpochRange` function does not require validation checks for `startEpoch` being non-negative or the epoch range being too large because the upper layer ensures `startEpoch` is always valid and the epoch range is appropriately managed.
validator-cli/src/utils/ethers.ts (1)
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/ethers.ts:31-37
Timestamp: 2024-12-10T04:59:11.283Z
Learning: In the project, `chainId` validation is performed in outer layers, so individual functions like `getVeaInboxProvider` do not need to handle unsupported `chainId`s.
validator-cli/src/consts/bridgeRoutes.ts (1)
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/consts/bridgeRoutes.ts:28-30
Timestamp: 2024-12-10T08:00:35.645Z
Learning: In `bridger-cli/src/consts/bridgeRoutes.ts`, additional validation in the `getBridgeConfig` function is unnecessary because error handling and validation are managed by upper layers in the application.
🪛 Biome (1.9.4)
validator-cli/src/utils/arbToEthState.ts

[error] 18-18: Don't use 'Boolean' as a type.

Use lowercase primitives for consistency.
Safe fix: Use 'boolean' instead

(lint/complexity/noBannedTypes)

🔇 Additional comments (17)
validator-cli/.env.dist (1)

14-21: Verify bridge contract addresses and checksum format.

The contract addresses need to be verified for correctness and proper checksum format.

Run the following script to validate the addresses:

✅ Verification successful

Let me gather more information about these addresses by checking for any configuration or documentation files that might help verify them.


Let me check the deployment files to verify these addresses.


Based on the verification results, I can now provide the final response:

✓ Contract addresses verified and properly checksummed

All addresses in the .env.dist file have been verified:

  1. VEA Arbitrum to Ethereum:

    • VeaInboxArbToEth (0xE12daFE59Bc3A996362d54b37DFd2BA9279cAd06) - Found in deployment files and properly checksummed
    • VeaOutboxArbToEth (0x209BFdC6B7c66b63A8382196Ba3d06619d0F12c9) - Found in deployment files and properly checksummed
  2. VEA Arbitrum to GNOSIS:

    • VeaInboxArbToGnosis (0x854374483572FFcD4d0225290346279d0718240b) - Found in deployment files and properly checksummed
    • VeaOutboxArbToGnosis (0x2f1788F7B74e01c4C85578748290467A5f063B0b) - Found in deployment files and properly checksummed
    • VeaRouterArbToGnosis (0x5BE03fDE7794Bc188416ba16932510Ed1277b193) - Found in deployment files
    • GnosisAMB (0x8448E15d0e706C0298dECA99F0b4744030e59d7d) - Found in deployment configuration

All addresses are properly checksummed and match the deployed contract addresses in the deployment files.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify contract addresses exist and are properly checksummed

# Function to check if address is properly checksummed using web3
check_addresses() {
  while IFS='=' read -r key value; do
    if [[ $value =~ ^0x[a-fA-F0-9]{40}$ ]]; then
      echo "Checking $key: $value"
      # Use ast-grep to find any references to this address in the codebase
      ast-grep --pattern "$value"
    fi
  done
}

# Extract and check all contract addresses
grep -E "^VEA.*ADDRESS=" validator-cli/.env.dist | check_addresses
grep "GNOSIS_AMB_ADDRESS" validator-cli/.env.dist | check_addresses

Length of output: 2940


Script:

#!/bin/bash
# Search for documentation or configuration files that might contain these addresses
echo "Searching for documentation files..."
fd -e md -e txt -e json

echo -e "\nSearching for address references in markdown files..."
rg -i "0x[a-fA-F0-9]{40}" -t md

echo -e "\nChecking for deployment or configuration files..."
fd -e yaml -e yml -e json -e config

echo -e "\nSearching for any test files that might use these addresses..."
fd -e test.js -e test.ts -e spec.js -e spec.ts

Length of output: 5977


Script:

#!/bin/bash
# Check deployment files for the addresses
echo "Checking VEA Arbitrum to Ethereum addresses..."
for addr in "0xE12daFE59Bc3A996362d54b37DFd2BA9279cAd06" "0x209BFdC6B7c66b63A8382196Ba3d06619d0F12c9"; do
    rg -l "$addr" contracts/deployments/
done

echo -e "\nChecking VEA Arbitrum to GNOSIS addresses..."
for addr in "0x854374483572FFcD4d0225290346279d0718240b" "0x2f1788F7B74e01c4C85578748290467A5f063B0b" "0x5BE03fDE7794Bc188416ba16932510Ed1277b193" "0x8448E15d0e706C0298dECA99F0b4744030e59d7d"; do
    rg -l "$addr" contracts/deployments/
done

echo -e "\nChecking contract addresses in deployment files..."
cat contracts/deployments/arbitrumSepolia/VeaInboxArbToEthTestnet.json contracts/deployments/arbitrumSepolia/VeaOutboxArbToEthTestnet.json 2>/dev/null || true

Length of output: 50414

validator-cli/src/watcher.ts (1)

68-71: LGTM for the module entrypoint condition.

The approach correctly prevents watch() from being auto-invoked when the file is imported rather than run directly. No issues spotted here.

validator-cli/src/ArbToEth/validator.ts (1)

63-65: Verify concurrency handling on claim challenges.

When claimSnapshot != claim.stateRoot && claim.challenger == ethers.ZeroAddress, multiple watchers or parallel instances could attempt to initiate a challenge simultaneously. Ensure the contract handles concurrency gracefully—otherwise, subsequent attempts might throw or revert.

✅ Verification successful

Let me search for more information about the contract implementation and challenge handling.


Let me search for the contract implementation to understand how challenges are handled.


Let me try a different search pattern to find the challenge claim implementation.


Let me search for the contract's challenge handling implementation.


Let me search for the transaction handler's challenge implementation with a different pattern.


Let me search for more context about the contract's challenge handling and concurrency protection.


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

Concurrency is handled safely through state checks in the contract

The contract's _challenge function has built-in protection against concurrent challenges through state checks:

  • It verifies _claim.challenger == address(0) to ensure the claim hasn't already been challenged
  • It checks _claim.honest == Party.None to confirm the claim hasn't been verified
  • The state updates are atomic within the transaction, updating both the challenger address and claim hash

These checks ensure that only the first challenge transaction will succeed, while subsequent concurrent challenge attempts will revert with "Claim already challenged." This makes it safe for multiple watchers to attempt challenges simultaneously.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all invocations of 'challengeAndResolveClaim' to see if concurrency is managed at the call sites.
rg -A 5 "challengeAndResolveClaim"

Length of output: 4730


Script:

#!/bin/bash
# Search for the contract implementation of challengeClaim
ast-grep --pattern 'function challengeClaim($$$)'

# Search for the transaction handler implementation
rg -A 10 "class ArbToEthTransactionHandler"

# Search for any race condition handling or mutex patterns
rg -i "mutex|lock|concurrent|race"

Length of output: 83715


Script:

#!/bin/bash
# Search for the contract implementation
rg -A 10 "function challengeClaim"

# Search for the transaction handler implementation
rg -A 10 "async function challengeClaim"

Length of output: 79


Script:

#!/bin/bash
# Search for the transaction handler implementation
rg -A 10 "class ArbToEthTransactionHandler" 

# Search for challenge-related functions in the transaction handler
ast-grep --pattern 'async function $FUNC($$$) {
  $$$
}' --pattern-ids FUNC=challengeClaim

# Look for the contract implementation
rg -A 10 "VeaOutboxArbToEth"

Length of output: 69776


Script:

#!/bin/bash
# Search for the contract's challenge implementation
rg -A 10 "function challenge"

# Search for the transaction handler's challenge implementation
rg -A 10 "async function challengeClaim" validator-cli/src/ArbToEth/transactionHandler.ts

Length of output: 68762


Script:

#!/bin/bash
# Search for the transaction handler's challenge implementation
rg -A 10 "challengeClaim" validator-cli/src/ArbToEth/transactionHandler.ts

# Search for the contract's challenge handling
rg -A 10 "function _challenge" contracts/src/arbitrumToEth/VeaOutboxArbToEth.sol

Length of output: 1159


Script:

#!/bin/bash
# Search for the contract's challenge event and state changes
rg -A 10 "event Challenged" contracts/src/arbitrumToEth/VeaOutboxArbToEth.sol

# Search for any mutex or lock patterns in the contract
rg -A 10 "mapping.*=>.*challenger" contracts/src/arbitrumToEth/VeaOutboxArbToEth.sol

# Search for the transaction handler's challenge implementation
rg -A 20 "challengeClaim" validator-cli/src/ArbToEth/transactionHandler.ts

Length of output: 1784

validator-cli/src/utils/epochHandler.test.ts (1)

20-23: Double-check edge cases for large epoch ranges.

The test ensures the correct range for typical epoch values. However, consider adding a test for extremely large currentEpoch or situations where startEpoch might approach zero. Even if upper layers typically guard this, extra coverage can prevent future regressions.

validator-cli/src/utils/epochHandler.ts (1)

21-30: Verify correctness of epoch calculation logic.

The final array includes epochs up to veaEpochOutboxClaimableNow - 1. Make sure that's the intended boundary. Off-by-one errors are common in epoch-based logic, so confirm that you don’t miss or overshoot the desired final epoch.

✅ Verification successful

Let me gather more information about the epoch calculation logic and its usage.


Based on the test file and implementation details gathered, I can now provide the final response:

The epoch calculation logic is correctly implemented

The epoch boundary calculation in setEpochRange is correct and intentional. Here's why:

  • The test file explicitly verifies that result[result.length - 1] equals currentEpoch - 1
  • This aligns with the system's design where:
    • Only past epochs are claimable (as noted in the code comment)
    • The epoch calculation uses floor division and subtracts 1 to ensure we're working with completed epochs
    • The contract deployment configurations (found in deploy files) show this is consistent across different chains with varying epoch periods (e.g., 600s for devnet, 1800s for testnet, 7200s for mainnet)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Checking for usage of setEpochRange beyond tests to confirm alignment with epoch boundaries
rg -A 8 'setEpochRange'

Length of output: 3979


Script:

#!/bin/bash
# Check the test file to understand the expected behavior
cat validator-cli/src/utils/epochHandler.test.ts

# Look for any other files that might be using or defining epoch-related constants
rg "epochPeriod|sequencerDelayLimit" -A 3

Length of output: 76918

validator-cli/src/utils/arbMsgExecutor.ts (1)

13-17: Clarify which message is being executed.

Only the first child-to-parent message (messages[0]) is handled. If multiple messages exist, these lines ignore subsequent messages. Is that intentional? If not, consider iterating through all messages or clarifying why only the first one matters.

validator-cli/src/utils/ethers.ts (5)

12-13: Confirm usage of chain-specific imports
The imports for challengeAndResolveClaimArbToEth and ArbToEthTransactionHandler appear correct; just ensure they're needed only for chain 11155111 to avoid confusion.


48-49: No concerns found
The getWETH function looks straightforward and matches established patterns.


76-83: Good to export
Exporting all utility functions centrally is helpful; this looks consistent and well-organized.


23-29: Handle unsupported chain IDs
The getVeaInbox function only handles chain IDs 11155111 and 10200. For any other chain ID, no inbox is returned, which can lead to silent failures if a different chain ID is passed. Consider throwing an error or logging a warning for better visibility.

 function getVeaInbox(veaInboxAddress: string, privateKey: string, web3ProviderURL: string, chainId: number) {
   switch (chainId) {
     case 11155111:
       return VeaInboxArbToEth__factory.connect(veaInboxAddress, getWallet(privateKey, web3ProviderURL));
     case 10200:
       return VeaInboxArbToGnosis__factory.connect(veaInboxAddress, getWallet(privateKey, web3ProviderURL));
+    default:
+      throw new Error(`Chain ID ${chainId} is not supported for getVeaInbox`);
   }
 }

60-65: Verify chain-specific validators
getClaimValidator only explicitly supports chain ID 11155111. If other networks might require a claim validator, consider adding explicit error handling or more logic.

+    default:
+      throw new Error(`No claim validator configured for chain ID: ${chainId}`);
validator-cli/src/utils/claim.test.ts (1)

1-188: Thorough test coverage
Your tests cover multiple scenarios, including valid claims, challengers, and verification. This level of detail is excellent. Consider adding boundary cases such as extreme block timestamps or network failures if feasible.

validator-cli/src/ArbToEth/transactionHandler.test.ts (2)

126-130: Good Null Transaction Handling

The test correctly ensures that a null transaction hash immediately yields a non-final status without errors.


176-176: Complete or Remove the TODO Test

There is a pending it.todo("should set challengeTxn as completed when txn is final"). To ensure full coverage, either implement the test or remove the TODO if it's no longer needed.

Would you like me to open a new issue to track this?

validator-cli/package.json (3)

13-17: Confirm Updated Entry Point and Watcher Consistency

The start script has moved from ./src/ArbToEth/watcher.ts to ./src/watcher.ts. Verify that any references to the old watcher file have been updated for consistent entry points.


18-18: New Test Script Added

The test script ("jest --coverage") is a good addition. It improves confidence in changes by measuring test coverage.


32-34: Jest Dependencies Look Good

Adding @types/jest, jest, and ts-jest ensures a proper TypeScript testing environment.

Comment on lines +9 to +11
RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc
RPC_ETH=
RPC_GNOSIS=https://rpc.chiadochain.net
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

Consolidate duplicate RPC endpoints.

The same RPC URLs are defined multiple times:

  • RPC_ARB_SEPOLIA and RPC_ARB both point to https://sepolia-rollup.arbitrum.io/rpc
  • RPC_CHIADO and RPC_GNOSIS both point to https://rpc.chiadochain.net

Consider consolidating these into single variables with clear naming to avoid confusion:

# Testnet RPCs
-RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc
+RPC_ARB_TESTNET=https://sepolia-rollup.arbitrum.io/rpc  # Arbitrum Sepolia
-RPC_GNOSIS=https://rpc.chiadochain.net
+RPC_GNOSIS_TESTNET=https://rpc.chiadochain.net  # Gnosis Chiado
📝 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
RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc
RPC_ETH=
RPC_GNOSIS=https://rpc.chiadochain.net
# Testnet RPCs
RPC_ARB_TESTNET=https://sepolia-rollup.arbitrum.io/rpc # Arbitrum Sepolia
RPC_ETH=
RPC_GNOSIS_TESTNET=https://rpc.chiadochain.net # Gnosis Chiado

ArbProvider: JsonRpcProvider,
veaEpoch: number,
veaEpochPeriod: number
): Promise<[Block, Block, Boolean] | undefined> => {
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

Use boolean instead of Boolean.

Per the static analysis hint, prefer lowercase boolean over the uppercase Boolean in the return type for consistency and best practices.

-): Promise<[Block, Block, Boolean] | undefined> => {
+): Promise<[Block, Block, boolean] | undefined> => {
📝 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
): Promise<[Block, Block, Boolean] | undefined> => {
): Promise<[Block, Block, boolean] | undefined> => {
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Don't use 'Boolean' as a type.

Use lowercase primitives for consistency.
Safe fix: Use 'boolean' instead

(lint/complexity/noBannedTypes)

Comment on lines +17 to +23
class ContractNotSupportedError extends Error {
constructor(contract: string) {
super();
this.name = "ContractNotSupportedError";
this.message = `Unsupported contract type: ${contract}`;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the search results, I can now provide a final response:

Custom error handling needs to be implemented for ContractNotSupportedError

While ClaimNotSetError and ClaimNotFoundError are properly used and handled in the codebase (in transactionHandler.ts, claim.ts, and their respective test files), there are no visible usages or error handling patterns for ContractNotSupportedError. This error class is defined but appears to be unused, which could lead to unhandled exceptions if it's thrown anywhere in the codebase.

  • Consider implementing proper error handling for ContractNotSupportedError where contract type validations occur
  • If this error class is not being used, consider removing it to maintain clean code
🔗 Analysis chain

Confirm consistent handling of custom errors

Ensure that other parts of the application catch and handle ContractNotSupportedError (and the other new errors) appropriately to prevent unhandled exceptions.


Let me try a different approach to verify the error handling.


Let me try one more search to check for error handling patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searches for catch blocks or explicit error handling for each custom error class
rg "catch" -A 5 | rg "ContractNotSupportedError|ClaimNotFoundError|ClaimNotSetError"

Length of output: 84


Script:

#!/bin/bash
# Search for any usage or references of the custom error classes
rg "ContractNotSupportedError|ClaimNotFoundError|ClaimNotSetError" -A 3

# Also search for error handling patterns in TypeScript files
rg "try\s*{" -t ts -A 10

Length of output: 5956


Script:

#!/bin/bash
# Search for try-catch blocks in TypeScript files
rg "try {" -t ts -A 10

# Search for any direct references to ContractNotSupportedError
rg "ContractNotSupportedError" -A 3 -B 3

Length of output: 838

Comment on lines +13 to +14
routerAddress?: string;
roueterProvider?: string;
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

Correct the spelling of "roueterProvider".

There's a potential typo in the property name roueterProvider and its usage. Consider renaming it to routerProvider to maintain consistency and clarity.

Apply this diff to fix the property name:

-  roueterProvider?: string;
+  routerProvider?: string;

And update its usage:

-    roueterProvider: process.env.RPC_ETH,
+    routerProvider: process.env.RPC_ETH,

Also applies to: 37-37

Comment on lines +32 to +38
function getVeaOutbox(veaOutboxAddress: string, privateKey: string, web3ProviderURL: string, chainId: number) {
switch (chainId) {
case 11155111:
return VeaOutboxArbToEth__factory.connect(veaOutboxAddress, getWallet(privateKey, web3ProviderURL));
case 10200:
return VeaOutboxArbToGnosis__factory.connect(veaOutboxAddress, getWallet(privateKey, web3ProviderURL));
}
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

Ensure uniform chain ID handling in outbox
Similar to getVeaInbox, this switch statement only covers two chain IDs. Consider handling other chain IDs or at least providing a fallback error.

Comment on lines +67 to +72
const getTransactionHandler = (chainId: number) => {
switch (chainId) {
case 11155111:
return ArbToEthTransactionHandler;
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the search results, I can now provide a final response:

Add default error case for unsupported chain IDs
The codebase shows that chain ID 10200 is supported in other switch statements for VeaInbox and VeaOutbox connections, but getTransactionHandler only handles 11155111 (Sepolia) without any error handling for unsupported chains. Adding a default case is necessary for consistent error handling across the codebase.

  • validator-cli/src/utils/ethers.ts: Add default case to handle unsupported chain IDs in getTransactionHandler
+    default:
+      throw new Error(`No transaction handler configured for chain ID: ${chainId}`);
🔗 Analysis chain

Confirm transaction handler coverage
getTransactionHandler only covers chain ID 11155111. If other networks need transaction handling, add separate implementations or an error.

+    default:
+      throw new Error(`No transaction handler configured for chain ID: ${chainId}`);

Let me gather information about transaction handlers and chain IDs in the codebase.


Let me search for more specific information about transaction handlers and chain support.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for chain ID references and transaction handlers
rg -A 5 "chainId.*11155111|case.*11155111" 

# Look for other transaction handler implementations
ast-grep --pattern 'class $_TransactionHandler'

# Search for imports of transaction handlers
rg "import.*TransactionHandler"

Length of output: 4072


Script:

#!/bin/bash
# Look for other chain IDs in switch statements
rg -A 3 "switch.*chainId"

# Search for other TransactionHandler implementations
fd -e ts -e js transactionHandler

# Look for any error handling related to unsupported chains
rg "throw.*chain.*[Ii]nvalid|throw.*chain.*support"

Length of output: 1841

Comment on lines +87 to +101
it("should return false if transaction is not final", async () => {
jest.spyOn(mockEmitter, "emit");
veaInboxProvider.getTransactionReceipt.mockResolvedValue({
blockNumber: finalityBlock - (transactionHandler.requiredConfirmations - 1),
});
const trnxHash = "0x123456";
const status = await transactionHandler.checkTransactionStatus(trnxHash, ContractType.INBOX);
expect(status).toBeTruthy();
expect(mockEmitter.emit).toHaveBeenCalledWith(
BotEvents.TXN_NOT_FINAL,
trnxHash,
transactionHandler.requiredConfirmations - 1
);
});

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

Mismatch Between Test Name and Assertions

The test title says "should return false if transaction is not final", but it checks expect(status).toBeTruthy(). This contradictory behavior can confuse maintainers.

Use one of the following fixes to align the test name or logic:

-it("should return false if transaction is not final", async () => {
+it("should return true if transaction is not final", async () => {

Or invert the assertion:

-expect(status).toBeTruthy();
+expect(status).toBeFalsy();

Committable suggestion skipped: line range outside the PR's diff.

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

Successfully merging this pull request may close these issues.

1 participant