Skip to content

Conversation

@ameeshaagrawal
Copy link
Collaborator

@ameeshaagrawal ameeshaagrawal commented Nov 7, 2025

Summary by CodeRabbit

Release Notes

  • New Features
    • Added deadline support for asynchronous operations with configurable default deadlines.
    • Introduced reverting trigger mechanism for enhanced control over trigger execution.
    • Enhanced fee settlement logic with improved transmitter and watcher fee handling.
    • Added deadline validation for app gateway calls to prevent expired executions.

@coderabbitai
Copy link

coderabbitai bot commented Nov 7, 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 PR introduces deadline-based expiration for promises/triggers across the protocol, refactors transmitter fee settlement in the watcher, updates fee management to support amount-based blocking/unblocking, adds default deadline tracking to switchboards with reverting trigger support, and modifies processTrigger to return overrides data. Multiple formatting corrections applied across Solana utilities.

Changes

Cohort / File(s) Summary
Fee Management
contracts/evmx/fees/FeesManager.sol, contracts/evmx/interfaces/IFeesManager.sol
Updated unblockAndAssignCredits to accept amount_ parameter; now decrements userBlockedCredits and blockedCredits by specified amount instead of fixed value, removes storage cleanup, burns/mints tokens accordingly.
Message Resolution
contracts/evmx/fees/MessageResolver.sol
MessageDetailsAdded event signature expanded to include srcChainSlug, dstChainSlug, srcPlug, dstPlug, sponsor, transmitter, feeAmount, deadline alongside existing payloadId.
Async Promise Infrastructure
contracts/evmx/helpers/AsyncPromise.sol
Added promiseDeadline state variable, deadline parameter to initialize, deadline expiration check in markResolved and markOnchainRevert, new PromiseAlreadyResolved error, relaxed state transition guards.
Async Deployer
contracts/evmx/helpers/AsyncDeployer.sol
Added defaultDeadline storage variable, extended initialize signature to accept deadline parameter, propagates deadline to AsyncPromise.initialize calls.
Watcher
contracts/evmx/watcher/Watcher.sol
Added isTransmitterFeesSettled flag to Payload tracking, refactored _resolvePayload to settle transmitter fees via unblockAndAssignCredits before processing, added deadline check in _callAppGateways, updated cancelExecution settlement logic.
Switchboard Core
contracts/protocol/switchboard/SwitchboardBase.sol
Added revertingTriggers mapping to track reverting trigger states.
Fast Switchboard
contracts/protocol/switchboard/FastSwitchboard.sol
Added defaultDeadline (1 day), RevertingTriggerSet and DefaultDeadlineSet events, processTrigger now returns overridesData with deadline extraction logic, added setRevertingTrigger and setDefaultDeadline setters.
Message Switchboard
contracts/protocol/switchboard/MessageSwitchboard.sol
Added defaultDeadline (1 day), RevertingTriggerSet event, setRevertingTrigger setter, processTrigger returns overridesData, changed _decodeOverrides from pure to non-pure with deadline parsing logic.
Core Protocol
contracts/protocol/Socket.sol, contracts/protocol/SocketConfig.sol, contracts/protocol/interfaces/ISwitchboard.sol
Socket: _triggerAppGateway captures overridesData from processTrigger, _increaseFeesForPayload passes msg.sender to switchboard, _verifyPlugSwitchboard validates switchboard status. ISwitchboard: processTrigger signature updated to return bytes memory overridesData. SocketConfig: formatting adjustments only.
Data Structures
contracts/utils/common/Structs.sol
Added isTransmitterFeesSettled boolean to Payload struct, deadline uint256 to MessageOverrides struct.
Solana Utils Formatting
contracts/evmx/helpers/solana-utils/Ed25519.sol, Ed25519_pow.sol, Sha512.sol, SolanaPda.sol, SolanaSignature.sol, program-pda/FeesPlugPdas.sol, contracts/evmx/watcher/borsh-serde/BorshDecoder.sol, BorshEncoder.sol, BorshUtils.sol, contracts/evmx/watcher/precompiles/WritePrecompile.sol
Trailing newlines corrected, unnecessary blank lines removed. No functional changes.
Test Infrastructure
test/SetupTest.t.sol, test/Utils.t.sol, test/mocks/MockPlug.sol, test/switchboard/MessageSwitchboard.t.sol
SetupTest: added defaultDeadline state and propagation to AsyncDeployer; MessageSwitchboard.t.sol: deadline values (86400) added to override construction; formatting adjustments across test files.
Deployment Scripts
hardhat-scripts/deploy/6.connect.ts, script/counter/IncrementCountersFromApp.s.sol
Formatting only; ABI encoding type array reformatted to multiline, unused blank lines removed.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant Socket
    participant Switchboard
    participant Watcher
    participant AsyncPromise
    participant FeesManager

    App->>Socket: triggerAppGateway(data, plugOverrides)
    Socket->>Switchboard: processTrigger(plug, triggerId, payload, overrides)
    Note over Switchboard: Extract/apply defaultDeadline<br/>if not in overrides
    Switchboard-->>Socket: return overridesData (with deadline)
    Socket->>Socket: Emit AppGatewayCallRequested<br/>(using overridesData)
    
    Socket->>Watcher: resolve(payloadId, data)
    Note over Watcher: Check deadline expired?
    alt Deadline not exceeded
        Watcher->>FeesManager: unblockAndAssignCredits<br/>(payloadId, transmitter, amount)
        FeesManager->>FeesManager: Burn amount from consumeFrom<br/>Mint amount to assignTo
        Watcher->>AsyncPromise: markResolved(payloadId)
        Note over AsyncPromise: Check promiseDeadline<br/>Revert if exceeded
        AsyncPromise->>AsyncPromise: Update state to RESOLVED
    else Deadline exceeded
        AsyncPromise-->>Watcher: DeadlinePassed revert
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Watcher fee settlement refactoring (Watcher.sol): Changed from _settlePayload to unblockAndAssignCredits call with per-transmitter amount tracking. Requires verification of fee calculation, isTransmitterFeesSettled flag state machine, and settlement timing in resolve/cancel paths.
  • Switchboard deadline mechanism (FastSwitchboard.sol, MessageSwitchboard.sol): New processTrigger return value propagation, deadline extraction/application logic, and state variable introduction. Verify deadline encoding/decoding consistency and default application correctness.
  • AsyncPromise deadline enforcement (AsyncPromise.sol, Watcher.sol): Added deadline checks that revert execution. Ensure promiseDeadline initialization (deadline_ + block.timestamp) is correct and deadline guard in _callAppGateways matches expected semantics.
  • Fee accounting changes (FeesManager.sol): Amount-based blocking instead of fixed values, removal of storage cleanup. Verify that userBlockedCredits accounting remains consistent across all unblock/assign paths and that blockedCredits is properly decremented.
  • Struct field additions (Structs.sol, Watcher.sol): New isTransmitterFeesSettled and deadline fields in widely-used structs. Check for missed initialization sites and ensure backward compatibility if needed.

