Skip to content

Conversation

@arthcp
Copy link
Contributor

@arthcp arthcp commented Nov 16, 2025

Summary by CodeRabbit

  • New Features

    • Added MONAD network support across the app and admin tooling; new admin commands for querying outbound transactions, seal events, attest and execute flows.
  • Infrastructure

    • Production deployments and verification metadata updated to include MONAD network addresses.
    • RPC/explorer entries and chain mappings added for MONAD.
  • Chores

    • Enabled EIP-1559 handling for Mainnet/Polygon and updated gas defaults; release version bumped to 1.0.113.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 16, 2025

Walkthrough

Adds MONAD (chain ID 143) across enums, RPC/config mappings, deployment addresses and verification data; introduces EIP-1559 overrides and a MONAD RPC env var; and adds four admin scripts for querying and sending attest/execute transactions.

Changes

Cohort / File(s) Summary
Enums & Chain IDs
src/enums/chainId.ts, src/enums/chainSlug.ts, src/enums/hardhatChainName.ts
Added MONAD = 143 and related enum members for chain slug and hardhat name.
Chain Mappings & Registries
src/enums/chainSlugToHardhatChainName.ts, src/enums/chainSlugToId.ts, src/enums/chainSlugToKey.ts, src/enums/hardhatChainNameToSlug.ts, src/enums/mainnetIds.ts, src/enums/ethLikeChains.ts
Extended mapping objects and arrays to include ChainSlug.MONAD where applicable.
Native Tokens / Currency
src/enums/native-tokens.ts, src/enums/currency.ts
Added wormhole token enum member; added ChainSlug.MONAD currency mapping; adjusted PLASMA currency mapping.
RPC / Explorer / Icons / Support Lists
scripts/rpcConfig/constants/rpc.ts, scripts/rpcConfig/constants/explorers.ts, scripts/rpcConfig/constants/icons.ts, scripts/rpcConfig/constants/batcherSupportedChainSlug.ts, .env.example
Added MONAD_RPC env example and RPC entry, explorer URL, icon placeholder, and batcher support for MONAD.
Hardhat Configuration
hardhat.config.ts
Added MONAD custom chain entry, live network mapping, and etherscan API key entry.
Deployment Addresses & Verification
deployments/prod_addresses.json, deployments/prod_verification.json
Inserted network ID 143 address blocks and verification metadata for contracts/mocks across deployments/prod files.
Overrides / Gas Handling
scripts/constants/overrides.ts
Added EIP‑1559 (type:2) handling for MAINNET/POLYGON, migrated PLASMA to EIP‑1559, added MONAD gasLimit and EIP‑1559 calculation branch.
Admin Scripts
scripts/admin/get-outbound-txs.ts, scripts/admin/get-seal-events.ts, scripts/admin/send-attest.ts, scripts/admin/send-execute.ts
New TypeScript utilities: query MessageAdded/Sealed events; build/sign (AWS KMS) and optionally send attest and execute transactions. Each exports a main entry function.
Logging tweak
scripts/deploy/scripts/registerSwitchboard.ts
Logging now includes signer.getChainId() in the registration message.
Version Bump
scripts/rpcConfig/constants/version.ts
PROD version updated (new prod version value).

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI (npm_config_*)
  participant Addrs as Addresses (deployments/prod_addresses.json)
  participant Provider as JSON-RPC Provider
  participant KMS as AWS KMS Signer
  participant Contract as Target Contract (Switchboard/Socket)
  rect rgba(0,128,0,0.06)
    CLI->>Addrs: load chain & integration addresses
    CLI->>Provider: create provider for chain
    CLI->>Contract: instantiate contract ABI + address
  end
  rect rgba(0,64,128,0.06)
    CLI->>KMS: request signature for message/hash
    KMS-->>CLI: signature
    CLI->>Contract: prepare calldata (encode)
  end
  alt --sendtx
    CLI->>Provider: send transaction (signed by key or via Wallet)
    Provider-->>CLI: txHash / receipt
  else dry-run
    CLI-->>CLI: print calldata & instructions
  end
  Note right of CLI: scripts support block-range event queries (chunked) and optional tx broadcast
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

This should be reviewed with focus on:

  • Admin scripts — verify AWS KMS signer integration, signer derivation, calldata encoding, and safety of optional --sendtx flow.
  • EIP‑1559 logic in scripts/constants/overrides.ts — ensure correct baseFee/priority calculations and fallbacks for older chains.
  • Deployment JSONs — validate all addresses for network 143 are correct and consistent across prod_addresses & prod_verification.
  • RPC/env handling — ensure .env.example entries (two MONAD_RPC lines present) are intentional and deduplicated.

Possibly related PRs

Poem

A new chain wakes, one-four-three,
Enums stretch wide to let it be.
Scripts will query, sign, and send,
Configs align, addresses penned.
Deployments hum — a network spree. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Bungee chains' is vague and does not clearly convey what the changeset accomplishes. While the PR adds support for the Monad network across multiple files, the title uses a generic term that provides no meaningful information about the actual changes. Use a descriptive title like 'Add Monad network support' or 'Add Monad (chain 143) configuration' to clearly indicate the primary change in the changeset.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 bungee-chains

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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

Copy link

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

♻️ Duplicate comments (1)
scripts/admin/get-seal-events.ts (1)

32-54: Validate and convert chain slugs to numbers immediately after extraction.

Same issue as in get-outbound-txs.ts. The env vars are strings but need to be numeric ChainSlug values.

Apply this diff:

 const sourceChainSlug = process.env.npm_config_source;
 if (!sourceChainSlug) {
   console.error("Error: source flag is required");
   process.exit(1);
 }
+const sourceChainSlugNum = parseInt(sourceChainSlug);
+if (isNaN(sourceChainSlugNum)) {
+  console.error(`Error: source must be a valid number, got: ${sourceChainSlug}`);
+  process.exit(1);
+}
 
 const destinationChainSlug = process.env.npm_config_destination;
 if (!destinationChainSlug) {
   console.error("Error: destination flag is required");
   process.exit(1);
 }
+const destinationChainSlugNum = parseInt(destinationChainSlug);
+if (isNaN(destinationChainSlugNum)) {
+  console.error(`Error: destination must be a valid number, got: ${destinationChainSlug}`);
+  process.exit(1);
+}

