Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@mani99brar
Copy link
Contributor

@mani99brar mani99brar commented Oct 22, 2025

Added Hashi Executor in relayer-cli

When enabled the hashi executor in relayer-cli will run from the current hashiNonce, check for hashi message execution and execute messages in batches.
New files added:

  • hashi.ts has main hashi logic for execution and message verification functions
  • hashiHelpers inlcudes hashi abis, types and helper functions for message construction.
  • graphQuiers.ts refactored all the qraph queries in this file except for proof.ts

Files updated:

  • relayerHelpers.ts added hashiNonce(represents vea nonce for a msg) which is stored in the state file.
  • .env added new HASHI_EXECUTOR_ENABLED flag which will run the hashi executor
  • relayer.ts added the hashi executor

PR-Codex overview

This PR focuses on implementing and enabling a new Hashi Executor feature, which enhances message processing in the relayer-cli by managing message execution through the Hashi protocol, including updates to state management and logging.

Detailed summary

  • Added hashiNonce to the state management in devnet_11155111.json.
  • Introduced HASHI_EXECUTOR_ENABLED in .env.dist.
  • Expanded message-related constants in botEvents.ts for Hashi.
  • Updated message retrieval to include from in relay.test.ts.
  • Modified message structure to include msgSender in proof.ts.
  • Created HashiMessage interface and related types in hashiTypes.ts.
  • Enhanced logging for Hashi execution in logger.ts.
  • Updated state handling to return hashiNonce in relayerHelpers.ts.
  • Adjusted updateStateFile to save hashiNonce.
  • Added new methods in hashiHelpers for message hashing and execution.
  • Implemented runHashiExecutor to process messages via Hashi.
  • Updated relay functions to accommodate new message parameters.
  • Added tests for Hashi message execution logic in hashi.test.ts.

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

Summary by CodeRabbit

  • New Features

    • Optional Hashi executor for batched cross-chain message execution with progress events and per-bridge executor routing
  • Bug Fixes

    • Fixed inbox parsing and included message-sender in relay/proof payloads
  • Tests

    • Added comprehensive tests covering Hashi execution and message handling
  • Chores

    • New env flag to enable Hashi executor; state now persists a separate Hashi nonce and sample state added

@netlify
Copy link

netlify bot commented Oct 22, 2025

Deploy Preview for veascan ready!

Name Link
🔨 Latest commit 0e4ca91
🔍 Latest deploy log https://app.netlify.com/projects/veascan/deploys/68ff789e412ac400080471a9
😎 Deploy Preview https://deploy-preview-434--veascan.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

Integrates an optional Hashi executor and message-execution pipeline: adds Hashi configs/ABIs/types/utilities, GraphQL helpers, Hashi orchestration and tests, threads a separate hashiNonce through init/state, extends relay/proof to include msgSender/from, and adds related events/logging and state file.

Changes

Cohort / File(s) Summary
Env & State
relayer-cli/.env.dist, relayer-cli/state/devnet_11155111.json
Add HASHI_EXECUTOR_ENABLED=true (with comment/newline) and add state file including ts, nonce, and hashiNonce.
Bridge Config
relayer-cli/src/consts/bridgeRoutes.ts
Extend IBridge with rpcInbox, optional yahoAddress, yaruAddress, hashiAddress; populate values for specific chains.
Hashi Executor Core
relayer-cli/src/utils/hashi.ts, relayer-cli/src/utils/hashi.test.ts
New Hashi orchestration: runHashiExecutor, executeBatchOnHashi, toExecuteMessage; tests covering executable detection and batch execution flows with mocked dependencies.
Hashi ABIs, Utils & Types
relayer-cli/src/utils/hashiHelpers/abi.ts, relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts, relayer-cli/src/utils/hashiHelpers/hashiTypes.ts
Add ABIs (dispatch, messageDispatched, thresholdView, Yaru), message hashing/ABI-encoding helpers, ID/hex helpers, and Hashi message types + execution-status enum.
GraphQL Helpers
relayer-cli/src/utils/graphQueries.ts
New GraphQL helpers: getVeaMsgTrnx, getCount, getNonceFrom using RELAYER_SUBGRAPH.
Relayer Integration
relayer-cli/src/relayer.ts, relayer-cli/src/utils/relayerHelpers.ts, relayer-cli/src/utils/relayerHelpers.test.ts
Thread hashiNonce through initialize and updateStateFile (signatures/returns changed); optionally call runHashiExecutor when HASHI_EXECUTOR_ENABLED; tests updated to expect hashiNonce.
Relay & Proof
relayer-cli/src/utils/relay.ts, relayer-cli/src/utils/relay.test.ts, relayer-cli/src/utils/proof.ts
Replace in-file GraphQL helpers with graphQueries imports; propagate expanded message tuple [to, from, data] (adds from/msgSender) across relay callsites and tests; getProofAtCount now accepts inboxAddress and returns msgSender.id.
Events & Logging
relayer-cli/src/utils/botEvents.ts, relayer-cli/src/utils/logger.ts
Add BotEvents: EXECUTING_HASHI, HASHI_EXECUTED, HASHI_BATCH_TXN, HASHI_EXECUTION_FAILED; logger attaches listeners to log Hashi progress, batches and completion.
Subgraph Inbox Parsing
relayer-subgraph-inbox/src/vea-inbox.ts
Adjust offsets in handleMessageSent parsing: msgSender and data byte-slices changed (new start offsets), altering extracted msgSender and data values.

Sequence Diagram(s)