Possibly related PRs

  • Merge again solana-triggers to dev-solana-v2  #195: Introduces identical unblockAndAssignCredits signature expansion (amount_ parameter) and fee-accounting refactor from fixed to amount-based decrements with burn/mint logic.
  • Deploy scripts #185: Modifies FeesManager/IFeesManager interfaces and propagates switchboard ID changes across deploy configuration, closely tied to fee settlement changes here.
  • Script and proxy changes #196: Updates FeesManager's unblockAndAssignCredits with amount-based accounting and blocked credits consumption patterns matching this PR's approach.

Poem

⏳ Deadlines now tick through the chain—
Promises expire, fees maintain their reign,
Switchboards know what's reverting today,
Amounts unlock in a cleaner way. 🔓

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Fix watcher' is vague and generic. It doesn't convey what specific issue is being fixed or what changes are made. Replace with a specific title describing the main change, such as 'Add deadline mechanism and transmitter fee settlement to watcher' or 'Implement deadline checks and refactor fees settlement logic'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

@arthcp
Copy link
Contributor

arthcp commented Nov 8, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 8, 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: 6

Caution

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

⚠️ Outside diff range comments (3)
contracts/evmx/watcher/precompiles/WritePrecompile.sol (2)

186-199: Fix missing gasLimit assignment when user provides non-zero value.

