Skip to content

Conversation

@tHeMaskedMan981
Copy link
Collaborator

@tHeMaskedMan981 tHeMaskedMan981 commented Nov 3, 2025

Summary by CodeRabbit

  • New Features

    • Introduced unified 256-bit payload ID architecture with origin and verification components for enhanced cross-chain payload tracking.
    • Added payload ID verification mechanism with new error types for destination validation.
    • EVMX configuration support for switchboards to enable trigger payload generation.
  • API Updates

    • Renamed triggerAppGateway to sendPayload (returns payload ID).
    • Renamed processTrigger to processPayload (updated parameter and return signatures).
    • New PayloadRequested event for payload tracking.
  • Documentation

    • Added PAYLOAD_ID_ARCHITECTURE.md design specification.

@coderabbitai
Copy link

coderabbitai bot commented Nov 3, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (9)
  • main
  • master
  • dev
  • stage
  • prod
  • staging
  • development
  • production
  • release

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request refactors the payload identification system across the protocol. It replaces the trigger-based architecture with a unified 256-bit payload ID scheme encoding origin, verification, pointer, and reserved fields. Key changes include renaming processTrigger to processPayload in switchboards, updating Socket's verification flow to validate payload IDs against destination details, introducing payload ID encoding/decoding utilities, and propagating the new structure through test fixtures and contract interfaces.

Changes

Cohort / File(s) Change Summary
Payload ID Architecture Design
PAYLOAD_ID_ARCHITECTURE.md
New design document specifying 256-bit payload ID layout (origin, verification, pointer, reserved), per-payload-type creation schemes, decoding helpers in IdUtils.sol, and multi-contract update requirements.
Payload ID Core Utilities
contracts/utils/common/IdUtils.sol
Reworked createPayloadId to encode origin/verification components (originChainSlug, originId, verificationChainSlug, verificationId, pointer) in 256-bit layout. Added decodePayloadId, getVerificationInfo, getOriginInfo decoder functions.
Payload Reference Type
contracts/utils/common/Structs.sol
Changed ExecuteParams field from payloadPointer (uint160) to payloadId (bytes32), altering downstream payload identification.
Interface Definitions
contracts/protocol/interfaces/ISocket.sol, contracts/protocol/interfaces/ISwitchboard.sol
Renamed triggerAppGatewaysendPayload in ISocket with return type updated to payloadId. Renamed processTriggerprocessPayload in ISwitchboard, removed triggerId_ parameter, added payloadId_ return. Added PayloadRequested event to ISocket.
Socket Core Protocol
contracts/protocol/Socket.sol
Introduced InvalidVerificationChainSlug and InvalidVerificationSwitchboardId errors. Renamed outbound API from triggerAppGateway/_triggerAppGateway to sendPayload/_sendPayload with payloadId return. Updated execute flow to validate payloadId against destination via getVerificationInfo, reverting on mismatch. Updated fallback to return payloadId.
FastSwitchboard EVMX Integration
contracts/protocol/switchboard/FastSwitchboard.sol
Added state variables (evmxChainSlug, watcherId, triggerPayloadCounter), error (EvmxConfigNotSet), and event (EvmxConfigSet). New setEvmxConfig function for EVMX verification setup. Refactored processTriggerprocessPayload (external payable override onlySocket returns bytes32 payloadId), generating payloadId via createPayloadId with origin/verification encoding and counter increment.
MessageSwitchboard Multi-Chain Routing
contracts/protocol/switchboard/MessageSwitchboard.sol
Added siblingSwitchboardIds mapping for per-chain switchboard IDs. Extended setSiblingConfig with switchboardId_ parameter. Refactored processTriggerprocessPayload with payloadId return. Updated _createDigestAndPayloadId to compute payloadId from origin (chainSlug, switchboardId) and destination (dstChainSlug, dstSwitchboardId) via createPayloadId, setting prevBatchDigestHash to bytes32(0). Added PayloadRequested event emission.
Watcher EVMX Payload Creation
contracts/evmx/watcher/Watcher.sol
Updated getCurrentPayloadId to construct payload ID with explicit origin (evmxSlug, watcher id 1) and verification (destination chainSlug and switchboardId) plus nextPayloadCount as pointer.
Function Signature Documentation
FunctionSignatures.md
Updated entries in FastSwitchboard and MessageSwitchboard sections from processTrigger to processPayload (both retain signature 0x7f3352bc).
Test Infrastructure
test/SetupTest.t.sol
Updated DeploySetup to pass switchboardId to setSiblingConfig. Changed _getTriggerData to return (bytes32 payloadId, DigestParams) instead of (uint160 payloadPointer, DigestParams). Updated _executeOnDestination to accept payloadId_ instead of payloadPointer_. Modified _createDigestParams to remove triggerId_ parameter and set prevBatchDigestHash to bytes32(0). Changed ExecuteParams usage from payloadPointer to payloadId.
Payload ID Verification Test Suite
test/SocketPayloadIdVerification.t.sol
New comprehensive test file with 9 test functions: Socket.execute payload ID verification (correct destination, wrong chain slug, wrong switchboard ID), FastSwitchboard processPayload behavior (payload ID creation, event emission, counter increments, multiple unique IDs), and EVMX config validation (onlyOwner, EvmxConfigNotSet).
Existing Test Refinements
test/switchboard/MessageSwitchboard.t.sol
Added PayloadRequested event definition for test assertions on Native and Sponsored payload paths.
Deprecated Test Mocks
deprecated/test/mock/MockFastSwitchboard.sol, deprecated/test/protocol/switchboards/FastSwitchboardTest.t.sol
Updated function signatures from processTrigger to processPayload and call sites to match. Removed overrides_ parameter in MockFastSwitchboard.
Test Utilities
test/mocks/MockPlug.sol
Changed internal call from socket__.triggerAppGateway to socket__.sendPayload.
Hardhat Configuration
hardhat.config.ts
Switched network account configuration from dynamic private key (0x{privateKey}) to static HashZero constant.

