Skip to content

Commit 5c2db8b

Browse files
authored
Updates to error reporting checks between FQ versions (#21757)
Updates to error reporting checks between versions
1 parent 6eda8c3 commit 5c2db8b

2 files changed

Lines changed: 40 additions & 67 deletions

File tree

deployment/ccip/shared/stateview/evm/validate_feequoter.go

Lines changed: 37 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ func (c CCIPChainState) validateAllDestChainConfigs(
339339
}
340340

341341
if v16Cfg != nil {
342-
if err := c.validateV16DestChainConfig(callOpts, sourceChainSel, destChainSel, *v16Cfg, legacyCfg, v16FeeTokens); err != nil {
342+
if err := c.validateV16DestChainConfig(callOpts, sourceChainSel, destChainSel, *v16Cfg, legacyCfg); err != nil {
343343
errs = append(errs, err)
344344
}
345345
}
@@ -359,7 +359,6 @@ func (c CCIPChainState) validateV16DestChainConfig(
359359
sourceChainSel, destChainSel uint64,
360360
destCfg fee_quoter.FeeQuoterDestChainConfig,
361361
legacyCfg *evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig,
362-
feeTokens []common.Address,
363362
) error {
364363
header := fmt.Sprintf("FeeQuoter v1.6 %s dest chain %d", c.FeeQuoter.Address().Hex(), destChainSel)
365364

@@ -380,56 +379,44 @@ func (c CCIPChainState) validateV16DestChainConfig(
380379
{"MaxDataBytes", uint64(destCfg.MaxDataBytes), uint64(legacyCfg.MaxDataBytes)},
381380
{"MaxPerMsgGasLimit", uint64(destCfg.MaxPerMsgGasLimit), uint64(legacyCfg.MaxPerMsgGasLimit)},
382381
{"DefaultTokenDestGasOverhead", uint64(destCfg.DefaultTokenDestGasOverhead), uint64(legacyCfg.DefaultTokenDestGasOverhead)},
383-
{"DefaultTokenFeeUSDCents", uint64(destCfg.DefaultTokenFeeUSDCents), uint64(legacyCfg.DefaultTokenFeeUSDCents)},
384382
{"EnforceOutOfOrder", destCfg.EnforceOutOfOrder, legacyCfg.EnforceOutOfOrder},
385383
{"DestGasPerPayloadByteBase", uint64(destCfg.DestGasPerPayloadByteBase), uint64(uint8(legacyCfg.DestGasPerPayloadByte))}, //nolint:gosec // G115: intentional v1.5 uint16->uint8 truncation during migration
386384
}); err != nil {
387385
errs = append(errs, err)
388386
}
389-
390-
// GasMultiplierWeiPerEth moved from per-token to per-dest in v1.6
391-
for _, ft := range feeTokens {
392-
legacyOnRamp := c.EVM2EVMOnRamp[destChainSel]
393-
if legacyOnRamp == nil {
394-
break
395-
}
396-
legacyFTCfg, err := legacyOnRamp.GetFeeTokenConfig(callOpts, ft)
397-
if err != nil || !legacyFTCfg.Enabled {
398-
continue
399-
}
400-
if destCfg.GasMultiplierWeiPerEth != legacyFTCfg.GasMultiplierWeiPerEth {
401-
errs = append(errs, fmt.Errorf("GasMultiplierWeiPerEth: v1.6=%d, v1.5 FeeTokenConfig=%d",
402-
destCfg.GasMultiplierWeiPerEth, legacyFTCfg.GasMultiplierWeiPerEth))
403-
}
404-
break
405-
}
406-
} else {
407-
// No legacy to cross-check — validate fee-related fields against expected values
408-
expectedFee := expectedDefaultTokenFeeUSDCents(sourceChainSel, destChainSel)
409-
if uint64(destCfg.DefaultTokenFeeUSDCents) != uint64(expectedFee) {
410-
errs = append(errs, fmt.Errorf("DefaultTokenFeeUSDCents: got=%d, want=%d", destCfg.DefaultTokenFeeUSDCents, expectedFee))
411-
}
412387
}
413388

414-
// v1.6 business-rule fields (always checked)
389+
// v1.6 field checks (always applied)
415390
if destCfg.ChainFamilySelector == [4]byte{} {
416391
errs = append(errs, errors.New("ChainFamilySelector is empty"))
417392
}
418-
if destCfg.GasPriceStalenessThreshold == 0 {
393+
// GasPriceStalenessThreshold: compare against v1.5 PriceRegistry when present; else require non-zero.
394+
if c.PriceRegistry != nil {
395+
st, stErr := c.PriceRegistry.GetStalenessThreshold(callOpts)
396+
if stErr != nil {
397+
errs = append(errs, fmt.Errorf("failed to get staleness threshold from v1.5 PriceRegistry: %w", stErr))
398+
} else if !st.IsUint64() || st.Uint64() > uint64(^uint32(0)) {
399+
errs = append(errs, fmt.Errorf("v1.5 PriceRegistry StalenessThreshold %s overflows uint32", st.String()))
400+
} else if want := uint32(st.Uint64()); want != destCfg.GasPriceStalenessThreshold { //nolint:gosec // G115: safe, verified <= MaxUint32
401+
errs = append(errs, fmt.Errorf("v1.5<->v1.6:\n GasPriceStalenessThreshold: got=%d, want=%d",
402+
destCfg.GasPriceStalenessThreshold, want))
403+
}
404+
} else if destCfg.GasPriceStalenessThreshold == 0 {
419405
errs = append(errs, errors.New("GasPriceStalenessThreshold is 0"))
420406
}
421-
if err := compareFieldChecks("business rules", []fieldCheck{
407+
if err := compareFieldChecks("deploy-constants", []fieldCheck{
422408
{"DestGasPerPayloadByteHigh", uint64(destCfg.DestGasPerPayloadByteHigh), uint64(ccipevm.CalldataGasPerByteHigh)},
423409
{"DestGasPerPayloadByteThreshold", uint64(destCfg.DestGasPerPayloadByteThreshold), uint64(ccipevm.CalldataGasPerByteThreshold)},
424410
{"DefaultTxGasLimit", uint64(destCfg.DefaultTxGasLimit), uint64(200_000)},
425-
{"NetworkFeeUSDCents", uint64(destCfg.NetworkFeeUSDCents), uint64(expectedNetworkFeeUSDCents(sourceChainSel, destChainSel))},
411+
{"GasMultiplierWeiPerEth", destCfg.GasMultiplierWeiPerEth, uint64(11e17)},
426412
}); err != nil {
427413
errs = append(errs, err)
428414
}
429-
430-
destFamily, _ := chain_selectors.GetSelectorFamily(destChainSel)
431-
if destFamily != chain_selectors.FamilyEVM && !destCfg.EnforceOutOfOrder {
432-
errs = append(errs, fmt.Errorf("EnforceOutOfOrder must be true for non-EVM dest (family %s)", destFamily))
415+
if err := compareFieldChecks("topology", []fieldCheck{
416+
{"NetworkFeeUSDCents", uint64(destCfg.NetworkFeeUSDCents), uint64(expectedNetworkFeeUSDCents(sourceChainSel, destChainSel))},
417+
{"DefaultTokenFeeUSDCents", uint64(destCfg.DefaultTokenFeeUSDCents), uint64(expectedDefaultTokenFeeUSDCents(sourceChainSel, destChainSel))},
418+
}); err != nil {
419+
errs = append(errs, err)
433420
}
434421

435422
return groupErrors(header, errs)
@@ -456,27 +443,30 @@ func (c CCIPChainState) validateV20DestChainConfig(
456443
if destCfgV2.ChainFamilySelector == [4]byte{} {
457444
errs = append(errs, errors.New("ChainFamilySelector is empty"))
458445
}
459-
if err := compareFieldChecks("business rules", []fieldCheck{
446+
if err := compareFieldChecks("deploy-constants", []fieldCheck{
460447
{"LinkFeeMultiplierPercent", uint64(destCfgV2.LinkFeeMultiplierPercent), uint64(fqv2seq.LinkFeeMultiplierPercent)},
461-
{"NetworkFeeUSDCents", uint64(destCfgV2.NetworkFeeUSDCents), uint64(expectedNetworkFeeUSDCents(sourceChainSel, destChainSel))},
462448
{"DefaultTxGasLimit", uint64(destCfgV2.DefaultTxGasLimit), uint64(200_000)},
463449
}); err != nil {
464450
errs = append(errs, err)
465451
}
452+
if err := compareFieldChecks("topology", []fieldCheck{
453+
{"NetworkFeeUSDCents", uint64(destCfgV2.NetworkFeeUSDCents), uint64(expectedNetworkFeeUSDCents(sourceChainSel, destChainSel))},
454+
{"DefaultTokenFeeUSDCents", uint64(destCfgV2.DefaultTokenFeeUSDCents), uint64(expectedDefaultTokenFeeUSDCents(sourceChainSel, destChainSel))},
455+
}); err != nil {
456+
errs = append(errs, err)
457+
}
466458

467-
// Cross-version field mapping: v1.6 <-> v2.0
459+
// Cross-version field mapping: v1.6 <-> v2.0 (v2.0 is got, v1.6 is want)
468460
if v16Cfg != nil {
469461
if err := compareFieldChecks("v1.6<->v2.0", []fieldCheck{
470-
{"IsEnabled", v16Cfg.IsEnabled, destCfgV2.IsEnabled},
471-
{"MaxDataBytes", uint64(v16Cfg.MaxDataBytes), uint64(destCfgV2.MaxDataBytes)},
472-
{"MaxPerMsgGasLimit", uint64(v16Cfg.MaxPerMsgGasLimit), uint64(destCfgV2.MaxPerMsgGasLimit)},
473-
{"DestGasOverhead", uint64(v16Cfg.DestGasOverhead), uint64(destCfgV2.DestGasOverhead)},
474-
{"DestGasPerPayloadByteBase", uint64(v16Cfg.DestGasPerPayloadByteBase), uint64(destCfgV2.DestGasPerPayloadByteBase)},
475-
{"ChainFamilySelector", v16Cfg.ChainFamilySelector, destCfgV2.ChainFamilySelector},
476-
{"DefaultTokenFeeUSDCents", uint64(v16Cfg.DefaultTokenFeeUSDCents), uint64(destCfgV2.DefaultTokenFeeUSDCents)},
477-
{"DefaultTokenDestGasOverhead", uint64(v16Cfg.DefaultTokenDestGasOverhead), uint64(destCfgV2.DefaultTokenDestGasOverhead)},
478-
{"DefaultTxGasLimit", uint64(v16Cfg.DefaultTxGasLimit), uint64(destCfgV2.DefaultTxGasLimit)},
479-
{"NetworkFeeUSDCents", uint64(v16Cfg.NetworkFeeUSDCents), uint64(destCfgV2.NetworkFeeUSDCents)},
462+
{"IsEnabled", destCfgV2.IsEnabled, v16Cfg.IsEnabled},
463+
{"MaxDataBytes", uint64(destCfgV2.MaxDataBytes), uint64(v16Cfg.MaxDataBytes)},
464+
{"MaxPerMsgGasLimit", uint64(destCfgV2.MaxPerMsgGasLimit), uint64(v16Cfg.MaxPerMsgGasLimit)},
465+
{"DestGasOverhead", uint64(destCfgV2.DestGasOverhead), uint64(v16Cfg.DestGasOverhead)},
466+
{"DestGasPerPayloadByteBase", uint64(destCfgV2.DestGasPerPayloadByteBase), uint64(v16Cfg.DestGasPerPayloadByteBase)},
467+
{"ChainFamilySelector", destCfgV2.ChainFamilySelector, v16Cfg.ChainFamilySelector},
468+
{"DefaultTokenDestGasOverhead", uint64(destCfgV2.DefaultTokenDestGasOverhead), uint64(v16Cfg.DefaultTokenDestGasOverhead)},
469+
{"DefaultTxGasLimit", uint64(destCfgV2.DefaultTxGasLimit), uint64(v16Cfg.DefaultTxGasLimit)},
480470
}); err != nil {
481471
errs = append(errs, err)
482472
}
@@ -489,25 +479,8 @@ func (c CCIPChainState) validateV20DestChainConfig(
489479
{"MaxDataBytes", uint64(destCfgV2.MaxDataBytes), uint64(legacyCfg.MaxDataBytes)},
490480
{"MaxPerMsgGasLimit", uint64(destCfgV2.MaxPerMsgGasLimit), uint64(legacyCfg.MaxPerMsgGasLimit)},
491481
{"DefaultTokenDestGasOverhead", uint64(destCfgV2.DefaultTokenDestGasOverhead), uint64(legacyCfg.DefaultTokenDestGasOverhead)},
492-
{"DefaultTokenFeeUSDCents", uint64(destCfgV2.DefaultTokenFeeUSDCents), uint64(legacyCfg.DefaultTokenFeeUSDCents)},
493482
{"DestGasPerPayloadByteBase", uint64(destCfgV2.DestGasPerPayloadByteBase), uint64(uint8(legacyCfg.DestGasPerPayloadByte))}, //nolint:gosec // G115: intentional v1.5 uint16->uint8 truncation during migration
494483
}
495-
// NetworkFeeUSDCents: per-token in v1.5, per-dest in v2.0. Fetch from v1.5 FeeTokenConfig
496-
if legacyOnRamp := c.EVM2EVMOnRamp[destChainSel]; legacyOnRamp != nil {
497-
v16FeeTokens, ftErr := c.FeeQuoter.GetFeeTokens(callOpts)
498-
if ftErr == nil {
499-
for _, ft := range v16FeeTokens {
500-
legacyFTCfg, err := legacyOnRamp.GetFeeTokenConfig(callOpts, ft)
501-
if err != nil || !legacyFTCfg.Enabled {
502-
continue
503-
}
504-
v15Checks = append(v15Checks,
505-
fieldCheck{"NetworkFeeUSDCents", uint64(destCfgV2.NetworkFeeUSDCents), uint64(legacyFTCfg.NetworkFeeUSDCents)},
506-
)
507-
break
508-
}
509-
}
510-
}
511484
if err := compareFieldChecks("v1.5<->v2.0", v15Checks); err != nil {
512485
errs = append(errs, err)
513486
}

deployment/ccip/shared/stateview/evm/validate_feequoter_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ func TestValidateFeeQuoter_CrossVersionValidation(t *testing.T) {
255255
MaxDataBytes: v15Cfg.MaxDataBytes,
256256
MaxPerMsgGasLimit: v15Cfg.MaxPerMsgGasLimit,
257257
DefaultTokenDestGasOverhead: v15Cfg.DefaultTokenDestGasOverhead,
258-
DefaultTokenFeeUSDCents: v15Cfg.DefaultTokenFeeUSDCents,
258+
DefaultTokenFeeUSDCents: 25, // topology: non-ETH EVM→EVM
259259
EnforceOutOfOrder: v15Cfg.EnforceOutOfOrder,
260260
DestGasPerPayloadByteBase: uint8(v15Cfg.DestGasPerPayloadByte), //nolint:gosec // match v1.5 truncation
261261
DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh,
@@ -264,7 +264,7 @@ func TestValidateFeeQuoter_CrossVersionValidation(t *testing.T) {
264264
NetworkFeeUSDCents: 10,
265265
GasPriceStalenessThreshold: 86400,
266266
ChainFamilySelector: [4]byte{0x28, 0x12, 0xd5, 0x2c},
267-
GasMultiplierWeiPerEth: 1e18,
267+
GasMultiplierWeiPerEth: 11e17, // deploy-constant
268268
}
269269
tenv, err = commonchangeset.Apply(t, tenv,
270270
commonchangeset.Configure(
@@ -286,7 +286,7 @@ func TestValidateFeeQuoter_CrossVersionValidation(t *testing.T) {
286286
DestGasOverhead: goodV16Cfg.DestGasOverhead,
287287
DestGasPerPayloadByteBase: goodV16Cfg.DestGasPerPayloadByteBase,
288288
ChainFamilySelector: goodV16Cfg.ChainFamilySelector,
289-
DefaultTokenFeeUSDCents: goodV16Cfg.DefaultTokenFeeUSDCents,
289+
DefaultTokenFeeUSDCents: 25, // topology: non-ETH EVM→EVM
290290
DefaultTokenDestGasOverhead: goodV16Cfg.DefaultTokenDestGasOverhead,
291291
DefaultTxGasLimit: 200_000,
292292
NetworkFeeUSDCents: 10,

0 commit comments

Comments
 (0)