The _validate function only handles the case where rawPayload_.overrideParams.gasLimit == 0, setting defaults for each chain. If a user provides a non-zero gasLimit, the function returns with an uninitialized gasLimit (0), silently dropping the user's override. This breaks the override mechanism.

Apply this diff to fix the logic:

-        if (rawPayload_.overrideParams.gasLimit == 0) {
+        gasLimit = rawPayload_.overrideParams.gasLimit;
+        if (gasLimit == 0) {
             if (rawPayload_.transaction.chainSlug == 5000) {
                 // Mantle default gas limit
                 gasLimit = 8_000_000_000;
             } else if (rawPayload_.transaction.chainSlug == 1329) {
                 // Sei default gas limit
                 gasLimit = 8_000_000;
             } else if (rawPayload_.transaction.chainSlug == 999) {
                 // HyperEVM default gas limit
                 gasLimit = 1_500_000;
             } else {
                 gasLimit = 10_000_000; // other chains default gas limit
             }
         }
+        return gasLimit;

273-278: Remove hardcoded Solana addresses before production.

Lines 273–278 contain explicit TODO comments about hardcoded socket and transmitter addresses for Solana. These placeholders should be replaced with dynamic configuration before this contract goes live, as hardcoded values will break if addresses change and prevent multi-environment deployment.

contracts/protocol/interfaces/ISwitchboard.sol (1)

34-39: Two ISwitchboard implementations still missing the return type—compilation will fail.

The interface now requires processTrigger to return bytes memory overridesData, but these implementations haven't been updated:

  • deprecated/test/protocol/switchboards/FastSwitchboardTest.t.sol (lines 24–31)
  • deprecated/test/mock/MockFastSwitchboard.sol (lines 48–56)

Both have the override keyword and will violate the new interface signature. Add returns (bytes memory overridesData) to both and return an appropriate value (even if just bytes(0) for test mocks).

🧹 Nitpick comments (4)
contracts/evmx/watcher/Watcher.sol (1)

138-141: Settlement flag timing creates atomicity risk.

Setting isTransmitterFeesSettled = true before calling feesManager__().unblockAndAssignCredits() means that if the unblock call reverts, the flag will remain true in storage (since the entire transaction reverts), but on retry, the settlement logic will be skipped. This is actually safe because the whole transaction reverts atomically. However, the pattern is slightly inconsistent with Line 150-151 where settlement happens after successful operations.

For consistency and clarity, consider whether the flag should be set after successful unblock, though the current implementation is functionally correct due to transaction atomicity.

contracts/protocol/switchboard/FastSwitchboard.sol (1)

120-123: Consider adding bounds validation for deadline.

The setDefaultDeadline function accepts any uint256 value without validation. Consider adding reasonable bounds:

  • Minimum: e.g., 1 hour (3600 seconds) to prevent accidentally setting too short deadlines
  • Maximum: e.g., 30 days (2592000 seconds) to prevent excessive deadline periods
 function setDefaultDeadline(uint256 defaultDeadline_) external onlyOwner {
+    require(defaultDeadline_ >= 1 hours && defaultDeadline_ <= 30 days, "Invalid deadline range");
     defaultDeadline = defaultDeadline_;
     emit DefaultDeadlineSet(defaultDeadline_);
 }

This prevents configuration errors that could cause operational issues.

contracts/evmx/helpers/AsyncPromise.sol (2)

84-93: Consider validating deadline parameter.

The initialize function accepts deadline_ without validation and sets promiseDeadline = deadline_ + block.timestamp. Consider adding bounds checking:

 function initialize(
     bytes32 payloadId_,
     address invoker_,
     address addressResolver_,
     uint256 deadline_
 ) public reinitializer(1) {
+    require(deadline_ > 0 && deadline_ <= 30 days, "Invalid deadline duration");
     localInvoker = invoker_;
     payloadId = payloadId_;
     _setAddressResolver(addressResolver_);
     promiseDeadline = deadline_ + block.timestamp;
 }

This prevents:

  • Deadline of 0 (immediate expiration)
  • Excessively long deadlines that could cause operational issues

102-103: Consider reordering checks for clarity.

The current order checks the deadline before the state:

if (block.timestamp > promiseDeadline) revert DeadlinePassed();
if (state == AsyncPromiseState.RESOLVED || state == AsyncPromiseState.ONCHAIN_REVERTING) revert PromiseAlreadyResolved();

If a promise is already resolved and the deadline has passed, this reverts with DeadlinePassed instead of PromiseAlreadyResolved.

Consider reversing the order for clearer error messages:

+if (state == AsyncPromiseState.RESOLVED || state == AsyncPromiseState.ONCHAIN_REVERTING) revert PromiseAlreadyResolved();
 if (block.timestamp > promiseDeadline) revert DeadlinePassed();
-if (state == AsyncPromiseState.RESOLVED || state == AsyncPromiseState.ONCHAIN_REVERTING) revert PromiseAlreadyResolved();

This ensures that if a promise is already resolved, the error message reflects that fact rather than indicating a deadline issue.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff6dfaf and 5b62e53.

📒 Files selected for processing (29)
  • contracts/evmx/fees/FeesManager.sol (1 hunks)
  • contracts/evmx/fees/MessageResolver.sol (7 hunks)
  • contracts/evmx/helpers/AsyncDeployer.sol (3 hunks)
  • contracts/evmx/helpers/AsyncPromise.sol (6 hunks)
  • contracts/evmx/helpers/solana-utils/Ed25519.sol (1 hunks)
  • contracts/evmx/helpers/solana-utils/Ed25519_pow.sol (1 hunks)
  • contracts/evmx/helpers/solana-utils/Sha512.sol (1 hunks)
  • contracts/evmx/helpers/solana-utils/SolanaPda.sol (1 hunks)
  • contracts/evmx/helpers/solana-utils/SolanaSignature.sol (1 hunks)
  • contracts/evmx/helpers/solana-utils/program-pda/FeesPlugPdas.sol (1 hunks)
  • contracts/evmx/interfaces/IFeesManager.sol (1 hunks)
  • contracts/evmx/watcher/Watcher.sol (4 hunks)
  • contracts/evmx/watcher/borsh-serde/BorshDecoder.sol (1 hunks)
  • contracts/evmx/watcher/borsh-serde/BorshEncoder.sol (1 hunks)
  • contracts/evmx/watcher/borsh-serde/BorshUtils.sol (1 hunks)
  • contracts/evmx/watcher/precompiles/WritePrecompile.sol (2 hunks)
  • contracts/protocol/Socket.sol (5 hunks)
  • contracts/protocol/SocketConfig.sol (4 hunks)
  • contracts/protocol/interfaces/ISwitchboard.sol (3 hunks)
  • contracts/protocol/switchboard/FastSwitchboard.sol (5 hunks)
  • contracts/protocol/switchboard/MessageSwitchboard.sol (17 hunks)
  • contracts/protocol/switchboard/SwitchboardBase.sol (2 hunks)
  • contracts/utils/common/Structs.sol (2 hunks)
  • hardhat-scripts/deploy/6.connect.ts (2 hunks)
  • script/counter/IncrementCountersFromApp.s.sol (0 hunks)
  • test/SetupTest.t.sol (4 hunks)
  • test/Utils.t.sol (1 hunks)
  • test/mocks/MockPlug.sol (1 hunks)
  • test/switchboard/MessageSwitchboard.t.sol (15 hunks)
💤 Files with no reviewable changes (1)
  • script/counter/IncrementCountersFromApp.s.sol
🔇 Additional comments (27)
contracts/evmx/helpers/solana-utils/Sha512.sol (1)

278-278: No functional changes to review.

This file contains only a trailing newline addition. The SHA512 implementation remains unchanged and correct.

contracts/evmx/watcher/borsh-serde/BorshEncoder.sol (1)

317-317: Trailing newline addition.

This is a formatting-only change with no functional impact.

contracts/evmx/helpers/solana-utils/SolanaSignature.sol (1)

1-17: LGTM—formatting aligned with best practices.

This is purely a formatting fix (EOF newline). The contract logic is unchanged: verifyMessage correctly delegates to Ed25519.verify and returns the result. No correctness, security, or functionality concerns.

contracts/evmx/helpers/solana-utils/SolanaPda.sol (1)

270-270: Formatting correction applied correctly.

Adding the trailing newline to the file end is a standard linting convention and causes no functional change. This aligns with the PR's formatting improvements across Solana utilities.

hardhat-scripts/deploy/6.connect.ts (2)

4-8: Formatting improvement for imports.

Multi-line grouped import improves readability and aligns with the formatting consistency observed across this PR.


177-179: Good formatting of complex ABI type string.

Splitting the ABI type array across multiple lines improves readability of the complex tuple structure. The trailing comma enables cleaner future diffs if additional types are added. The type string itself remains functionally correct.

contracts/evmx/helpers/solana-utils/Ed25519_pow.sol (1)

1-329: Formatting-only change; no functional updates.

This file contains only a trailing newline adjustment. The Ed25519 cryptographic implementation itself remains unchanged and is unaffected by the PR's core logic changes (watcher refactoring, deadline-based expiration, fee settlement). The code is correct.

contracts/evmx/watcher/borsh-serde/BorshDecoder.sol (1)

359-359: Trailing newline formatting aligns with best practices.

This change is purely stylistic—adding a newline at EOF follows POSIX conventions and improves consistency with the rest of the codebase as mentioned in the PR summary.

contracts/evmx/helpers/solana-utils/Ed25519.sol (1)

906-906: Non-functional formatting change only.

This file shows only a trailing newline correction at the end of the file. Since this is a non-functional formatting fix and the Ed25519 library implementation remains unchanged, no code review is warranted here. This change appears orthogonal to the PR's primary objectives around watcher fixes and deadline-based expiration.

contracts/evmx/watcher/precompiles/WritePrecompile.sol (1)

97-97: Clarify intent of commented-out _initializeWatcher call.

Line 97 has a commented-out call to _initializeWatcher. Confirm whether this is intentional (e.g., feature flag, temporary debug) or if it should be removed or restored.

contracts/protocol/SocketConfig.sol (1)

30-30: LGTM - Formatting changes improve readability.

The multi-line formatting applied to function calls and conditionals is consistent and makes the code more readable without any behavioral impact.

Also applies to: 124-127, 131-134, 146-146, 190-193

contracts/evmx/watcher/Watcher.sol (4)

104-104: LGTM: Proper initialization of settlement flag.

The new isTransmitterFeesSettled field is correctly initialized to false when the payload is created.


223-224: LGTM: Deadline validation is correct.

The deadline check correctly prevents late triggers by reverting when deadline < block.timestamp (deadline is in the past).


150-152: The three-way credit split is correct; verify upstream validation prevents underflow.

The settlement correctly splits credits three ways:

  1. unblockAndAssignCredits(..., transmitter, feesUsed_) assigns fees to transmitter
  2. unblockAndAssignCredits(..., watcher, watcherFees) assigns fees to watcher
  3. unblockCredits(payloadId) returns the remainder to consumeFrom

Each call reduces blockedCredits[payloadId] by its amount, so the remainder is properly returned to the original user. The implementation is intentional and safe.

However, ensure that upstream code (where p.watcherFees and feesUsed_ are calculated) validates that feesUsed_ + watcherFees ≤ maxFees. If either amount exceeds what remains in blockedCredits, the userBlockedCredits subtraction will underflow.


277-278: Cancel execution fee distribution is correct; naming is misleading but logic is sound.

The original concern mischaracterizes the cancellation scenario. cancelExecution() is not cancelling an unused payload—it settles fees for a failed execution attempt.

The code calls cancelExecution() when:

  • markOnchainRevert(): execution was attempted and reverted onchain (after deadline)
  • _revertTx(): explicit revert of an attempted execution

In these scenarios, the transmitter deserves compensation for work attempted. The fee split—transmitter gets maxFees - watcherFees, watcher gets watcherFees—is intentional and mirrors the success path where both parties are paid.

The weak point is naming: cancelExecution obscures that this settles failed executions, not unused payloads. Better naming would reduce confusion, but the logic itself is correct.

Likely an incorrect or invalid review comment.

test/switchboard/MessageSwitchboard.t.sol (1)

223-223: LGTM: Test overrides correctly updated with deadline field.

All test cases now include deadline: 86400 (1 day in seconds) in their overrides, which correctly aligns with:

  • The new deadline field in MessageOverrides struct
  • The defaultDeadline = 1 days in switchboard contracts
  • The deadline validation logic introduced in the PR

The consistent use of 86400 across all tests ensures proper coverage of the deadline feature.

Also applies to: 259-259, 452-452, 521-521, 534-534, 625-625, 636-636, 1018-1018, 1066-1066, 1116-1116

contracts/evmx/helpers/AsyncDeployer.sol (1)

147-148: LGTM: Deadline correctly propagated to AsyncPromise.

The defaultDeadline is properly included in the initialization data for AsyncPromise contracts, ensuring promises are created with the correct deadline configuration.

contracts/protocol/switchboard/FastSwitchboard.sol (3)

14-14: LGTM: Default deadline set to reasonable value.

Setting defaultDeadline = 1 days provides a reasonable default expiration period for payloads.


86-95: Verify overrides structure consistency between switchboards.

FastSwitchboard's processTrigger:

  • Decodes overrides_ as a single uint256 deadline
  • Returns either the original overrides_ or a new encoded deadline

However, MessageSwitchboard's processTrigger (lines 166-174):

  • Decodes overrides_ as a complex MessageOverrides struct (version, dstChainSlug, gasLimit, value, refundAddress, deadline, etc.)
  • Returns abi.encode(overrides) with the full struct

This inconsistency means:

  1. FastSwitchboard and MessageSwitchboard expect different overrides formats
  2. The ISwitchboard interface doesn't specify the overrides structure
  3. AppGateways using different switchboards must provide different override formats

This is acceptable if intentional (different switchboards have different requirements), but should be documented clearly. Verify that:

  • This design is intentional
  • AppGateways know which override format to use for their connected switchboard
  • The difference in complexity is justified (MessageSwitchboard needs more fields for messaging)

115-118: LGTM: Setter properly restricted to owner.

The setRevertingTrigger function correctly uses onlyOwner modifier and emits an appropriate event.

contracts/protocol/Socket.sol (3)

216-228: LGTM: Switchboard can now normalize overrides before emission.

Capturing overridesData from processTrigger and using it in the AppGatewayCallRequested event allows switchboards to:

  • Apply default values (e.g., deadline)
  • Normalize the overrides format
  • Return computed values back to the event for off-chain tracking

This improves flexibility and ensures emitted events reflect the actual overrides that will be used.


238-244: LGTM: Passing sender enables authorization in switchboard.

Adding msg.sender to the increaseFeesForPayload call allows the switchboard to verify that the plug attempting to increase fees is the same plug that created the payload. This prevents unauthorized fee manipulation.


252-253: LGTM: Stricter switchboard validation improves security.

Adding the check isValidSwitchboard[switchboardId] != SwitchboardStatus.REGISTERED ensures that only fully registered switchboards can be used. This prevents operations on switchboards in intermediate or invalid states.

contracts/evmx/helpers/AsyncPromise.sol (1)

65-65: LGTM: New error appropriately defines the rejection case.

The PromiseAlreadyResolved error clearly communicates when a promise cannot be resolved again.

contracts/protocol/switchboard/MessageSwitchboard.sol (3)

46-46: LGTM: Consistent default deadline across switchboards.

Setting defaultDeadline = 1 days matches FastSwitchboard's default, providing consistency across the protocol.


166-174: LGTM: Overrides properly decoded, defaulted, and returned.

The pattern of:

  1. Decode overrides
  2. Apply defaults (in _decodeOverrides)
  3. Re-encode and return

Ensures that the returned overridesData contains the complete, normalized overrides with all defaults applied.


240-242: LGTM: Correct removal of pure modifier.

Changing _decodeOverrides from internal pure to internal is necessary because the function now accesses state (defaultDeadline) and uses block.timestamp, which are not allowed in pure functions.

@ameeshaagrawal ameeshaagrawal merged commit bb20519 into solana-phase1 Nov 12, 2025
1 check passed
@ameeshaagrawal ameeshaagrawal deleted the fix-watcher branch November 12, 2025 10:09
@coderabbitai coderabbitai bot mentioned this pull request Nov 13, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 24, 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.

4 participants