Sequence Diagram(s)

sequenceDiagram
    participant Plug
    participant Socket
    participant FSB as FastSwitchboard
    participant Watcher
    participant Relayer

    Plug->>Socket: sendPayload(data) payable
    activate Socket
    Socket->>FSB: processPayload(plug, payload, overrides)
    activate FSB
    FSB->>FSB: validate EVMX config set
    FSB->>FSB: create payloadId = createPayloadId(origin, verification, pointer)
    FSB->>FSB: increment triggerPayloadCounter
    FSB-->>Socket: return payloadId
    deactivate FSB
    Socket-->>Plug: return payloadId
    deactivate Socket

    Note over Relayer: Off-chain indexing

    Relayer->>Socket: execute(ExecuteParams{payloadId, ...})
    activate Socket
    Socket->>Socket: verify payloadId via getVerificationInfo()
    alt Valid destination
        Socket->>FSB: _verify(payloadId, ...)
        activate FSB
        FSB-->>Socket: ✓
        deactivate FSB
        Socket->>Socket: execute payload
    else Invalid chainSlug
        Socket-->>Relayer: revert InvalidVerificationChainSlug
    else Invalid switchboardId
        Socket-->>Relayer: revert InvalidVerificationSwitchboardId
    end
    deactivate Socket
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • IdUtils.sol: Payload ID bit-packing scheme (192/128/64-bit layout for origin/verification/pointer). Verify encoding matches across all creation/decoding paths and doesn't overflow component values.
  • Socket.sol execute flow: Verification logic added in execute that extracts verification details from payloadId and validates against destination. Ensure getVerificationInfo extraction aligns with createPayloadId encoding.
  • FastSwitchboard.sol: EVMX config validation (must be set before processPayload), triggerPayloadCounter monotonic increment, and createPayloadId parameter order. Counter should never overflow or repeat per switchboard.
  • MessageSwitchboard.sol: _createDigestAndPayloadId now computes payloadId from destination switchboard IDs retrieved via siblingSwitchboardIds mapping. Validate that reverts occur when dstSwitchboardId is 0 and that digest handling correctly zeroes prevBatchDigestHash.
  • Test coverage in SocketPayloadIdVerification.t.sol: Validates cross-contract verification (Socket validates against FastSwitchboard's created payloadId). Ensure mock plug and setup correctly propagate payloadIds.
  • ExecuteParams migration: Field type change from uint160 to bytes32 should propagate without truncation. Verify all execute callers pass full payloadId.

Possibly related PRs

  • Deploy scripts #185: Updates switchboard function selectors/signatures for FastSwitchboard and MessageSwitchboard—directly related to processTrigger→processPayload renaming and ISwitchboard interface changes in this PR.
  • Socket test #186: Modifies Socket's verification and execution flow for payload/verification handling—overlaps with this PR's execute verification refactor using getVerificationInfo and InvalidVerification errors.
  • Merge again solana-triggers to dev-solana-v2  #195: Comprehensive switchboard/socket API refactor touching processTrigger→processPayload, ISwitchboard/Socket/FastSwitchboard/MessageSwitchboard changes, and IdUtils/Structs payload ID overhaul—core logic duplication with this PR.

Poem

🔄 From trigger to payload, the architecture blooms,
256 bits of origin and truth in its rooms,
Verification flows deep through socket's main gate,
Switchboards craft IDs that encode their fate. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly describes the main architectural change: a comprehensive update to how payload IDs are constructed, encoded, and verified across the codebase.

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

@tHeMaskedMan981 tHeMaskedMan981 changed the base branch from feat/message-switchboard to phase-1 November 3, 2025 14:34
@arthcp
Copy link
Contributor

arthcp commented Nov 6, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 6, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Caution

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

⚠️ Outside diff range comments (2)
hardhat.config.ts (1)

18-88: Restore non-zero private keys for configured networks

constants.HashZero is not a valid secp256k1 private key. Hardhat instantiates an ethers.Wallet for each entry in accounts, and new Wallet(HashZero) throws invalid private key at runtime. This should keep using a real signer (e.g., SOCKET_PRIVATE_KEY) or fail fast when it is missing, otherwise every network that hits getChainConfig will crash before any deployment or test runs.

-import { constants } from "ethers";
+// no additional import needed

-const privateKey: HardhatNetworkAccountUserConfig = process.env
-  .SOCKET_PRIVATE_KEY as unknown as HardhatNetworkAccountUserConfig;
+const socketPrivateKey = process.env.SOCKET_PRIVATE_KEY;
+if (!socketPrivateKey || /^0x0+$/.test(socketPrivateKey.replace(/^0x/, ""))) {
+  throw new Error("SOCKET_PRIVATE_KEY must be set to a non-zero hex private key");
+}

 function getChainConfig(chainSlug: ChainSlug): NetworkUserConfig {
   return {
-    accounts: [`${constants.HashZero}`],
+    accounts: [
+      socketPrivateKey.startsWith("0x") ? socketPrivateKey : `0x${socketPrivateKey}`,
+    ],
     chainId: ChainSlugToId[chainSlug],
     url: getJsonRpcUrl(chainSlug),
   };
 }
@@
   EVMX: {
-    accounts: [`0x${privateKey}`],
+    accounts: [
+      socketPrivateKey.startsWith("0x") ? socketPrivateKey : `0x${socketPrivateKey}`,
+    ],
     chainId: EVMX_CHAIN_ID,
     url: process.env.EVMX_RPC,
   },
deprecated/test/mock/MockFastSwitchboard.sol (1)

48-54: Signature mismatch breaks compilation

This should implement the new ISwitchboard.processPayload signature exactly. The extra triggerId_ parameter and missing return value leave the override invalid, so the contract will not compile after the interface change.

Apply this diff to realign the mock:

-function processPayload(
-    address plug_,
-    bytes32 triggerId_,
-    bytes calldata payload_,
-    bytes calldata overrides_
-) external payable override {
-    // Simple implementation that just accepts the trigger
-    // In a real switchboard, this would process the trigger
-}
+function processPayload(
+    address plug_,
+    bytes calldata payload_,
+    bytes calldata overrides_
+) external payable override returns (bytes32 payloadId_) {
+    // Simple implementation that just accepts the payload
+    payloadId_ = keccak256(abi.encodePacked(plug_, payload_, overrides_));
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 053fd3c and 4c55c6a.

📒 Files selected for processing (17)
  • FunctionSignatures.md (2 hunks)
  • PAYLOAD_ID_ARCHITECTURE.md (1 hunks)
  • contracts/evmx/watcher/Watcher.sol (1 hunks)
  • contracts/protocol/Socket.sol (7 hunks)
  • contracts/protocol/interfaces/ISocket.sol (2 hunks)
  • contracts/protocol/interfaces/ISwitchboard.sol (1 hunks)
  • contracts/protocol/switchboard/FastSwitchboard.sol (4 hunks)
  • contracts/protocol/switchboard/MessageSwitchboard.sol (7 hunks)
  • contracts/utils/common/IdUtils.sol (1 hunks)
  • contracts/utils/common/Structs.sol (1 hunks)
  • deprecated/test/mock/MockFastSwitchboard.sol (1 hunks)
  • deprecated/test/protocol/switchboards/FastSwitchboardTest.t.sol (2 hunks)
  • hardhat.config.ts (2 hunks)
  • test/SetupTest.t.sol (7 hunks)
  • test/SocketPayloadIdVerification.t.sol (1 hunks)
  • test/mocks/MockPlug.sol (1 hunks)
  • test/switchboard/MessageSwitchboard.t.sol (21 hunks)
🧰 Additional context used
🪛 LanguageTool
PAYLOAD_ID_ARCHITECTURE.md

[grammar] ~24-~24: Ensure spelling is correct
Context: ...cher (on EVMX) - Verified by: Watcher offchain (links source) - Verification: `dst...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~36-~36: Ensure spelling is correct
Context: ...astSwitchboard - Verified by: Watcher offchain (verifies source) - Verification: `...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~120-~120: Ensure spelling is correct
Context: ...tches local config 2. Source (Watcher offchain): Verifies origin component matches e...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🔇 Additional comments (4)
FunctionSignatures.md (1)

365-393: Docs now mirror the ABI rename

The signature table now matches the processPayload entry point exposed by the switchboards, so downstream consumers will see the correct selector. This should ship with the contract rename.

test/mocks/MockPlug.sol (1)

41-41: Mock aligns with new outbound API

Switching to socket__.sendPayload keeps the return type while exercising the same payable flow the contracts now expose. This should keep the mock in sync with the production interface.

deprecated/test/protocol/switchboards/FastSwitchboardTest.t.sol (1)

24-151: Test coverage keeps pace with the rename

Updating both the override and the call site to processPayload ensures the event emission path is still exercised after the contract rename. This should maintain the existing assertion coverage.

contracts/utils/common/Structs.sol (1)

73-82: ExecuteParams now transports payloadId

Replacing payloadPointer with payloadId keeps the 32-byte layout while matching the new payload-ID pipeline, so the execution path reads the same identifier produced by the switchboards.

Comment on lines 336 to 337
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData:"0x"
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

Fix extraData to true empty bytes
This should store an empty byte array. The literal "0x" encodes two bytes (0x30, 0x78), so the digest we hash now includes those extra characters. Off-chain signers using empty extraData will compute a different digest and their attestations will be rejected. Swap to hex"" (or bytes("")) so the digest stays compatible.

-            prevBatchDigestHash: bytes32(0), // No longer using triggerId
-            extraData:"0x"
+            prevBatchDigestHash: bytes32(0), // No longer using triggerId
+            extraData: hex""
📝 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
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData:"0x"
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData: hex""
🤖 Prompt for AI Agents
contracts/protocol/switchboard/MessageSwitchboard.sol around lines 336-337: the
extraData field is currently set to the string literal "0x", which encodes the
characters '0' and 'x' into the digest; replace it with a true empty bytes value
(e.g. hex"" or bytes("")) so the serialized digest matches off‑chain signers
expecting empty extraData; update the assignment to use hex"" (or bytes("")) and
run tests/attestation flow to confirm digest compatibility.

Comment on lines 899 to 901
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData: "0x" // Contract now sets extraData to empty
});
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

