Skip to content

fix(cre): wire ChainWrite.TargetsLimit to non-EVM WriteReport capabilities - #23255

Draft
cawthorne wants to merge 2 commits into
developfrom
fix/cre-chain-write-limits-non-evm
Draft

fix(cre): wire ChainWrite.TargetsLimit to non-EVM WriteReport capabilities#23255
cawthorne wants to merge 2 commits into
developfrom
fix/cre-chain-write-limits-non-evm

Conversation

@cawthorne

Copy link
Copy Markdown
Contributor

Summary

ChainWrite.TargetsLimit in CRE settings was silently unthrottled for non-EVM chains. The callLimiters map in capability_executor.go only wired ChainWriteTargets to {"evm", "WriteReport"} — Aptos, Solana, and Stellar WriteReport calls bypassed the limiter entirely.

The gap

The lookup at capability_executor.go:101:

limiter, ok := c.callLimiters[capCall{name: capName, method: request.Method}]
if ok { /* apply limit */ }
// if !ok → limiter silently skipped

For an Aptos write, ParseID("aptos:ChainSelector:4457093679053095497@1.0.0") returns name="aptos". The map only had {"evm", "WriteReport"} — so ok=false and the call proceeded unchecked.

family WriteReport exists? In callLimiters (before) In callLimiters (after)
evm
aptos
solana
stellar

The fix

Add 3 map entries — the limiter object (limiters.ChainWriteTargets) and settings schema (cresettings.chainWrite.TargetsLimit) already exist and are chain-family-agnostic:

{"evm", "WriteReport"}:     limiters.ChainWriteTargets,
{"aptos", "WriteReport"}:   limiters.ChainWriteTargets,  // new
{"solana", "WriteReport"}:  limiters.ChainWriteTargets,  // new
{"stellar", "WriteReport"}: limiters.ChainWriteTargets,  // new

Production impact

Any production workflow writing to Aptos/Solana/Stellar has unlimited write targets today, regardless of ChainWrite.TargetsLimit in the org-level CRE settings. With this fix, TargetsLimit=0 correctly blocks all chain writes, not just EVM.

How discovered

While debugging fire-drill transmit_fault scenarios in chainlink-data-feeds. We investigated whether ChainWrite.TargetsLimit=0 could replace the bad-contract-address fault (hot-reloadable, no re-register), but found Aptos writes bypassed the limiter — leading to this fix.

Test plan

  • go test ./core/services/workflows/v2/... passes (verified locally)
  • Existing EVM write-limit tests still pass (no behavioral change for EVM)
  • Manual: set ChainWrite.TargetsLimit = 0 on an Aptos-targeted workflow, verify writes are now blocked (previously: writes succeeded)

chainlink-releases-bot and others added 2 commits July 21, 2026 19:35
…ities

The callLimiters map in capability_executor.go only wired
ChainWriteTargets to {"evm", "WriteReport"}. Aptos, Solana, and
Stellar WriteReport calls were silently unthrottled — the limiter
lookup returned ok=false and the call proceeded unchecked,
regardless of the ChainWrite.TargetsLimit setting.

The settings schema (chainlink-common cresettings.chainWrite) already
defines TargetsLimit as a chain-family-agnostic per-workflow limit,
and the chainWrite struct carries Aptos/Solana sub-structs — the
wiring just never connected them.

Add map entries for aptos, solana, and stellar WriteReport methods,
all pointing to the same limiters.ChainWriteTargets limiter. This
is a 4-line change — the limiter object and settings infrastructure
already exist and are chain-family-agnostic.

Discovered while debugging fire-drill transmit_fault scenarios:
ApplyTransmitFault injects a bad target contract address to cause
write failures, but we investigated whether ChainWrite.TargetsLimit=0
could be used instead (hot-reloadable, no re-register). It cannot,
because Aptos writes bypass the limiter entirely. With this fix,
TargetsLimit=0 would correctly block all chain writes, not just EVM.
@github-actions

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting develop

@github-actions

Copy link
Copy Markdown
Contributor

I see you updated files related to core. Please run make gocs in the root directory to add a changeset as well as in the text include at least one of the following tags:

  • #added For any new functionality added.
  • #breaking_change For any functionality that requires manual action for the node to boot.
  • #bugfix For bug fixes.
  • #changed For any change to the existing functionality.
  • #db_update For any feature that introduces updates to database schema.
  • #deprecation_notice For any upcoming deprecation functionality.
  • #internal For changesets that need to be excluded from the final changelog.
  • #nops For any feature that is NOP facing and needs to be in the official Release Notes for the release.
  • #removed For any functionality/config that is removed.
  • #updated For any functionality that is updated.
  • #wip For any change that is not ready yet and external communication about it should be held off till it is feature complete.

@trunk-io

trunk-io Bot commented Jul 28, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@cl-sonarqube-production

Copy link
Copy Markdown

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