Then update lines 59-60 and 98 to use the numeric versions:

-  const sourceChain = sourceChainSlug;
-  const destinationChain = destinationChainSlug;
+  const sourceChain = sourceChainSlugNum as ChainSlug;
+  const destinationChain = destinationChainSlugNum as ChainSlug;
-  const provider = getProviderFromChainSlug(parseInt(sourceChain) as ChainSlug);
+  const provider = getProviderFromChainSlug(sourceChain);
🧹 Nitpick comments (2)
scripts/admin/send-attest.ts (1)

128-130: Cache the parsed destination chain value

The destinationChain is parsed multiple times (lines 129, 142, 186) with parseInt(destinationChain). Parse once at the beginning of main().

Apply this refactor after line 92:

 export const main = async () => {
   const sourceChain = sourceChainSlug;
-  const destinationChain = destinationChainSlug;
+  const destinationChain = parseInt(destinationChainSlug) as ChainSlug;
 
-  console.log(`\nProcessing attest for path: ${sourceChain} -> ${destinationChain}\n`);
+  console.log(`\nProcessing attest for path: ${sourceChain} -> ${destinationChain}\n`);

Then remove parseInt calls at lines 129, 142, and 186.

scripts/rpcConfig/constants/icons.ts (1)

45-45: Consider adding a MONAD icon.

The icon is currently an empty string, consistent with other chains, but adding a proper icon URL would improve the UI experience.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adce691 and 45f7395.

📒 Files selected for processing (25)
  • .env.example (1 hunks)
  • deployments/prod_addresses.json (27 hunks)
  • deployments/prod_verification.json (1 hunks)
  • scripts/admin/get-outbound-txs.ts (1 hunks)
  • scripts/admin/get-seal-events.ts (1 hunks)
  • scripts/admin/send-attest.ts (1 hunks)
  • scripts/admin/send-execute.ts (1 hunks)
  • scripts/constants/overrides.ts (4 hunks)
  • scripts/deploy/scripts/registerSwitchboard.ts (1 hunks)
  • scripts/rpcConfig/constants/batcherSupportedChainSlug.ts (1 hunks)
  • scripts/rpcConfig/constants/explorers.ts (1 hunks)
  • scripts/rpcConfig/constants/icons.ts (1 hunks)
  • scripts/rpcConfig/constants/rpc.ts (1 hunks)
  • scripts/rpcConfig/constants/version.ts (1 hunks)
  • src/enums/chainId.ts (1 hunks)
  • src/enums/chainSlug.ts (1 hunks)
  • src/enums/chainSlugToHardhatChainName.ts (1 hunks)
  • src/enums/chainSlugToId.ts (1 hunks)
  • src/enums/chainSlugToKey.ts (1 hunks)
  • src/enums/currency.ts (1 hunks)
  • src/enums/ethLikeChains.ts (1 hunks)
  • src/enums/hardhatChainName.ts (1 hunks)
  • src/enums/hardhatChainNameToSlug.ts (1 hunks)
  • src/enums/mainnetIds.ts (1 hunks)
  • src/enums/native-tokens.ts (1 hunks)
👮 Files not reviewed due to content moderation or server errors (1)
  • deployments/prod_addresses.json
🧰 Additional context used
🧬 Code graph analysis (5)
scripts/admin/send-execute.ts (4)
scripts/admin/tripCommon.ts (2)
  • sendTx (61-61)
  • addresses (50-50)
src/socket-types.ts (1)
  • DeploymentAddresses (115-117)
scripts/deploy/config/config.ts (1)
  • mode (20-22)
scripts/constants/networks.ts (1)
  • getProviderFromChainSlug (54-57)
scripts/admin/send-attest.ts (3)
scripts/admin/tripCommon.ts (2)
  • sendTx (61-61)
  • addresses (50-50)
scripts/deploy/config/config.ts (2)
  • mode (20-22)
  • overrides (133-154)
scripts/constants/networks.ts (1)
  • getProviderFromChainSlug (54-57)
scripts/admin/get-outbound-txs.ts (4)
src/socket-types.ts (1)
  • DeploymentAddresses (115-117)
scripts/deploy/config/config.ts (1)
  • mode (20-22)
scripts/admin/get-seal-events.ts (1)
  • main (58-142)
scripts/constants/networks.ts (1)
  • getProviderFromChainSlug (54-57)
scripts/constants/overrides.ts (1)
scripts/deploy/config/config.ts (1)
  • overrides (133-154)
scripts/admin/get-seal-events.ts (4)
src/socket-types.ts (1)
  • DeploymentAddresses (115-117)
src/addresses.ts (1)
  • getAllAddresses (173-173)
scripts/deploy/config/config.ts (1)
  • mode (20-22)
scripts/constants/networks.ts (1)
  • getProviderFromChainSlug (54-57)
🔇 Additional comments (25)
scripts/rpcConfig/constants/version.ts (1)

5-5: This version jump requires manual verification of the team's versioning strategy.

The PROD version skips from 1.0.106 to 1.0.110 for a single chain addition (MONAD). While the version strings exist only in scripts/rpcConfig/constants/version.ts and aren't used for compatibility checks or feature logic elsewhere, the jump is unusual. Git history shows frequent version bumps, but no documented versioning scheme exists in the repository to validate whether the +4 increment is intentional or a mistake. Confirm with the maintainers that this aligns with the project's versioning practice.

scripts/deploy/scripts/registerSwitchboard.ts (1)

56-59: LGTM - Improved observability

The enhanced logging now includes the chain ID, which helps with debugging multi-chain deployments. The additional async call is negligible overhead for a logging operation.

scripts/admin/send-attest.ts (2)

139-144: Message hash construction looks correct

The ABI encoding matches the expected signature verification pattern for FastSwitchboard attest function. Parameters are properly ordered and typed.


169-193: Transaction sending is properly gated and includes overrides

The sendTx flag correctly gates transaction submission, and the transaction includes proper overrides for the destination chain. Good separation between signature generation and transaction submission.

scripts/admin/send-execute.ts (1)

110-124: Hasher contract integration is correctly implemented

The hasher address is retrieved from the Socket contract and used to pack the message with proper parameter ordering. The ABI definition matches the expected packMessage signature.

src/enums/chainSlugToHardhatChainName.ts (1)

79-79: LGTM - Consistent enum mapping

The MONAD mapping follows the established pattern for chain slug to hardhat name mappings.

src/enums/hardhatChainName.ts (1)

76-76: LGTM - Consistent hardhat chain name

The MONAD hardhat chain name follows the established lowercase naming convention.

src/enums/chainSlug.ts (1)

78-78: LGTM - Chain slug properly linked to chain ID

The MONAD chain slug correctly references ChainId.MONAD (143), maintaining consistency with the chain ID enum.

src/enums/chainId.ts (1)

76-76: MONAD chain ID 143 is correct

The official chain ID for Monad mainnet is 143. The enum value matches the specification and no changes are needed.

scripts/rpcConfig/constants/explorers.ts (1)

47-47: Verify the explorer URL stability.

The explorer URL contains "mainnet-beta" which suggests the network or explorer may still be in beta. Ensure this is production-ready and won't cause issues with block explorers or verification flows.

src/enums/mainnetIds.ts (1)

49-49: LGTM!

MONAD correctly added to the mainnet identifiers list.

src/enums/ethLikeChains.ts (1)

34-34: LGTM!

MONAD correctly added to the eth-like chains with constant gas limits.

src/enums/chainSlugToKey.ts (1)

79-79: LGTM!

MONAD mapping correctly added to ChainSlugToKey.

scripts/rpcConfig/constants/rpc.ts (1)

80-80: LGTM!

MONAD RPC configuration correctly added using the standard checkEnvValue pattern.

src/enums/hardhatChainNameToSlug.ts (1)

79-79: LGTM!

Reverse mapping from HardhatChainName.MONAD to ChainSlug.MONAD correctly added.

.env.example (1)

142-143: Remove duplicate MONAD_RPC definition.

The MONAD_RPC environment variable is defined twice (lines 142 and 143). Remove one of these duplicate entries.

Apply this diff to remove the duplicate:

-
-MONAD_RPC=' '

Likely an incorrect or invalid review comment.

scripts/rpcConfig/constants/batcherSupportedChainSlug.ts (1)

68-69: All required infrastructure is in place—safe to merge.

Verification confirms MONAD support is fully wired:

  • Enums defined across all required files (chainId, chainSlug, hardhatChainName, key mappings, ethLikeChains)
  • RPC endpoint configured with env var check: checkEnvValue("MONAD_RPC")
  • Gas overrides present: gasLimit: 3_00_000
  • Explorer and icon URLs configured

The batcher can ship with this change.

src/enums/chainSlugToId.ts (1)

79-80: Mapping verified and unique.

ChainId.MONAD = 143 confirmed at src/enums/chainId.ts:76, and the value is unique across all ChainId enum members. The ChainSlugToId mapping correctly pairs ChainSlug.MONAD with ChainId.MONAD. Change is sound.

deployments/prod_verification.json (1)

975-1120: This review comment is based on false assumptions and should be disregarded.

The verification script correctly failed at step 4. The data does not conform to the stated invariants:

  • Optimistic/Fast/Transmit/Exec do NOT reference Socket at [3][0]: They reference 0xB0BBff631... (unknown). Socket appears at different indices.
  • External address dependency: The block references 0xB0BBff631..., 0x8c36353d..., and 0xA49f876C... which are NOT defined in block 143. These addresses are external dependencies not validated by the proposed checks.
  • Incomplete coverage: The data integrity assumptions are fundamentally broken—the verification cannot succeed as designed because the data structure does not match the claimed invariants.

The original review proposed `` based on validations that fail. Discard the suggested jq checks and approve/reject based on actual business requirements for the "143" configuration, not on assumptions about internal referential integrity that don't hold.

Likely an incorrect or invalid review comment.

scripts/admin/get-outbound-txs.ts (1)

65-77: Fix type mismatch in address lookup.

After applying the fix above, this code will correctly use numeric ChainSlug values as keys. The DeploymentAddresses type expects numeric keys, not strings.

scripts/admin/get-seal-events.ts (1)

65-77: Fix type mismatch in address lookup.

After applying the fix above, this code will correctly use numeric ChainSlug values as keys.

scripts/constants/overrides.ts (4)

29-33: LGTM - EIP-1559 enabled for MAINNET.

The addition of type: 2 correctly enables EIP-1559 transactions for MAINNET while preserving existing gas configuration.


35-39: LGTM - EIP-1559 enabled for POLYGON_MAINNET.

The addition of type: 2 correctly enables EIP-1559 transactions for Polygon mainnet.


124-128: Verify the switch from dynamic to fixed gas pricing.

PLASMA now uses a fixed gasPrice: 100_000_000 instead of the previous multiplier-based calculation. This could cause issues if network conditions change significantly.

Confirm that a fixed gas price is appropriate for PLASMA, or if dynamic pricing should be retained.


143-150: LGTM - Clear EIP-1559 documentation.

The documentation accurately describes the EIP-1559 parameter handling and helps users understand the new behavior.

Comment on lines +1 to +147
import { config as dotenvConfig } from "dotenv";
import {
ChainSlug,
DeploymentAddresses,
IntegrationTypes,
getAllAddresses,
} from "../../src";
import { mode } from "../deploy/config/config";
import SingleCapacitorArtifact from "../../out/SingleCapacitor.sol/SingleCapacitor.json";
import { getProviderFromChainSlug } from "../constants";
import { ethers } from "ethers";

dotenvConfig();

/**
* Usage
*
* --source Specify the source chain slug.
* This flag is required.
* Eg. npx --source=1 --destination=10 --startblock=12345 --endblock=12456 ts-node scripts/admin/get-outbound-txs.ts
*
* --destination Specify the destination chain slug.
* This flag is required.
*
* --startblock Specify the start block number.
* This flag is required.
*
* --endblock Specify the end block number.
* This flag is required.
*/

const sourceChainSlug = process.env.npm_config_source;
if (!sourceChainSlug) {
console.error("Error: source flag is required");
process.exit(1);
}

const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}