sequenceDiagram
    actor Relayer
    participant RH as relayerHelpers
    participant HE as HashiExecutor
    participant GQ as GraphQueries
    participant HM as toExecuteMessage
    participant SF as StateFile

    Relayer->>RH: initialize(chainId, ...) → {nonce, hashiNonce}
    RH-->>Relayer: {nonce, hashiNonce}

    alt HASHI_EXECUTOR_ENABLED
        Relayer->>HE: runHashiExecutor({chainId, network, nonce: hashiNonce, emitter})
        HE->>GQ: getNonceFrom / getVeaMsgTrnx / getCount
        GQ-->>HE: nonces, txHashes, counts
        loop per nonce range
            HE->>HM: toExecuteMessage(nonce, veaInbox, rpcInbox, ...)
            HM-->>HE: VeaNonceToHashiMessage | null
        end
        HE->>HE: executeBatchOnHashi(messages[])
        HE-->>Relayer: updated hashiNonce
    end

    Relayer->>SF: updateStateFile(..., nonce, hashiNonce)
    SF-->>Relayer: persisted
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Areas to focus review on:

  • hashi.ts: orchestration, dependency injection, error handling around batch execution and receipts.
  • hashiMsgUtils.ts: ABI encoding, hashing, endianness and checksum normalization.
  • relay/proof changes: ensure from/msgSender is correctly derived, encoded, and passed to contract calls.
  • relayerHelpers signature changes: callers/mocks/tests updated consistently (initialize/updateStateFile).
  • graphQueries vs previous inline queries: confirm query shapes and usage.

Possibly related PRs

  • Fix/message encoding #429 — Changes adding msgSender/from propagation through proof and relay flows; closely related to proof.ts and relay.ts edits.
  • Feat/relayer tests #395 — Overlapping relayer core changes (events, relayerHelpers signatures, logger); may touch same initialization/state behavior.
  • feat/arb-sep-to-sep-testnet #344 — Related bridge configuration and interface extensions in bridgeRoutes.ts and state/init handling.

Suggested labels

Type: Feature🗿, Package: Bots

Suggested reviewers

  • jaybuidl
  • alcercu

Poem

🐰 I hop through code and count each nonce anew,
I fetch, I batch, I nudge the Hashi crew,
From graph to state my tiny paws align,
A hashiNonce tucked safe in JSON fine,
Hooray — messages leap and land on cue! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Feat/hashi executor" directly describes the primary change in the changeset, which is the addition of a comprehensive Hashi executor module to the relayer-cli. The title is concise, clear, and uses a conventional "Feat/" prefix to indicate this is a feature addition. While the title doesn't elaborate on implementation details like state management updates or GraphQL refactoring, it accurately captures the main objective of the PR—adding Hashi executor functionality. A teammate scanning the commit history would immediately understand this is about introducing the Hashi executor feature.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/hashi-executor

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
relayer-cli/src/utils/proof.ts (2)

23-49: Harden getMessageDataToRelay: handle empty results, narrow query, and type the return

  • Query asks for first: 5 but only index 0 is used; set first: 1.
  • Guard when messageSents is empty to avoid result[0] access.
  • Explicit return type e.g., Promise<[string, string, string] | undefined>.
  • chainId param is currently unused; either use it to select subgraph or remove.

Apply:

-                messageSents(first: 5, where: {nonce: ${nonce}, inbox: "${inbox}"}) {
+                messageSents(first: 1, where: {nonce: ${nonce}, inbox: "${inbox}"}) {
@@
-    return [result[`messageSents`][0].to.id, result[`messageSents`][0].msgSender.id, result[`messageSents`][0].data];
+    const [first] = result.messageSents ?? [];
+    if (!first) return undefined;
+    return [first.to.id, first.msgSender.id, first.data];

69-108: Call sites properly updated; null-safety and casing fixes still needed

toLocaleLowerCase() produces different results than toLowerCase() for certain locales like Turkish, which can cause issues when normalizing addresses. Both call sites in relay.ts (lines 30 and 165) correctly pass the inboxAddress parameter, but the following changes in proof.ts remain unaddressed:

  • Replace inboxAddress.toLocaleLowerCase() with toLowerCase() (line 84)
  • Add null-safety checks before accessing result[layer${i}][0].hash (lines 97-101); return empty array if layer missing or empty
  • chainId parameter is unused; consider removing or using for subgraph selection
-    const layerId = inboxAddress.toLocaleLowerCase() + "-" + proofIndices[i];
+    const layerId = inboxAddress.toLowerCase() + "-" + proofIndices[i];
@@
-    for (let i = 0; i < proofIndices.length; i++) {
-      proof.push(result[`layer${i}`][0].hash);
-    }
+    for (let i = 0; i < proofIndices.length; i++) {
+      const layer = result[`layer${i}`];
+      if (!layer || layer.length === 0 || !layer[0]?.hash) {
+        return [];
+      }
+      proof.push(layer[0].hash);
+    }
relayer-cli/src/utils/relay.test.ts (1)

115-117: Comment vs stub mismatch on gas estimate

The comment references an estimated gas of 500000 → 600000 after 20% buffer, but the stub returns 600000. Either change the stub to 500000 or fix the comment.

-      // With an estimated gas of 500000, the computed gasLimit is (500000 * 120)/100 = 600000.
+      // With an estimated gas of 600000, the computed gasLimit is 600000 (per current stub/logic).

Or:

- mockBatchSend.estimateGas = jest.fn().mockResolvedValue(600000);
+ mockBatchSend.estimateGas = jest.fn().mockResolvedValue(500000);
relayer-cli/src/utils/relay.ts (3)

176-186: Fix return when no messages were batched.

lastNonce stays null when nothing was added; returning lastNonce + 1 yields 1 and violates Promise<number | null>.

Apply:

-  return lastNonce + 1; // return current nonce
+  // If no messages were prepared, signal no progress.
+  return lastNonce === null ? null : lastNonce + 1;

76-86: Guard against missing PRIVATE_KEY (batch path).

fetchBatcher/fetchVeaOutbox will construct a signer; without PRIVATE_KEY this fails at runtime.

Apply:

   const bridgeConfig = fetchBridgeConfig(chainId);
   const privateKey = process.env.PRIVATE_KEY;
+  if (!privateKey) throw new MissingEnvironmentVariable("PRIVATE_KEY");

140-148: Guard against missing PRIVATE_KEY (relayAllFrom).

Same risk here when creating batcher and veaOutbox.

Apply:

   const privateKey = process.env.PRIVATE_KEY;
+  if (!privateKey) throw new MissingEnvironmentVariable("PRIVATE_KEY");
relayer-cli/src/utils/relayerHelpers.ts (1)

66-86: Fix state persistence and type safety for nullable hashiNonce.

The call site at relayer.ts:79 passes potentially null/undefined values: initialize returns { nonce: number | null; hashiNonce: number | null } and runHashiExecutor returns number | undefined. The current function signature incorrectly types params as non-nullable number, and the condition if (nonceFrom != null) skips state writes when only hashiNonce advances, losing progress.

Apply:

-async function updateStateFile(
+async function updateStateFile(
   chainId: number,
   createdTimestamp: number,
-  nonceFrom: number,
-  hashiNonceFrom: number,
+  nonceFrom: number | null,
+  hashiNonceFrom: number | null,
   network: string,
   emitter: EventEmitter,
   fileSystem: typeof fs = fs,
   removeLock: typeof releaseLock = releaseLock
 ) {
-  if (nonceFrom != null) {
+  if (nonceFrom != null || hashiNonceFrom != null) {
     const stateDir = process.env.STATE_DIR || "";
     if (!fileSystem.existsSync(stateDir)) {
       fileSystem.mkdirSync(stateDir, { recursive: true });
     }
-    const chain_state_file = process.env.STATE_DIR + network + "_" + chainId + ".json";
-    const json = {
-      ts: createdTimestamp,
-      nonce: nonceFrom,
-      hashiNonce: hashiNonceFrom,
-    };
+    const chain_state_file = path.join(stateDir, `${network}_${chainId}.json`);
+    const existing =
+      fileSystem.existsSync(chain_state_file)
+        ? JSON.parse(fileSystem.readFileSync(chain_state_file, { encoding: "utf8" }))
+        : { ts: createdTimestamp, nonce: 0, hashiNonce: 0 };
+    const json = {
+      ts: createdTimestamp,
+      nonce: nonceFrom ?? existing.nonce ?? 0,
+      hashiNonce: hashiNonceFrom ?? existing.hashiNonce ?? 0,
+    };
     fileSystem.writeFileSync(chain_state_file, JSON.stringify(json), { encoding: "utf8" });
   }
 
   removeLock(network, chainId);
   emitter.emit(BotEvents.LOCK_RELEASED);
 }
🧹 Nitpick comments (13)
relayer-cli/src/utils/graphQueries.ts (3)

4-20: Prefer GraphQL variables over string interpolation and reduce log noise

  • Build queries with variables to avoid injection/escaping issues and to improve caching.
  • Consider gating console.log behind a DEBUG/LOG_LEVEL env.

Example:

-const query = `{messageSents(first: 1, where: {nonce: ${nonce}, inbox: "${inboxAddress}"}) { id transactionHash }}`
-const result = await request(url, query)
+const query = `query($nonce: Int!, $inbox: String!) {
+  messageSents(first: 1, where: { nonce: $nonce, inbox: $inbox }) { id transactionHash }
+}`
+const result = await request(url, query, { nonce, inbox: inboxAddress })

2-2: Type safety note

Defining a minimal common interface for veaOutbox (e.g., with stateRoot()) allows easier mocking and testing across chains. Based on learnings.


12-19: Error handling is fine; consider structured logging

Catching and returning [] is acceptable here; add context (nonce/inbox) to the log object for observability.

relayer-cli/.env.dist (1)

24-27: Lint warnings vs. intended quoting; add trailing newline

  • Quotes around STATE_DIR are intentional; keep as-is. Based on learnings.
  • Add a newline at EOF to appease linters.
 HASHI_EXECUTOR_ENABLED=true
+ 

Optional: default to false in dist to prevent accidental enablement in new setups.

relayer-cli/src/utils/relay.test.ts (1)

64-65: Test fixture updated to [to, from, data]

Good alignment with the new tuple signature. Consider asserting that the encoded calldata reflects inclusion of the “from” parameter to prevent regressions.

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

63-72: Add a handler for HASHI_EXECUTION_FAILED to surface errors

You emit a failure event in BotEvents but don’t log it here. Add an error listener for parity with MESSAGE_EXECUTION_FAILED.

Suggested diff:

   // Hashi executor logs
   emitter.on(BotEvents.EXECUTING_HASHI, (startNonce, endNonce) => {
     console.log(`Executing Hashi for nonces from ${startNonce} to ${endNonce}`);
   });
   emitter.on(BotEvents.HASHI_EXECUTED, (endNonce) => {
     console.log(`Successfully executed Hashi till ${endNonce}`);
   });
   emitter.on(BotEvents.HASHI_BATCH_TXN, (txHash, batchSize) => {
     console.log(`Hashi batch transaction ${txHash} for ${batchSize} messages`);
   });
+  emitter.on(BotEvents.HASHI_EXECUTION_FAILED, (failedNonce, reason) => {
+    console.error(`Hashi execution failed at nonce ${failedNonce}`, reason);
+  });
relayer-cli/src/utils/botEvents.ts (1)

21-25: Enum additions LGTM; ensure consumers handle failure event

New Hashi events look good. Confirm logger binds HASHI_EXECUTION_FAILED (and it emits error-level logs).

relayer-cli/src/consts/bridgeRoutes.ts (1)

20-24: Parameterize Hashi/Yaru/Yaho addresses and verify correctness per chain

Hard-coding addresses risks drift across envs. Prefer env vars (e.g., HASHI_YAHO_ARBITRUM_SEPOLIA, HASHI_YARU_SEPOLIA, HASHI_HASHI_SEPOLIA, etc.) and document required values. Also confirm these addresses are correct for 11155111 and 10200 and that rpcInbox pointing to RPC_ARBITRUM_SEPOLIA is intentional for both.

Also applies to: 67-71, 79-83

relayer-cli/src/utils/hashi.test.ts (1)

6-14: Reuse shared MockEmitter to avoid duplication

There’s already a MockEmitter utility (validator-cli/src/utils/emitter.ts). Reuse it here to reduce duplication and keep behavior consistent.

relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts (1)

11-23: Prefer public ethers APIs and correct return typing

  • Use bigint (primitive) as return type for getHashiMsgId.
  • Replace internal toBeArray with getBytes and validate 32‑byte length.
  • Since you now accept Uint8Array in HashiMessage.data (see types suggestion), the data branch remains correct.

Suggested diff:

 export function getHashiMsgId(
   sourceChainId: bigint | number | string,
   dispatcherAddress: string,
   message: HashiMessage
-): BigInt {
+): bigint {
   // Normalize exactly as Solidity would see inputs
   const source = BigInt(sourceChainId);
   const dispatcher = getAddress(dispatcherAddress); // checksum normalize

   const msgHash = calculateMessageHash(message);
   const encodedId = coder.encode(["uint256", "address", "bytes32"], [source, dispatcher, msgHash]);
   return hexToBigInt32Bytes(keccak256(encodedId));
 }
@@
-function hexToBigInt32Bytes(hex32: string): bigint {
-  const bytes = toBeArray(hex32);
+function hexToBigInt32Bytes(hex32: string): bigint {
+  const bytes = getBytes(hex32);
+  if (bytes.length !== 32) {
+    throw new Error(`Expected 32-byte hex string, got ${bytes.length} bytes`);
+  }
   // Convert bytes to BigInt (big-endian)
   let n = BigInt(0);
   for (const b of Array.from(bytes)) {
     n = (n << BigInt(8)) + BigInt(b);
   }
   return n;
 }

Also applies to: 34-41, 56-64

relayer-cli/src/utils/relay.ts (1)

127-133: Doc nit: update JSDoc param name.

Comment says @param msgSender but code uses msgSenders: string[].

- * @param msgSender The address of the sender
+ * @param msgSenders The addresses of the senders
relayer-cli/src/utils/hashi.ts (2)

24-45: Typo in function name: toExecuteMesssage.

Three “s” makes grepping/imports error-prone; consider renaming to toExecuteMessage and re-exporting an alias for backward compatibility.


229-235: Remove stray console.log; use BotEvents if needed.

console.log("Message already executed flag:", flag); is noisy in prod paths.

-    console.log("Message already executed flag:", flag);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 571a1eb and 1f52086.

📒 Files selected for processing (18)
  • relayer-cli/.env.dist (1 hunks)
  • relayer-cli/src/consts/bridgeRoutes.ts (2 hunks)
  • relayer-cli/src/relayer.ts (3 hunks)
  • relayer-cli/src/utils/botEvents.ts (1 hunks)
  • relayer-cli/src/utils/graphQueries.ts (1 hunks)
  • relayer-cli/src/utils/hashi.test.ts (1 hunks)
  • relayer-cli/src/utils/hashi.ts (1 hunks)
  • relayer-cli/src/utils/hashiHelpers/abi.ts (1 hunks)
  • relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts (1 hunks)
  • relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (1 hunks)
  • relayer-cli/src/utils/logger.ts (1 hunks)
  • relayer-cli/src/utils/proof.ts (2 hunks)
  • relayer-cli/src/utils/relay.test.ts (1 hunks)
  • relayer-cli/src/utils/relay.ts (4 hunks)
  • relayer-cli/src/utils/relayerHelpers.test.ts (3 hunks)
  • relayer-cli/src/utils/relayerHelpers.ts (4 hunks)
  • relayer-cli/state/devnet_11155111.json (1 hunks)
  • relayer-subgraph-inbox/src/vea-inbox.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-08-27T07:02:45.825Z
Learnt from: mani99brar
PR: kleros/vea#430
File: contracts/src/interfaces/inboxes/IVeaInbox.sol:0-0
Timestamp: 2025-08-27T07:02:45.825Z
Learning: The sendMessage signature simplification in IVeaInbox.sol and related call site updates across relay-cli and test files were fixed in a separate PR by mani99brar.

Applied to files:

  • relayer-subgraph-inbox/src/vea-inbox.ts
📚 Learning: 2024-12-10T08:00:35.645Z
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.

Applied to files:

  • relayer-cli/src/consts/bridgeRoutes.ts
📚 Learning: 2025-07-07T12:29:34.770Z
Learnt from: mani99brar
PR: kleros/vea#427
File: relayer-cli/.env.dist:24-24
Timestamp: 2025-07-07T12:29:34.770Z
Learning: In relayer-cli/.env.dist, the user (mani99brar) intentionally keeps quotes around environment variable values like `STATE_DIR="/home/user/vea/relayer-cli/state/"` as this works as intended for their use case.

Applied to files:

  • relayer-cli/.env.dist
📚 Learning: 2024-12-09T09:04:04.819Z
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/graphQueries.ts:36-58
Timestamp: 2024-12-09T09:04:04.819Z
Learning: In `bridger-cli/src/utils/graphQueries.ts` (TypeScript), the `getVerificationStatus` function is no longer needed and has been removed.

Applied to files:

  • relayer-cli/src/utils/graphQueries.ts
📚 Learning: 2024-12-09T09:40:28.400Z
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/transactionHandler.ts:13-13
Timestamp: 2024-12-09T09:40:28.400Z
Learning: In `bridger-cli/src/utils/transactionHandler.ts`, the `veaOutbox` implementations differ for each chain, but a common interface should be defined for type checks to enhance type safety.

Applied to files:

  • relayer-cli/src/utils/graphQueries.ts
🧬 Code graph analysis (5)
relayer-cli/src/utils/hashi.test.ts (2)
validator-cli/src/utils/emitter.ts (1)
  • MockEmitter (6-14)
relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (2)
  • HashiMessage (1-10)
  • VeaNonceToHashiMessage (12-16)
relayer-cli/src/relayer.ts (3)
relayer-cli/src/utils/hashi.ts (1)
  • runHashiExecutor (237-237)
relayer-cli/src/utils/relay.ts (2)
  • relayBatch (188-188)
  • relayAllFrom (188-188)
relayer-cli/src/utils/relayerHelpers.ts (1)
  • updateStateFile (206-206)
relayer-cli/src/utils/relayerHelpers.test.ts (2)
relayer-cli/src/utils/relayerHelpers.ts (2)
  • initialize (205-205)
  • updateStateFile (206-206)
relayer-cli/src/utils/lock.ts (1)
  • releaseLock (72-85)
relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts (1)
relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (1)
  • HashiMessage (1-10)
relayer-cli/src/utils/hashi.ts (3)
relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (2)
  • VeaNonceToHashiMessage (12-16)
  • HashiMessage (1-10)
relayer-cli/src/utils/hashiHelpers/abi.ts (3)
  • YaruAbi (13-342)
  • messageDispatchedAbi (5-7)
  • thresholdViewAbi (9-11)
relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts (1)
  • getHashiMsgId (11-23)
🪛 dotenv-linter (4.0.0)
relayer-cli/.env.dist

[warning] 24-24: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 27-27: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

⏰ 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). (3)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: test
  • GitHub Check: dependency-review
🔇 Additional comments (16)
relayer-subgraph-inbox/src/vea-inbox.ts (1)

34-38: Offsets verified as correct against contract implementation.

The msgSender extraction at byte 28 and data extraction at byte 48 are correct. The contract encodes messages via abi.encodePacked(oldCount, _to, msg.sender, _data) where oldCount (uint64) occupies bytes 0-7, _to (address) bytes 8-27, msg.sender (address) bytes 28-47, and _data (bytes) starts at byte 48. The TypeScript implementation accurately mirrors this format.

relayer-cli/src/utils/proof.ts (2)

8-10: Schema change acknowledged: msgSender.id added

Looks good and matches the new [to, from, data] flow. Ensure downstream tuple types reflect this.


116-135: Proof indices logic: LGTM

The index computation looks consistent and guards nonce >= count.

relayer-cli/src/utils/relay.test.ts (1)

136-139: Batch expectations: OK

Targets/values/datas arrays match the mock encoder behavior by nonce index. Looks consistent.

Also applies to: 167-172

relayer-cli/state/devnet_11155111.json (1)

1-5: No action required—ts is correctly stored as seconds and never consumed.

The verification confirms the state file is safe. The ts field is explicitly written as Math.floor(Date.now() / 1000) (line 37 in relayerHelpers.ts), storing it in seconds. The initialize function only extracts nonce and hashiNonce from the state file—ts is never read back, eliminating any risk of misinterpretation as milliseconds. The format is unambiguous in the code.

relayer-cli/src/utils/graphQueries.ts (1)

31-47: Systematically unused chainId across relayer functions—clarify design intent

The chainId parameter is unused in getCount, but this mirrors the same pattern in getMessageDataToRelay, getProofAtCount, and other relayer utilities—all receive chainId yet use a single process.env.RELAYER_SUBGRAPH endpoint. Clarify whether:

  • Single subgraph is intentional and chainId can be removed from all function signatures, or
  • Each function should use chainId to select chain-specific subgraph endpoints (aligning with the claimer's getOutboxSubgraphUrl/getInboxSubgraphUrl pattern).

The query already filters appropriately by stateRoot, but consistency across the codebase matters for maintainability.

relayer-cli/src/utils/relayerHelpers.test.ts (1)

25-38: LGTM: tests correctly validate hashiNonce initialization and persistence

The initialize and updateStateFile expectations reflect the extended state shape. Good coverage on both create and read paths.

Consider adding one test where initialize reads a state missing hashiNonce to ensure backward compatibility defaults to 0.

Also applies to: 41-54, 61-65

relayer-cli/src/relayer.ts (2)

66-71: Guard Hashi executor with try/catch and emit failure event

Avoid taking down the loop on transient Hashi errors. Emit BotEvents.HASHI_EXECUTION_FAILED and continue.

Suggested diff:

-  if (hashiExecutorEnabled) {
-    // Execute messages on Hashi
-    hashiNonce = await runHashiExecutor({ chainId, network, nonce: hashiNonce, emitter });
-  }
+  if (hashiExecutorEnabled) {
+    try {
+      // Execute messages on Hashi
+      hashiNonce = await runHashiExecutor({ chainId, network, nonce: hashiNonce, emitter });
+    } catch (err) {
+      emitter.emit(BotEvents.HASHI_EXECUTION_FAILED, hashiNonce ?? 0, err);
+    }
+  }
⛔ Skipped due to learnings
Learnt from: fcanela
PR: kleros/vea#344
File: relayer-cli/src/testnetRelayer.ts:14-22
Timestamp: 2024-11-26T11:30:41.074Z
Learning: In 'relayer-cli/src/testnetRelayer.ts', the error handling strategy is to allow errors to propagate and be handled by an upper layer, so adding try/catch statements in the main loop is not required.
Learnt from: fcanela
PR: kleros/vea#344
File: relayer-cli/src/devnetRelayExample.ts:9-14
Timestamp: 2024-11-26T11:30:35.723Z
Learning: In `relayer-cli/src/devnetRelayExample.ts`, error handling is managed by the upper layer via `ShutdownManager`'s error signal handler, so adding a `try...catch` block in the main loop is unnecessary.
Learnt from: fcanela
PR: kleros/vea#344
File: relayer-cli/src/utils/relay.ts:28-40
Timestamp: 2024-11-26T11:30:36.180Z
Learning: In `relayer-cli/src/utils/relay.ts`, avoid suggesting adding try/catch blocks that only log errors and rethrow in the `relay` function.

72-75: Review comment is incorrect—function signature already uses object parameters

The relayBatch function at relayer-cli/src/utils/relay.ts:63 is defined with object destructuring:

const relayBatch = async ({ chainId, network, nonce, maxBatchSize, emitter, ... })

The call at relayer-cli/src/relayer.ts:74 correctly passes an object:

await relayBatch({ chainId, network, nonce, maxBatchSize, emitter })

All test invocations (relay.test.ts lines 82, 101, 122, 145, 180) also use object parameters, confirming this is the intended API. The proposed fix to change to positional parameters would break the code.

Likely an incorrect or invalid review comment.

relayer-cli/src/utils/relay.ts (3)

34-36: LGTM: expanded message tuple is wired correctly.

sendMessage(proof, nonce, to, from, data) aligns with the new [to, from, data] shape.


102-106: LGTM: batch path updated for from param.

Static call and ABI encoding include from consistently.


168-171: LGTM: relayAllFrom uses extended tuple and encodes correctly.

relayer-cli/src/utils/relayerHelpers.ts (3)

28-29: LGTM: initialize now returns both nonce and hashiNonce.


38-39: LGTM: bootstrap includes hashiNonce=0 in new state.


45-55: LGTM: loads hashiNonce from state when present.

relayer-cli/src/utils/hashiHelpers/abi.ts (1)

1-342: LGTM: ABI surfaces match the executor’s encode/decode usage.

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

♻️ Duplicate comments (1)
relayer-cli/src/utils/graphQueries.ts (1)

64-86: Paginate >1000 results and use variables; normalize casing.

Current query caps at 1000 and may miss older nonces. Use a paginated loop with first/skip and GraphQL variables; keep addresses lowercased. This was flagged earlier; re-iterating with a concrete patch.

-const getNonceFrom = async (chainId: number, inbox: string, nonce: number, msgSender: string) => {
-  const subgraph = process.env.RELAYER_SUBGRAPH;
-
-  const result = (await request(
-    `https://api.studio.thegraph.com/query/${subgraph}`,
-    `{
-        messageSents(
-          first: 1000, 
-          where: {
-            inbox: "${inbox}",
-            nonce_gte: ${nonce}, 
-            msgSender_: {id: "${msgSender.toLowerCase()}"}
-          }, 
-          orderBy: nonce, 
-          orderDirection: asc
-        ) {
-          nonce
-        }
-      }`
-  )) as MessageSentsResponse;
-
-  return result[`messageSents`].map((a: { nonce: string | number }) => Number(a.nonce));
-};
+const getNonceFrom = async (_chainId: number, inbox: string, nonce: number, msgSender: string) => {
+  const subgraph = process.env.RELAYER_SUBGRAPH;
+  if (!subgraph) throw new Error("Missing RELAYER_SUBGRAPH");
+  const endpoint = `https://api.studio.thegraph.com/query/${subgraph}`;
+  const query = gql`
+    query MsgsFrom($inbox: String!, $nonce: BigInt!, $sender: String!, $first: Int!, $skip: Int!) {
+      messageSents(
+        first: $first
+        skip: $skip
+        where: { inbox: $inbox, nonce_gte: $nonce, msgSender_: { id: $sender } }
+        orderBy: nonce
+        orderDirection: asc
+      ) {
+        nonce
+      }
+    }
+  `;
+  const first = 1000;
+  let skip = 0;
+  const acc: number[] = [];
+  for (;;) {
+    const vars = { inbox: inbox.toLowerCase(), nonce, sender: msgSender.toLowerCase(), first, skip };
+    const page = (await request(endpoint, query, vars)) as MessageSentsResponse;
+    const items = page.messageSents;
+    acc.push(...items.map((a) => Number(a.nonce)));
+    if (items.length < first) break;
+    skip += first;
+  }
+  return acc;
+};
🧹 Nitpick comments (7)
relayer-cli/src/utils/graphQueries.ts (1)

31-47: Remove or underscore unused parameter; add ENV guard and variables in getCount.

chainId is unused; mark as _chainId to satisfy TS and future use. Also guard RELAYER_SUBGRAPH and use variables.

-const getCount = async (veaOutbox: VeaOutboxArbToEth | VeaOutboxArbToGnosis, chainId: number): Promise<number> => {
-  const subgraph = process.env.RELAYER_SUBGRAPH;
+const getCount = async (veaOutbox: VeaOutboxArbToEth | VeaOutboxArbToGnosis, _chainId: number): Promise<number> => {
+  const subgraph = process.env.RELAYER_SUBGRAPH;
+  if (!subgraph) throw new Error("Missing RELAYER_SUBGRAPH");
   const stateRoot = await veaOutbox.stateRoot();
 
-  const result = (await request(
-    `https://api.studio.thegraph.com/query/${subgraph}`,
-    `{
-      snapshotSaveds(first: 1, where: { stateRoot: "${stateRoot}" }) {
-        count
-      }
-    }`
-  )) as SnapshotResponse;
+  const endpoint = `https://api.studio.thegraph.com/query/${subgraph}`;
+  const query = gql`
+    query SnapByRoot($stateRoot: Bytes!) {
+      snapshotSaveds(first: 1, where: { stateRoot: $stateRoot }) {
+        count
+      }
+    }
+  `;
+  const result = (await request(endpoint, query, { stateRoot })) as SnapshotResponse;
 
-  if (result["snapshotSaveds"].length == 0) return 0;
+  if (result.snapshotSaveds.length === 0) return 0;
 
-  return Number(result["snapshotSaveds"][0].count);
+  return Number(result.snapshotSaveds[0].count);
 };
relayer-cli/src/utils/hashi.ts (6)

11-11: Hardcoded SOURCE_CHAIN_ID OK for current scope; add TODO.

Accepted per project context (Arbitrum Sepolia only). Add a reminder for future multi-route support.

-const SOURCE_CHAIN_ID = 421614; // Arbitrum Sepolia
+const SOURCE_CHAIN_ID = 421614; // Arbitrum Sepolia
+// TODO: Make source chain id configurable when enabling non-Arbitrum routes.

Based on learnings.


36-61: Reuse provider and log interface across the loop to cut overhead.

Currently a new provider/interface can be constructed per nonce (via defaults). Build once and pass in.

 async function runHashiExecutor({
@@
   const bridgeConfig = fetchBridgeConfig(chainId);
   const { veaContracts, rpcInbox } = bridgeConfig;
   const veaInboxAddress = veaContracts[network].veaInbox.address;
   const privateKey = process.env.PRIVATE_KEY;
   const veaInbox = fetchVeaInbox(veaInboxAddress, privateKey, rpcInbox, chainId);
+  const providerInbox = new JsonRpcProvider(rpcInbox);
+  const logIFace = new Interface(messageDispatchedAbi);
   const inboxCount = await veaInbox.count();
@@
-    const toExecute = await isMessageExecutable({ chainId, nonce, veaInboxAddress, rpcInbox });
+    const toExecute = await isMessageExecutable({
+      chainId,
+      nonce,
+      veaInboxAddress,
+      rpcInbox,
+      provider: providerInbox,
+      logIFace,
+    });

80-86: Optional: inject signer/private key for testability and clearer failures.

Keep env handling upstream if desired, but allowing an injected signer (or privateKey param) decouples this util from process.env.

-  const provider = new JsonRpcProvider(rpcOutbox);
-  const signer = new Wallet(process.env.PRIVATE_KEY!, provider);
+  const provider = new JsonRpcProvider(rpcOutbox);
+  // Consider: accept a signer/privateKey param; fallback to env for convenience.
+  const signer = new Wallet(process.env.PRIVATE_KEY!, provider);

Based on learnings.


162-176: Consider early-config checks for Yaho address; clearer error if misconfigured.

Fail-fast on missing yahoAddress before decoding to improve diagnostics; optional per your fail-fast stance on hashes.

   const hashes = await fetchVeaMsgTrnx(nonce, veaInboxAddress);
   const bridgeConfig = fetchBridgeConfig(chainId);
-  const yahoAddress = bridgeConfig.yahoAddress?.toLowerCase();
+  const yahoAddress = bridgeConfig.yahoAddress?.toLowerCase();
+  if (!yahoAddress) throw new Error("Missing yahoAddress in bridge config");

211-240: Message ID domain/dispatcher selection — defer change, track via TODO.

Using SOURCE_CHAIN_ID and bridgeConfig(message.targetChainId) is acceptable for current Arbitrum-only routes. Add a TODO to derive domain + dispatcher from the source chain config when expanding routes.

-  const domain = BigInt(SOURCE_CHAIN_ID); // uint256
-  const id = getHashiMsgId(SOURCE_CHAIN_ID, bridgeConfig.yahoAddress!, message); // bytes32
+  const domain = BigInt(SOURCE_CHAIN_ID); // uint256
+  const id = getHashiMsgId(SOURCE_CHAIN_ID, bridgeConfig.yahoAddress!, message); // bytes32
+  // TODO: When adding more routes, compute ID with the source chain's dispatcher and chain id.

Based on learnings.


242-242: Typo in exported function name; add alias to ease future rename.

Function is spelled toExecuteMesssage. Consider exporting an alias now to avoid breakage later.

-export { executeBatchOnHashi, runHashiExecutor, toExecuteMesssage };
+export { executeBatchOnHashi, runHashiExecutor, toExecuteMesssage };
+// Back-compat alias; safe to remove after repo-wide rename.
+export { toExecuteMesssage as toExecuteMessage };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f52086 and 0568965.

📒 Files selected for processing (2)
  • relayer-cli/src/utils/graphQueries.ts (1 hunks)
  • relayer-cli/src/utils/hashi.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-10-27T13:45:23.401Z
Learnt from: mani99brar
PR: kleros/vea#434
File: relayer-cli/src/utils/hashi.ts:206-235
Timestamp: 2025-10-27T13:45:23.401Z
Learning: The Hashi executor in relayer-cli currently only supports routes from Arbitrum Sepolia (chain ID 421614), so the hardcoded SOURCE_CHAIN_ID constant in relayer-cli/src/utils/hashi.ts is acceptable for the current scope. This will be updated when support for other source chains is added.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
📚 Learning: 2024-12-09T10:18:00.133Z
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/ethers.ts:20-82
Timestamp: 2024-12-09T10:18:00.133Z
Learning: In `bridger-cli/src/utils/ethers.ts`, prefer to keep the existing `chainId` checks without refactoring to avoid overcomplicating the code with additional conditional logic.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
📚 Learning: 2024-11-19T10:25:55.588Z
Learnt from: fcanela
PR: kleros/vea#344
File: validator-cli/src/utils/arbMsgExecutor.ts:14-14
Timestamp: 2024-11-19T10:25:55.588Z
Learning: In the `validator-cli/src/utils/arbMsgExecutor.ts` file, checks for commonly required environment variables like `PRIVATE_KEY` should be performed earlier in the application lifecycle, before individual functions are executed.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
📚 Learning: 2024-11-20T11:50:12.303Z
Learnt from: madhurMongia
PR: kleros/vea#359
File: validator-cli/src/utils/arbMsgExecutor.ts:13-13
Timestamp: 2024-11-20T11:50:12.303Z
Learning: In the `validator-cli` codebase, when initializing `Wallet` instances in TypeScript, it's acceptable to rely on the `Wallet` class's built-in validation of the private key retrieved from environment variables, without adding explicit checks for the existence of `PRIVATE_KEY`.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
📚 Learning: 2025-10-27T13:46:03.446Z
Learnt from: mani99brar
PR: kleros/vea#434
File: relayer-cli/src/utils/hashi.ts:80-86
Timestamp: 2025-10-27T13:46:03.446Z
Learning: In the relayer-cli codebase, when initializing Wallet instances, it's acceptable to rely on the Wallet class's built-in validation of the private key retrieved from environment variables, without adding explicit checks for the existence of PRIVATE_KEY.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
📚 Learning: 2024-12-09T09:40:28.400Z
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/transactionHandler.ts:13-13
Timestamp: 2024-12-09T09:40:28.400Z
Learning: In `bridger-cli/src/utils/transactionHandler.ts`, the `veaOutbox` implementations differ for each chain, but a common interface should be defined for type checks to enhance type safety.

Applied to files:

  • relayer-cli/src/utils/hashi.ts
  • relayer-cli/src/utils/graphQueries.ts
📚 Learning: 2024-12-09T09:04:04.819Z
Learnt from: mani99brar
PR: kleros/vea#370
File: bridger-cli/src/utils/graphQueries.ts:36-58
Timestamp: 2024-12-09T09:04:04.819Z
Learning: In `bridger-cli/src/utils/graphQueries.ts` (TypeScript), the `getVerificationStatus` function is no longer needed and has been removed.

Applied to files:

  • relayer-cli/src/utils/graphQueries.ts
🧬 Code graph analysis (1)
relayer-cli/src/utils/hashi.ts (3)
relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (2)
  • VeaNonceToHashiMessage (12-16)
  • HashiMessage (1-10)
relayer-cli/src/utils/hashiHelpers/abi.ts (3)
  • YaruAbi (13-342)
  • messageDispatchedAbi (5-7)
  • thresholdViewAbi (9-11)
relayer-cli/src/utils/hashiHelpers/hashiMsgUtils.ts (1)
  • getHashiMsgId (11-23)
⏰ 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). (3)
  • GitHub Check: test
  • GitHub Check: Analyze (javascript)
  • GitHub Check: dependency-review

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
18.6% Duplication on New Code (required ≤ 10%)

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

♻️ Duplicate comments (2)
relayer-cli/src/utils/hashi.test.ts (2)

1-231: Verify function name typo in hashi.ts.

The past review flagged a typo toExecuteMesssage (triple 's') in hashi.ts at lines 20, 43, 157, and 237. While this test file's imports use the correct spelling, ensure the actual function definition and all its references in hashi.ts have been corrected to toExecuteMessage.

Run the following script to check for any remaining instances of the typo:

#!/bin/bash
# Description: Search for the typo 'toExecuteMesssage' (triple 's') in hashi.ts and related files

# Search for the typo with triple 's'
echo "Checking for typo 'toExecuteMesssage' (triple 's'):"
rg -n 'toExecuteMesssage' relayer-cli/src/utils/

# Verify correct spelling exists
echo -e "\nVerifying correct spelling 'toExecuteMessage':"
rg -n 'toExecuteMessage' relayer-cli/src/utils/hashi.ts -C 1 | head -20

101-117: Type mismatch: HashiMessage numeric fields should be bigint.

Line 116 expects hashiMessage.nonce to be BigInt(1), but the HashiMessage interface defines nonce (along with targetChainId and threshold) as number. This creates a type mismatch since:

  • Decoded event logs return BigInt values (lines 85-87)
  • Test assertions expect BigInt (line 116)
  • But the type definition specifies number

Update hashiTypes.ts to define these three fields as bigint to align with runtime behavior and eliminate type inconsistencies.

🧹 Nitpick comments (1)
relayer-cli/src/utils/hashi.test.ts (1)

6-14: Extract MockEmitter to shared test utilities.

This class duplicates the identical MockEmitter from validator-cli/src/utils/emitter.ts. To avoid code duplication and maintain consistency across test files, extract it to a shared test utilities module (e.g., test-utils/mockEmitter.ts) that both validator-cli and relayer-cli can import.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0568965 and 0e4ca91.

📒 Files selected for processing (2)
  • relayer-cli/src/utils/hashi.test.ts (1 hunks)
  • relayer-cli/src/utils/hashi.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • relayer-cli/src/utils/hashi.ts
🧰 Additional context used
🧬 Code graph analysis (1)
relayer-cli/src/utils/hashi.test.ts (2)
validator-cli/src/utils/emitter.ts (1)
  • MockEmitter (6-14)
relayer-cli/src/utils/hashiHelpers/hashiTypes.ts (2)
  • HashiMessage (1-10)
  • VeaNonceToHashiMessage (12-16)
⏰ 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). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: dependency-review
🔇 Additional comments (1)
relayer-cli/src/utils/hashi.test.ts (1)

82-95: LGTM: Mock event log correctly uses BigInt.

The mock properly simulates decoded event logs by returning BigInt values for numeric fields (nonce, targetChainId, threshold), which matches actual blockchain event decoding behavior.

@mani99brar mani99brar marked this pull request as ready for review October 27, 2025 15:05
@mani99brar mani99brar requested a review from jaybuidl as a code owner October 27, 2025 15:05
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.

2 participants