Skip to content

feat: add better error decoding on set-root/execute steps, and skip z…#848

Open
ecPablo wants to merge 4 commits intomainfrom
ecpablo/fix-fork-tests-display
Open

feat: add better error decoding on set-root/execute steps, and skip z…#848
ecPablo wants to merge 4 commits intomainfrom
ecpablo/fix-fork-tests-display

Conversation

@ecPablo
Copy link
Contributor

@ecPablo ecPablo commented Mar 11, 2026

  • MCMS.execute and MCMS.set-root did not have recursive error decoding. In cases where the mcms.execute is a bypass execution from timelock, or some permission error related to the mcms contract itself, the decoding logic just decoded the first error, not the inner txs errors. This hooks up the ErrorDecoder object so it uses the same logic as the timelock execution.
  • Fork tests are not yet supported for zksync, causing false negatives. Added proper logic to skip zksync chains

@changeset-bot
Copy link

changeset-bot bot commented Mar 11, 2026

🦋 Changeset detected

Latest commit: 2bf49da

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
chainlink-deployments-framework Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ecPablo ecPablo marked this pull request as ready for review March 11, 2026 22:35
@ecPablo ecPablo requested a review from a team as a code owner March 11, 2026 22:35
Copilot AI review requested due to automatic review settings March 11, 2026 22:35
@cl-sonarqube-production
Copy link

Quality Gate failed Quality Gate failed

Failed conditions
32.1% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves revert/error decoding for MCMS set-root / execute flows (including nested CallReverted(bytes) payloads) and adds logic to skip fork execution on zkSync-like chains where standard Anvil forking isn’t supported.

Changes:

  • Add recursive formatting/decoding for ABI-unpacked error args (so nested revert payloads inside bytes are decoded when possible).
  • Wrap setRoot / execute failures with additional revert decoding attempts and skip fork execution for zkSync chains.
  • Add unit tests covering nested error decoding and the new helper behavior; add a patch changeset.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
engine/cld/commands/mcms/cmd_execute_fork.go Skips fork execution for zkSync, and adds addDecodedRevertReason to enrich failures with decoded revert data.
engine/cld/commands/mcms/execute_fork_test.go Adds tests for addDecodedRevertReason nil/degenerate cases.
deployment/helpers.go Enhances parseErrorFromABI output by recursively decoding []byte args that contain nested revert payloads.
deployment/helpers_test.go Adds coverage for CallReverted(bytes) wrapping Error(string) and nested custom errors.
.changeset/happy-cows-know.md Declares a patch release for improved decoding + zkSync skipping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +261 to +273
// isZkSyncChain checks if a chain selector corresponds to a zkSync chain.
// zkSync chains use zkEVM/EraVM which requires anvil-zksync, not standard Anvil.
// Returns (true, nil) for zkSync chains, (false, nil) for non-zkSync, or (false, err) on lookup failure.
func isZkSyncChain(selector uint64) (bool, error) {
chainIDStr, err := chainsel.GetChainIDFromSelector(selector)
if err != nil {
return false, err
}

// zkSync Era mainnet = 324, zkSync Sepolia testnet = 300
// See: https://docs.zksync.io/zksync-network/environment
return chainIDStr == "324" || chainIDStr == "300", nil
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

isZkSyncChain only treats chain IDs 324 and 300 as zkSync. Elsewhere in the codebase, several additional selectors are treated as zkSync VM chains (e.g. Lens + Cronos zkEVM) and will still attempt standard Anvil forking and likely fail, so this won't fully eliminate the false negatives this PR targets. Consider reusing the same selector allowlist as chainLoaderEVM.isZkSyncVM (engine/cld/chains/chains.go:570-582) or, if available here, derive the flag from the loaded chain (e.g. cldf_evm.Chain.IsZkSyncVM).

Copilot uses AI. Check for mistakes.
}

if reason, err := abi.UnpackRevert(inner); err == nil {
return fmt.Sprintf("Error(\"%s\")", reason)
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

tryDecodeByteArg wraps any successful abi.UnpackRevert decode as Error("..."). abi.UnpackRevert can also decode Panic(uint256) revert payloads, so this will mislabel panics as Error(...) and produce misleading output. Suggest checking the 4-byte selector (0x08c379a0 vs 0x4e487b71) and formatting accordingly, or returning the decoded reason string without forcing the Error("...") wrapper.

Suggested change
return fmt.Sprintf("Error(\"%s\")", reason)
return reason

Copilot uses AI. Check for mistakes.
return "", errors.New("error not found in ABI")
}

// formatUnpackedArgs formats an ABI-unpacked value, recursively decoding any
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// formatUnpackedArgs formats an ABI-unpacked value, recursively decoding any
// formatUnpackedArgs formats an ABI-unpacked value, recursively decode any

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