const startBlock = process.env.npm_config_startblock;
if (!startBlock) {
console.error("Error: startblock flag is required");
process.exit(1);
}

const endBlock = process.env.npm_config_endblock;
if (!endBlock) {
console.error("Error: endblock flag is required");
process.exit(1);
}

const addresses: DeploymentAddresses = getAllAddresses(mode);

export const main = async () => {
const sourceChain = sourceChainSlug;
const destinationChain = destinationChainSlug;

console.log(`\nProcessing path: ${sourceChain} -> ${destinationChain}\n`);

// Get addresses from prod_addresses.json
const sourceAddresses = addresses[sourceChain];
if (!sourceAddresses) {
console.error(`Error: No addresses found for source chain ${sourceChain}`);
process.exit(1);
}

const integration = sourceAddresses.integrations?.[destinationChain];
if (!integration) {
console.error(
`Error: No integration found for ${sourceChain} -> ${destinationChain}`
);
process.exit(1);
}

// Get FAST integration addresses (switchboard, socket, capacitor)
const fastIntegration = integration[IntegrationTypes.fast];
if (!fastIntegration) {
console.error(
`Error: No FAST integration found for ${sourceChain} -> ${destinationChain}`
);
process.exit(1);
}

const switchboardAddress = fastIntegration.switchboard;
const capacitorAddress = fastIntegration.capacitor;
const socketAddress = sourceAddresses.Socket;

console.log("Addresses:");
console.log(` Switchboard: ${switchboardAddress}`);
console.log(` Socket: ${socketAddress}`);
console.log(` Capacitor: ${capacitorAddress}\n`);

// Get provider and query events
const provider = getProviderFromChainSlug(parseInt(sourceChain) as ChainSlug);

const capacitorContract = new ethers.Contract(
capacitorAddress,
SingleCapacitorArtifact.abi,
provider
);

const fromBlock = parseInt(startBlock);
const toBlock = parseInt(endBlock);

console.log(`Querying events from block ${fromBlock} to ${toBlock}\n`);

// Query MessageAdded events in chunks of 5000 blocks
const CHUNK_SIZE = 5000;
const messageAddedEvents = [];

for (let currentBlock = fromBlock; currentBlock <= toBlock; currentBlock += CHUNK_SIZE) {
const chunkEnd = Math.min(currentBlock + CHUNK_SIZE - 1, toBlock);
console.log(`Querying chunk: ${currentBlock} to ${chunkEnd}`);

const events = await capacitorContract.queryFilter(
capacitorContract.filters.MessageAdded(),
currentBlock,
chunkEnd
);

messageAddedEvents.push(...events);
}

console.log(`Found ${messageAddedEvents.length} outbound transactions:\n`);

for (const event of messageAddedEvents) {
console.log(`Block: ${event.blockNumber}`);
console.log(` Transaction Hash: ${event.transactionHash}`);
console.log(` Packed Message: ${event.args?.packedMessage}`);
console.log(` Packet Count: ${event.args?.packetCount?.toString()}`);
console.log(` Root Hash: ${event.args?.newRootHash}`);
console.log("");
}

console.log("Script completed.");
};