Align test fixture with empty extraData
This should mirror the production struct. After fixing extraData to actual empty bytes, these fixtures need to expect hex""; otherwise the digest constructed in tests will diverge from the contract.

-            prevBatchDigestHash: bytes32(0), // No longer using triggerId
-            extraData: "0x" // Contract now sets extraData to empty
+            prevBatchDigestHash: bytes32(0), // No longer using triggerId
+            extraData: hex"" // Contract now sets extraData to empty
📝 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
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData: "0x" // Contract now sets extraData to empty
});
prevBatchDigestHash: bytes32(0), // No longer using triggerId
extraData: hex"" // Contract now sets extraData to empty
});
🤖 Prompt for AI Agents
In test/SetupTest.t.sol around lines 899 to 901, the test fixture uses
extraData: "0x" but the production contract sets extraData to empty bytes
(hex""); update the fixture and any expected digest construction to use empty
bytes (hex"") instead of the string "0x" so the test encodes the same byte
sequence as the contract and the computed digest matches production.

@arthcp arthcp merged commit 3c8f98f into phase-1 Nov 8, 2025
1 check passed
@arthcp arthcp deleted the feat/id branch November 8, 2025 12:04
@coderabbitai coderabbitai bot mentioned this pull request Nov 8, 2025
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.

3 participants