main()
.then(() => process.exit(0))
.catch((error: Error) => {
console.error(error);
process.exit(1);
});
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Eliminate code duplication with get-seal-events.ts.

This script shares ~95% identical code with get-seal-events.ts. Extract the common logic (env parsing, validation, address resolution, chunked querying) into a shared utility function or base class. The only differences are the contract artifact and event filter.

Consider creating a shared helper like:

// scripts/admin/utils/query-events.ts
export async function queryEventsForPath(
  sourceChain: ChainSlug,
  destinationChain: ChainSlug,
  startBlock: number,
  endBlock: number,
  contractType: 'Socket' | 'SingleCapacitor',
  eventName: string
) {
  // Common logic here
}

Then both scripts become simple wrappers:

// get-outbound-txs.ts
const result = await queryEventsForPath(
  sourceChain,
  destinationChain, 
  startBlock,
  endBlock,
  'SingleCapacitor',
  'MessageAdded'
);
🤖 Prompt for AI Agents
In scripts/admin/get-outbound-txs.ts around lines 1-147, the file duplicates
~95% of the logic from get-seal-events.ts; extract the common logic (env flag
parsing and validation, address resolution via getAllAddresses(mode), provider
creation, chunked query loop and result aggregation) into a shared helper (e.g.,
scripts/admin/utils/query-events.ts) that accepts parameters for sourceChain,
destinationChain, startBlock, endBlock, contract artifact/ABI or a contract
factory, and the event filter name or filter function; change this script to
validate flags then call the helper with the SingleCapacitor artifact and
MessageAdded event, returning the matched events; ensure the helper returns
event objects and that error handling/logging stays consistent; update
get-seal-events.ts to call the same helper with its respective artifact and
event name so both scripts are thin wrappers.

Comment on lines +32 to +54
const sourceChainSlug = process.env.npm_config_source;
if (!sourceChainSlug) {
console.error("Error: source flag is required");
process.exit(1);
}

const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}

const startBlock = process.env.npm_config_startblock;
if (!startBlock) {
console.error("Error: startblock flag is required");
process.exit(1);
}

const endBlock = process.env.npm_config_endblock;
if (!endBlock) {
console.error("Error: endblock flag is required");
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Validate and convert chain slugs to numbers immediately after extraction.

The env vars are strings but need to be numeric ChainSlug values. Convert and validate them right after extraction to fail fast and ensure type safety throughout the script.

Apply this diff:

 const sourceChainSlug = process.env.npm_config_source;
 if (!sourceChainSlug) {
   console.error("Error: source flag is required");
   process.exit(1);
 }
+const sourceChainSlugNum = parseInt(sourceChainSlug);
+if (isNaN(sourceChainSlugNum)) {
+  console.error(`Error: source must be a valid number, got: ${sourceChainSlug}`);
+  process.exit(1);
+}
 
 const destinationChainSlug = process.env.npm_config_destination;
 if (!destinationChainSlug) {
   console.error("Error: destination flag is required");
   process.exit(1);
 }
+const destinationChainSlugNum = parseInt(destinationChainSlug);
+if (isNaN(destinationChainSlugNum)) {
+  console.error(`Error: destination must be a valid number, got: ${destinationChainSlug}`);
+  process.exit(1);
+}

Then update lines 59-60 and 98 to use the numeric versions:

-  const sourceChain = sourceChainSlug;
-  const destinationChain = destinationChainSlug;
+  const sourceChain = sourceChainSlugNum as ChainSlug;
+  const destinationChain = destinationChainSlugNum as ChainSlug;
-  const provider = getProviderFromChainSlug(parseInt(sourceChain) as ChainSlug);
+  const provider = getProviderFromChainSlug(sourceChain);

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

🤖 Prompt for AI Agents
In scripts/admin/get-outbound-txs.ts around lines 32 to 54, the extracted
npm_config_* environment variables are left as strings but are expected to be
numeric ChainSlug values; convert and validate sourceChainSlug,
destinationChainSlug, startBlock, and endBlock to numbers immediately after
extraction (parseInt or Number), check for NaN and out-of-range/invalid values,
and exit with a clear error if validation fails so the script fails fast; then
update the usages at lines 59-60 and line 98 to reference the new numeric
variables (e.g., sourceChain, destinationChain, startBlockNum/endBlockNum)
instead of the original string variables.

Comment on lines +50 to +54
const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add validation for numeric chain slug

The script validates presence but not format of destinationChainSlug. This could cause runtime errors at lines 129, 142, and 186 when calling parseInt.

Add validation after line 53:

 const destinationChainSlug = process.env.npm_config_destination;
 if (!destinationChainSlug) {
   console.error("Error: destination flag is required");
   process.exit(1);
 }
+if (isNaN(parseInt(destinationChainSlug))) {
+  console.error("Error: destination must be a numeric chain slug");
+  process.exit(1);
+}
📝 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
const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}
const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}
if (isNaN(parseInt(destinationChainSlug))) {
console.error("Error: destination must be a numeric chain slug");
process.exit(1);
}
🤖 Prompt for AI Agents
In scripts/admin/send-attest.ts around lines 50 to 54, the destinationChainSlug
environment value is only checked for presence but not validated as a numeric
slug; add a validation after line 53 that ensures destinationChainSlug
represents an integer (e.g., test with a /^\d+$/ or attempt parseInt(base 10)
and check for NaN) and if invalid print a clear error to stderr and exit
non-zero so later parseInt calls at lines 129, 142, and 186 cannot receive
malformed input.

Comment on lines +32 to +47
const EXECUTION_CONFIG = {
executionDetails: {
packetId: "0x0000a4b129ebc834d24af22b9466a4150425354998c3e800000000000000cbe6", // Replace with actual packet ID
proposalCount: "0", // Replace with actual proposal count
executionGasLimit: "200000", // Replace with actual gas limit
decapacitorProof: "0x", // Replace with actual proof
},
messageDetails: {
msgId: "0x0000a4b126e5ce884875ea3776a57f0b225b1ea8d2e9beeb00000000000608cb", // Replace with actual message ID
executionFee: "0", // Replace with actual execution fee
minMsgGasLimit: "100000", // Replace with actual min gas limit
executionParams: "0x0000000000000000000000000000000000000000000000000000000000000000", // Replace with actual execution params
payload: "0x0000000000000000000000008cb4c89cc297e07c7a309af8b16cc2f5f62a3b1300000000000000000000000000000000000000000000000000000000062ebe4d", // Replace with actual payload
},
msgValue: "0", // ETH value to send with transaction (in wei)
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Hardcoded execution config is a critical design flaw

This EXECUTION_CONFIG object contains placeholder values that must be manually edited before each script execution. This defeats the purpose of an admin script and introduces human error risk.

Convert these to CLI flags similar to send-attest.ts:

  • --packetid
  • --proposalcount
  • --executiongaslimit
  • --decapacitorproof
  • --msgid
  • --executionfee
  • --minmsggaslimit
  • --executionparams
  • --payload
  • --msgvalue

This makes the script safer and scriptable for automation.

🤖 Prompt for AI Agents
In scripts/admin/send-execute.ts around lines 32 to 47, the EXECUTION_CONFIG is
hardcoded with placeholder values which must be converted to CLI flags; update
the script to parse command-line options (matching send-attest.ts style) for
--packetid, --proposalcount, --executiongaslimit, --decapacitorproof, --msgid,
--executionfee, --minmsggaslimit, --executionparams, --payload and --msgvalue,
validate required flags and provide helpful usage/errors, then build
EXECUTION_CONFIG from those parsed flag values (using sensible defaults where
applicable) before using it in the transaction flow; also update help/usage text
and ensure values are passed as strings and any numeric fields are
validated/converted appropriately.

Comment on lines +49 to +53
const destinationChainSlug = process.env.npm_config_destination;
if (!destinationChainSlug) {
console.error("Error: destination flag is required");
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add validation for numeric chain slug

Same issue as send-attest.ts - destinationChainSlug should be validated as numeric before parseInt calls at lines 72, 186, and 216.

Add after line 52:

 const destinationChainSlug = process.env.npm_config_destination;
 if (!destinationChainSlug) {
   console.error("Error: destination flag is required");
   process.exit(1);
 }
+if (isNaN(parseInt(destinationChainSlug))) {
+  console.error("Error: destination must be a numeric chain slug");
+  process.exit(1);
+}
🤖 Prompt for AI Agents
In scripts/admin/send-execute.ts around lines 49 to 53, destinationChainSlug is
only checked for presence but not that it is numeric; add validation immediately
after line 52 to ensure destinationChainSlug contains only digits (e.g. /^\d+$/
or Number parsing + Number.isInteger) and if not, print a clear error and exit;
this prevents unsafe parseInt calls later at lines 72, 186, and 216 by
guaranteeing a valid numeric slug before those parses.

Comment on lines +161 to +172
let maxFeePerGas = overrides.gasPrice;
if (!maxFeePerGas) {
const feeData = await provider.getFeeData();
const baseGasPrice =
feeData.maxFeePerGas || (await provider.getGasPrice());
const multiplier =
overrides.gasPriceMultiplier || DEFAULT_GAS_PRICE_MULTIPLIER;
maxFeePerGas = baseGasPrice
.mul(Math.round(multiplier * 100000))
.div(100000)
.toNumber();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Risk: BigNumber.toNumber() can overflow for large gas prices.

Lines 171 and 190 use .toNumber() on BigNumber values. This throws an error if the value exceeds Number.MAX_SAFE_INTEGER (approximately 9 × 10^15). High gas prices during network congestion could trigger this.

Keep values as BigNumber instead:

       const multiplier =
         overrides.gasPriceMultiplier || DEFAULT_GAS_PRICE_MULTIPLIER;
-      maxFeePerGas = baseGasPrice
+      maxFeePerGas = baseGasPrice
         .mul(Math.round(multiplier * 100000))
-        .div(100000)
-        .toNumber();
+        .div(100000);

Apply similar fix to the legacy transaction branch (lines 187-190).

Also applies to: 182-191

🤖 Prompt for AI Agents
scripts/constants/overrides.ts lines 161-172 (and similarly 182-191 / legacy
branch): the code calls .toNumber() on a BigNumber which can overflow; instead
keep and return a BigNumber throughout. Compute the scaled value using BigNumber
arithmetic (multiply by a BigNumber factor and div the same factor) and assign
the resulting BigNumber to maxFeePerGas (and the legacy maxGasPrice variable)
rather than converting to Number; if downstream expects a primitive, convert to
a string there or change the type to accept BigNumber.

Comment on lines +174 to +177
// Get base fee to calculate maxPriorityFeePerGas
const block = await provider.getBlock("latest");
const baseFee = block.baseFeePerGas?.toNumber() || 0;
const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix base fee calculation and priority fee logic.

Multiple issues:

  1. Fallback to 0: If baseFeePerGas is undefined, defaulting to 0 is incorrect. All blocks post-EIP-1559 have a base fee; undefined indicates a provider error or pre-EIP-1559 chain.

  2. Priority fee can be 0: Math.max(maxFeePerGas - baseFee, 0) can result in 0 if maxFeePerGas ≤ baseFee. Transactions with maxPriorityFeePerGas = 0 may never be included or face severe delays.

Apply this diff:

-    // Get base fee to calculate maxPriorityFeePerGas
-    const block = await provider.getBlock("latest");
-    const baseFee = block.baseFeePerGas?.toNumber() || 0;
-    const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
+    // Calculate maxPriorityFeePerGas
+    const feeData = await provider.getFeeData();
+    const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas?.toNumber() || 
+      Math.floor(maxFeePerGas * 0.1); // Fallback: 10% of maxFeePerGas

This uses the provider's recommended priority fee with a reasonable fallback.

📝 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
// Get base fee to calculate maxPriorityFeePerGas
const block = await provider.getBlock("latest");
const baseFee = block.baseFeePerGas?.toNumber() || 0;
const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
// Calculate maxPriorityFeePerGas
const feeData = await provider.getFeeData();
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas?.toNumber() ||
Math.floor(maxFeePerGas * 0.1); // Fallback: 10% of maxFeePerGas
🤖 Prompt for AI Agents
In scripts/constants/overrides.ts around lines 174-177, the code naively
defaults block.baseFeePerGas to 0 and sets maxPriorityFeePerGas =
Math.max(maxFeePerGas - baseFee, 0), which is incorrect; instead fetch the
latest block and assert baseFeePerGas is present (throw or surface an error if
undefined), then call provider.getFeeData() to get the
providerRecommendedPriority = feeData.maxPriorityFeePerGas; compute
desiredPriority = providerRecommendedPriority ?? a sensible fallback (e.g. 1.5
gwei), then set maxPriorityFeePerGas to the lesser of desiredPriority and
(maxFeePerGas - baseFee) but if that difference is <= 0 use the fallback
desiredPriority and ensure maxFeePerGas is adjusted or reject the tx; in short:
fail on missing baseFeePerGas, prefer provider.getFeeData().maxPriorityFeePerGas
with a small gwei fallback, and clamp priority to not exceed maxFeePerGas -
baseFee while avoiding a zero priority.

const block = await provider.getBlock("latest");
const baseFee = block.baseFeePerGas?.toNumber() || 0;
const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove debug console.log statement.

This console.log should not be in production code.

Apply this diff:

     const baseFee = block.baseFeePerGas?.toNumber() || 0;
     const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
-console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
     return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, type };
📝 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
console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
const baseFee = block.baseFeePerGas?.toNumber() || 0;
const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, type };
🤖 Prompt for AI Agents
In scripts/constants/overrides.ts around line 178, remove the debug
console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type) from
production code; either delete the statement entirely or replace it with the
project’s proper logging call at debug level (e.g., logger.debug with the same
structured message) and ensure no leftover console.* calls remain.

Comment on lines 28 to 30
[ChainSlug.PLASMA]: NativeTokens["plasma"],
[ChainSlug.MONAD]: NativeTokens["wormhole"],
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

MONAD currency mapping is likely wrong.

This should map to MONAD’s native token, not “wormhole”. MONAD_TESTNET maps to NativeTokens["monad"], but MONAD maps to NativeTokens["wormhole"], which will misprice gas/fees wherever Currency is used.

Action:

  • Replace with the correct MONAD mainnet token id (e.g., the same "monad" entry or a distinct MON mainnet key) once confirmed in native-tokens.ts.
  • Keep PLASMA -> "plasma" only if NativeTokens defines it.

Quick checks:

Consider typing Currency for safety:

  • export const Currency = { ... } as const satisfies Partial<Record<ChainSlug, keyof typeof NativeTokens>>;
    This should catch wrong keys at compile time.

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Verify NativeTokens keys exist:"
rg -nP 'export\s+const\s+NativeTokens' src/enums/native-tokens.ts -n -C3
rg -nP '"monad"|\"wormhole\"|\"plasma\"' src/enums/native-tokens.ts -n -C2

Length of output: 31


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Finding native-tokens.ts and currency.ts files ==="
fd -type f -name "native-tokens.ts"
fd -type f -name "currency.ts"

echo ""
echo "=== Checking currency.ts around lines 28-30 ==="
fd -type f -name "currency.ts" -exec cat {} \;

echo ""
echo "=== Checking for NativeTokens definition ==="
fd -type f -name "*.ts" | xargs rg -l "NativeTokens" | head -5

Length of output: 225


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Finding files ==="
fd currency.ts
fd native-tokens.ts

echo ""
echo "=== Search for MONAD and wormhole in TS files ==="
rg -n "MONAD.*wormhole|wormhole.*MONAD" --type ts -C2

echo ""
echo "=== Search for Currency enum ==="
rg -n "ChainSlug.MONAD\|ChainSlug.PLASMA" --type ts -C3

echo ""
echo "=== Search for NativeTokens definition ==="
rg -n "NativeTokens\s*=" --type ts -A10 | head -50

Length of output: 399


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== View native-tokens.ts ==="
cat src/enums/native-tokens.ts

echo ""
echo "=== Search for MONAD_TESTNET in currency.ts ==="
rg -n "MONAD_TESTNET" src/enums/currency.ts -C3

Length of output: 1112


Fix PLASMA and MONAD token mappings—both are broken.

  • Line 28 (PLASMA): Maps to NativeTokens["plasma"], but "plasma" is not defined in the NativeTokens enum. This will fail at runtime. Remove this entry or add "plasma" to NativeTokens if it's a valid coingecko ID.

  • Line 29 (MONAD): Maps to NativeTokens["wormhole"], but MONAD_TESTNET correctly uses NativeTokens["monad"]. Mainnet MONAD should use the same "monad" token for consistent native gas pricing. Change to NativeTokens["monad"].

  [ChainSlug.PLASMA]: NativeTokens["plasma"],  // ❌ "plasma" doesn't exist in NativeTokens
  [ChainSlug.MONAD]: NativeTokens["wormhole"],  // ❌ Should be NativeTokens["monad"]
🤖 Prompt for AI Agents
In src/enums/currency.ts around lines 28 to 30, the PLASMA and MONAD token
mappings are incorrect: PLASMA maps to NativeTokens["plasma"] which does not
exist (remove the PLASMA entry or add "plasma" to NativeTokens only if it's a
valid coingecko ID), and MONAD maps to NativeTokens["wormhole"] but should map
to NativeTokens["monad"] to match MONAD_TESTNET and ensure consistent native gas
token usage; update the PLASMA mapping accordingly (preferably remove it) and
change MONAD to NativeTokens["monad"].

"hyperliquid" = "hyperliquid",
"sei-network" = "sei-network",
"dogwifcoin" = "dogwifcoin",
"wormhole" = "wormhole",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify wormhole is the correct native token for MONAD

Confirm that "wormhole" (from CoinGecko) is the correct native token identifier for the MONAD blockchain. Token mappings must be accurate for pricing and display.


🌐 Web query:

What is the native token for MONAD blockchain and its CoinGecko identifier?

💡 Result:

  • Native token: MON (Monad). [1]
  • CoinGecko identifier (API / page ID): monad. [2]

Sources: CoinGecko coin page for Monad and CoinGecko overview article. [1][2]

References
[1] CoinGecko — Monad coin page (API ID: monad). (coingecko.com)
[2] CoinGecko — What Is Monad? overview (refers to the MON token). (coingecko.com)

Citations:


Remove incorrect wormhole token mapping

The native token for MONAD is MON, with CoinGecko identifier "monad", not "wormhole". Wormhole is a cross-chain messaging protocol, not MONAD's native token. This mapping will cause incorrect pricing lookups and display. Remove the wormhole entry from this enum.

🤖 Prompt for AI Agents
In src/enums/native-tokens.ts around line 23, the enum contains an incorrect
mapping '"wormhole" = "wormhole"'; remove this wormhole entry so MONAD's native
token mapping remains correct (ensure the enum retains the correct "monad" /
"MON" mapping elsewhere and update any references that depended on the removed
key to use the proper "monad" identifier), then run type checks and a quick grep
to fix any broken imports/usages.

Copy link

@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 (6)
src/enums/currency.ts (1)

28-30: Verify token mappings exist in NativeTokens enum.

Past review flagged that NativeTokens["plasma"] doesn't exist and would fail at runtime. MONAD mapping to NativeTokens["monad"] appears correct if "monad" is defined in the NativeTokens enum.

Run this script to verify both token IDs exist:

#!/bin/bash
# Description: Verify PLASMA and MONAD tokens exist in NativeTokens enum

echo "=== Checking NativeTokens enum definition ==="
cat src/enums/native-tokens.ts

echo ""
echo "=== Searching for 'plasma' token ==="
rg -n '"plasma"' src/enums/native-tokens.ts

echo ""
echo "=== Searching for 'monad' token ==="
rg -n '"monad"' src/enums/native-tokens.ts

echo ""
echo "=== All NativeTokens keys ==="
rg -n '^\s+[a-zA-Z0-9_-]+:' src/enums/native-tokens.ts

If "plasma" doesn't exist, either:

  1. Remove the PLASMA currency mapping, or
  2. Add "plasma" to NativeTokens with the correct CoinGecko ID
scripts/constants/overrides.ts (5)

124-131: Fix gas limit formatting for MONAD.

Line 130 uses 3_00_000 which is inconsistent with the formatting pattern used throughout the file (e.g., 6_000_000, 3_000_000). This should be 300_000 to clearly represent three hundred thousand.

Apply this diff:

   [ChainSlug.MONAD]: {
-    gasLimit: 3_00_000,
+    gasLimit: 300_000,
   },

159-180: Critical: Return type breaks consuming code + multiple calculation issues.

This EIP-1559 implementation has several problems already flagged in previous reviews:

  1. Return type incompatibility: Returns { gasLimit, maxFeePerGas, maxPriorityFeePerGas, type } but consumers like scripts/deploy/helpers/send-msg/utils.ts:127 expect gasPrice. This breaks relay transactions.

  2. BigNumber overflow: Lines 171 and 190 use .toNumber() which throws on values exceeding Number.MAX_SAFE_INTEGER. Keep values as BigNumber.

  3. Invalid priority fee calculation: Lines 174-177 default baseFeePerGas to 0 and can result in maxPriorityFeePerGas = 0, which causes transactions to stall. Use provider.getFeeData() for proper priority fee.

  4. Debug statement: Line 178 has a console.log that must be removed.


161-172: BigNumber.toNumber() overflow risk.

Line 171 (and 190 in the legacy branch) converts BigNumber to number, which throws if gas price exceeds Number.MAX_SAFE_INTEGER (~9 × 10^15). During network congestion, this can fail.

Keep BigNumber throughout and convert only at the final usage point if needed.


174-177: Fix base fee fallback and priority fee calculation.

Issues:

  1. Defaulting baseFeePerGas to 0 is incorrect - all post-EIP-1559 blocks have a base fee
  2. maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0) can be 0, causing transactions to stall

Use provider.getFeeData().maxPriorityFeePerGas with a sensible fallback (e.g., 1.5 gwei).


178-178: Remove debug console.log.

Production code should not contain debug console statements.

Apply this diff:

     const baseFee = block.baseFeePerGas?.toNumber() || 0;
     const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
-console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
     return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, type };
🧹 Nitpick comments (1)
scripts/constants/overrides.ts (1)

124-128: PLASMA configuration mixes legacy and EIP-1559 semantics.

Using gasPrice with type: 2 is confusing. For EIP-1559 transactions (type 2), the property should be named maxFeePerGas in the override config to match the transaction type semantics. While this works because line 161 reads overrides.gasPrice into maxFeePerGas, it creates confusion for maintainers.

Consider renaming the field in the ChainOverride type to clarify intent:

 type ChainOverride = {
   type?: number;
   gasLimit?: number;
   gasPrice?: number;
+  maxFeePerGas?: number;  // For EIP-1559 chains (type 2)
   gasPriceMultiplier?: number;
 };

Then update PLASMA:

   [ChainSlug.PLASMA]: {
     gasLimit: 5_000_000,
-    gasPrice: 1_000_000_000,
+    maxFeePerGas: 1_000_000_000,
     type: 2,
   },

And update line 161 to check both:

-    let maxFeePerGas = overrides.gasPrice;
+    let maxFeePerGas = overrides.maxFeePerGas || overrides.gasPrice;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45f7395 and 7e3704b.

📒 Files selected for processing (5)
  • deployments/prod_addresses.json (28 hunks)
  • hardhat.config.ts (3 hunks)
  • scripts/constants/overrides.ts (4 hunks)
  • scripts/rpcConfig/constants/version.ts (1 hunks)
  • src/enums/currency.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/rpcConfig/constants/version.ts
👮 Files not reviewed due to content moderation or server errors (1)
  • deployments/prod_addresses.json
🔇 Additional comments (3)
scripts/constants/overrides.ts (1)

31-31: LGTM - EIP-1559 enabled for Ethereum and Polygon.

Enabling type 2 transactions on MAINNET and POLYGON_MAINNET is correct, as both chains support EIP-1559. This allows the code to use maxFeePerGas and maxPriorityFeePerGas instead of legacy gasPrice.

Also applies to: 37-37

hardhat.config.ts (2)

134-134: LGTM - MONAD network added to production networks.

The network configuration correctly maps MONAD to its chain config and will be available when NODE_ENV=production.


198-198: API key mapping aligns with Etherscan endpoint.

Using ETHERSCAN_API_KEY is consistent with the apiURL configuration that routes through api.etherscan.io. If the endpoint verification confirms MONAD support, this mapping is correct.

Note: This approval is contingent on verifying that Etherscan actually supports MONAD chain ID 143 (see comment on lines 449-456).

Comment on lines +449 to +456
{
network: "monad",
chainId: ChainId.MONAD,
urls: {
apiURL: "https://api.etherscan.io/v2/api?chainid=143",
browserURL: "https://monadscan.com/",
},
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify Etherscan API endpoint supports MONAD chain ID 143.

The apiURL uses https://api.etherscan.io/v2/api?chainid=143, which routes through Etherscan's infrastructure. MONAD is a separate L1 blockchain - verify that Etherscan actually indexes MONAD (chain ID 143) before contracts can be verified on mainnet.

If Etherscan doesn't support MONAD yet, this configuration will fail during contract verification with hardhat verify.

Alternatively, search for Etherscan's supported chains:


🏁 Script executed:

#!/bin/bash
# Verify if Etherscan API v2 supports MONAD chain ID 143

echo "=== Testing Etherscan API for MONAD (chain ID 143) ==="
curl -s "https://api.etherscan.io/v2/api?chainid=143&module=proxy&action=eth_blockNumber" | jq '.'

echo ""
echo "=== Check if monadscan.com is reachable ==="
curl -s -o /dev/null -w "%{http_code}" "https://monadscan.com/"

echo ""
echo "=== Check Etherscan supported chains documentation ==="
echo "Verify at: https://docs.etherscan.io/v/etherscan-v2/"

Length of output: 292


🌐 Web query:

Does Etherscan API v2 support MONAD chain ID 143?

💡 Result:

Short answer: No — Etherscan API v2 does not list Monad mainnet (chain ID 143) as a supported chain; it lists Monad testnet (chain ID 10143). [1][2][3]

Sources:

  • Etherscan supported-chains (shows Monad Testnet 10143, not 143). [1]
  • Etherscan API V2 multichain overview. [2]
  • Monad docs (confirming Monad mainnet chain ID = 143). [3]

This configuration will fail contract verification—Etherscan API v2 doesn't support MONAD mainnet (chain ID 143).

Etherscan API v2 only supports Monad testnet (chain ID 10143), not mainnet (chain ID 143). The apiURL pointing to Etherscan will return errors when users attempt hardhat verify for MONAD mainnet contracts. Either:

  • Use a different verification service that supports MONAD, or
  • Remove the Etherscan configuration for MONAD until it's officially supported, or
  • Clarify in documentation that contract verification isn't available via Etherscan for MONAD mainnet
🤖 Prompt for AI Agents
In hardhat.config.ts around lines 449 to 456, the MONAD network block uses an
Etherscan v2 apiURL for chainId 143 which is unsupported and will break hardhat
verify; either remove the Etherscan configuration for MONAD, replace the apiURL
with a supported verification endpoint (or correct testnet chainId 10143 if you
intended testnet), or switch to a verification service that supports MONAD
mainnet; update the config accordingly and add a short comment explaining why
the Etherscan entry was removed/changed.

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