Skip to content

Commit b401802

Browse files
committed
all changes
1 parent fde2872 commit b401802

File tree

7 files changed

+1500
-144
lines changed

7 files changed

+1500
-144
lines changed

ccv/chains/evm/deployment/v1_7_0/adapters/feequoterupdater.go

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
88
cldf_ops "github.com/smartcontractkit/chainlink-deployments-framework/operations"
99

10-
fqops "github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment/v1_7_0/operations/fee_quoter"
1110
sequence1_7 "github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment/v1_7_0/sequences"
1211
"github.com/smartcontractkit/chainlink-ccip/deployment/deploy"
1312
"github.com/smartcontractkit/chainlink-ccip/deployment/utils/sequences"
@@ -38,27 +37,10 @@ func (fqu FeeQuoterUpdater) SequenceFeeQuoterInputCreation() *cldf_ops.Sequence[
3837
}
3938
output15 := report15.Output
4039
// combine the outputs from both sequences to create the input for the fee quoter update sequence
41-
output.DestChainConfigs = append(output16.DestChainConfigs, output15.DestChainConfigs...)
42-
output.TokenTransferFeeConfigUpdates = fqops.ApplyTokenTransferFeeConfigUpdatesArgs{
43-
TokenTransferFeeConfigArgs: append(
44-
output16.TokenTransferFeeConfigUpdates.TokenTransferFeeConfigArgs,
45-
output15.TokenTransferFeeConfigUpdates.TokenTransferFeeConfigArgs...),
46-
TokensToUseDefaultFeeConfigs: append(
47-
output16.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs,
48-
output15.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs...),
49-
}
50-
output.AuthorizedCallerUpdates.AddedCallers = append(
51-
output16.AuthorizedCallerUpdates.AddedCallers,
52-
output15.AuthorizedCallerUpdates.AddedCallers...)
53-
54-
// constructor args from the v1.6.0 sequence takes precedence over the constructor args from the v1.5.0 sequence,
55-
// as FeeQuoter 1.6.3 is more closely related to FeeQuoter 1.7.0
56-
// if the constructor args from the v1.6.0 sequence is empty, it means there is no FeeQuoter 1.6 exists for that chain
57-
// use the constructor args from the v1.5.0 sequence in that case
58-
if output16.ConstructorArgs.IsEmpty() {
59-
output.ConstructorArgs = output15.ConstructorArgs
40+
output, err = sequence1_7.MergeFeeQuoterUpdateOutputs(output16, output15)
41+
if err != nil {
42+
return sequence1_7.FeeQuoterUpdate{}, fmt.Errorf("failed to merge FeeQuoterUpdateInput from v1.6.0 and v1.5.0: %w", err)
6043
}
61-
6244
// check if output is empty, if so, return an error
6345
if empty, err := output.IsEmpty(); err != nil || empty {
6446
return sequence1_7.FeeQuoterUpdate{},

ccv/chains/evm/deployment/v1_7_0/sequences/fee_quoter.go

Lines changed: 158 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/ethereum/go-ethereum/common"
99
"github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/gobindings/generated/latest/fee_quoter"
1010
cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
11+
"golang.org/x/exp/maps"
1112

1213
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/operations/contract"
1314
onrampops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/operations/onramp"
@@ -33,6 +34,7 @@ import (
3334

3435
const (
3536
LinkFeeMultiplierPercent uint8 = 90
37+
NetworkFeeUSDCents = 10
3638
)
3739

3840
type FeeQuoterUpdate struct {
@@ -187,6 +189,8 @@ var (
187189
if datastore_utils.IsAddressRefEmpty(fq16Ref) {
188190
return FeeQuoterUpdate{}, nil
189191
}
192+
output.ChainSelector = input.ChainSelector
193+
output.ExistingAddresses = input.ExistingAddresses
190194
// get feeQuoter 1.6 address meta
191195
metadataForFq16, err := datastore_utils.FilterContractMetaByContractTypeAndVersion(
192196
input.ExistingAddresses,
@@ -205,7 +209,12 @@ var (
205209
if len(metadataForFq16) > 1 {
206210
return FeeQuoterUpdate{}, fmt.Errorf("multiple metadata entries found for FeeQuoter v1.6.3 on chain selector %d", input.ChainSelector)
207211
}
208-
fqOutput := metadataForFq16[0].Metadata.(seq1_6.FeeQuoterImportConfigSequenceOutput)
212+
// Convert metadata to typed struct if needed
213+
fqOutput, err := datastore_utils.ConvertMetadataToType[seq1_6.FeeQuoterImportConfigSequenceOutput](metadataForFq16[0].Metadata)
214+
if err != nil {
215+
return FeeQuoterUpdate{}, fmt.Errorf("failed to convert metadata to "+
216+
"FeeQuoterImportConfigSequenceOutput for chain selector %d: %w", input.ChainSelector, err)
217+
}
209218
// is feeQuoter going to be deployed or fetched from existing addresses?
210219
feeQuoterRef := datastore_utils.GetAddressRef(
211220
input.ExistingAddresses,
@@ -314,7 +323,8 @@ var (
314323
if len(onRampMetadata) == 0 {
315324
return FeeQuoterUpdate{}, fmt.Errorf("no metadata found for EVM2EVMOnRamp v1.5.0 on chain selector %d", input.ChainSelector)
316325
}
317-
326+
output.ChainSelector = input.ChainSelector
327+
output.ExistingAddresses = input.ExistingAddresses
318328
// is feeQuoter going to be deployed or fetched from existing addresses?
319329
feeQuoter17Ref := datastore_utils.GetAddressRef(
320330
input.ExistingAddresses,
@@ -329,22 +339,26 @@ var (
329339
var tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigSingleTokenArgs
330340
var tokenTransferFeeConfigArgsForAll []fqops.TokenTransferFeeConfigArgs
331341
for _, meta := range onRampMetadata {
332-
onRampCfg := meta.Metadata.(seq1_5.OnRampImportConfigSequenceOutput)
342+
// Convert metadata to typed struct if needed
343+
onRampCfg, err := datastore_utils.ConvertMetadataToType[seq1_5.OnRampImportConfigSequenceOutput](meta.Metadata)
344+
if err != nil {
345+
return FeeQuoterUpdate{}, fmt.Errorf("failed to convert metadata to "+
346+
"OnRampImportConfigSequenceOutput for chain selector %d: %w", input.ChainSelector, err)
347+
}
333348
if staticCfg.LinkToken == (common.Address{}) {
334349
staticCfg = fqops.StaticConfig{
335350
LinkToken: onRampCfg.StaticConfig.LinkToken,
336351
MaxFeeJuelsPerMsg: onRampCfg.StaticConfig.MaxNopFeesJuels,
337352
}
338353
}
339-
var networkFeeUSDCents uint16
340-
// NetworkFeeUSDCents is same across all feetokens in the same chain, so we can just take it from the first onRamp config
341-
for _, feeTokenCfg := range onRampCfg.FeeTokenConfig {
342-
if feeTokenCfg.NetworkFeeUSDCents != 0 {
343-
networkFeeUSDCents = uint16(feeTokenCfg.NetworkFeeUSDCents)
344-
break
345-
}
354+
355+
chainFamilySelectorBytes := utils.GetSelectorHex(onRampCfg.RemoteChainSelector)
356+
// Safely convert ChainFamilySelector from []byte to [4]byte
357+
var chainFamilySelector [4]byte
358+
if len(chainFamilySelectorBytes) < 4 {
359+
return FeeQuoterUpdate{}, fmt.Errorf("ChainFamilySelector has invalid length %d (expected 4) for remote chain selector %d", len(chainFamilySelectorBytes), onRampCfg.RemoteChainSelector)
346360
}
347-
chainFamilySelector := utils.GetSelectorHex(onRampCfg.RemoteChainSelector)
361+
copy(chainFamilySelector[:], chainFamilySelectorBytes[:4])
348362
destChainCfgs = append(destChainCfgs, fqops.DestChainConfigArgs{
349363
DestChainSelector: onRampCfg.RemoteChainSelector,
350364
DestChainConfig: adapters.FeeQuoterDestChainConfig{
@@ -353,12 +367,12 @@ var (
353367
MaxPerMsgGasLimit: onRampCfg.DynamicConfig.MaxPerMsgGasLimit,
354368
DestGasOverhead: onRampCfg.DynamicConfig.DestGasOverhead,
355369
DestGasPerPayloadByteBase: uint8(onRampCfg.DynamicConfig.DestGasPerPayloadByte),
356-
ChainFamilySelector: [4]byte(chainFamilySelector),
370+
ChainFamilySelector: chainFamilySelector,
357371
DefaultTokenFeeUSDCents: onRampCfg.DynamicConfig.DefaultTokenFeeUSDCents,
358372
DefaultTokenDestGasOverhead: onRampCfg.DynamicConfig.DefaultTokenDestGasOverhead,
359373
DefaultTxGasLimit: uint32(onRampCfg.StaticConfig.DefaultTxGasLimit),
360-
NetworkFeeUSDCents: networkFeeUSDCents,
361-
LinkFeeMultiplierPercent: 90,
374+
NetworkFeeUSDCents: NetworkFeeUSDCents,
375+
LinkFeeMultiplierPercent: LinkFeeMultiplierPercent,
362376
},
363377
})
364378
for token, tokenCfg := range onRampCfg.TokenTransferFeeConfig {
@@ -386,7 +400,7 @@ var (
386400
DestChainConfigArgs: destChainCfgs,
387401
TokenTransferFeeConfigArgs: tokenTransferFeeConfigArgsForAll,
388402
// TODO: what to do with price updaters for 1.5 if there is no 1.6 lanes here
389-
PriceUpdaters: []common.Address{},
403+
// PriceUpdaters: []common.Address{},
390404
}
391405
} else {
392406
output.DestChainConfigs = destChainCfgs
@@ -395,3 +409,132 @@ var (
395409
return output, nil
396410
})
397411
)
412+
413+
func MergeFeeQuoterUpdateOutputs(output16, output15 FeeQuoterUpdate) (FeeQuoterUpdate, error) {
414+
result := output16
415+
416+
// ConstructorArgs: use output15 if output16 is empty
417+
if result.ConstructorArgs.IsEmpty() {
418+
result.ConstructorArgs = output15.ConstructorArgs
419+
} else {
420+
// merge the dest chainConfig args
421+
result.ConstructorArgs.DestChainConfigArgs = mergeDestChainConfigs(
422+
result.ConstructorArgs.DestChainConfigArgs,
423+
output15.ConstructorArgs.DestChainConfigArgs)
424+
resultPriceUpdatersMap := make(map[common.Address]bool)
425+
for _, updater := range result.ConstructorArgs.PriceUpdaters {
426+
resultPriceUpdatersMap[updater] = true
427+
}
428+
for _, updater := range output15.ConstructorArgs.PriceUpdaters {
429+
if !resultPriceUpdatersMap[updater] {
430+
result.ConstructorArgs.PriceUpdaters = append(result.ConstructorArgs.PriceUpdaters, updater)
431+
resultPriceUpdatersMap[updater] = true
432+
}
433+
}
434+
result.ConstructorArgs.TokenTransferFeeConfigArgs = mergeTokenTransferFeeConfigArgs(
435+
result.ConstructorArgs.TokenTransferFeeConfigArgs,
436+
output15.ConstructorArgs.TokenTransferFeeConfigArgs)
437+
result.ConstructorArgs.PriceUpdaters = maps.Keys(resultPriceUpdatersMap)
438+
}
439+
440+
result.DestChainConfigs = mergeDestChainConfigs(result.DestChainConfigs, output15.DestChainConfigs)
441+
442+
// TokenTransferFeeConfigUpdates: merge by DestChainSelector, output16 takes precedence for duplicates
443+
result.TokenTransferFeeConfigUpdates.TokenTransferFeeConfigArgs = mergeTokenTransferFeeConfigArgs(
444+
result.TokenTransferFeeConfigUpdates.TokenTransferFeeConfigArgs,
445+
output15.TokenTransferFeeConfigUpdates.TokenTransferFeeConfigArgs)
446+
447+
// TokensToUseDefaultFeeConfigs: merge by DestChainSelector and Token
448+
if len(result.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs) == 0 {
449+
result.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs = output15.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs
450+
} else {
451+
// Create a map of (DestChainSelector, Token) pairs from output16
452+
tokenRemoveMap := make(map[string]bool)
453+
for _, cfg := range result.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs {
454+
key := fmt.Sprintf("%d:%s", cfg.DestChainSelector, cfg.Token.Hex())
455+
tokenRemoveMap[key] = true
456+
}
457+
// Add configs from output15 that don't exist in output16
458+
for _, cfg := range output15.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs {
459+
key := fmt.Sprintf("%d:%s", cfg.DestChainSelector, cfg.Token.Hex())
460+
if !tokenRemoveMap[key] {
461+
result.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs = append(result.TokenTransferFeeConfigUpdates.TokensToUseDefaultFeeConfigs, cfg)
462+
}
463+
// If it exists in both, output16's value is already used (takes precedence)
464+
}
465+
}
466+
467+
// AuthorizedCallerUpdates: merge unique entries from both outputs
468+
result.AuthorizedCallerUpdates = mergePriceUpdaters(result.AuthorizedCallerUpdates, output15.AuthorizedCallerUpdates)
469+
470+
return result, nil
471+
}
472+
473+
func mergeTokenTransferFeeConfigArgs(args1, args2 []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs) []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs {
474+
result := args1
475+
// TokenTransferFeeConfigArgs: merge by DestChainSelector
476+
if len(result) == 0 {
477+
result = args2
478+
} else {
479+
// Create a map of dest chain selectors from output16
480+
tokenConfigMap := make(map[uint64]int)
481+
for i, cfg := range result {
482+
tokenConfigMap[cfg.DestChainSelector] = i
483+
}
484+
// Add configs from output15 that don't exist in output16
485+
for _, cfg := range args2 {
486+
if _, exists := tokenConfigMap[cfg.DestChainSelector]; !exists && len(cfg.TokenTransferFeeConfigs) > 0 {
487+
result = append(result, cfg)
488+
}
489+
// If it exists in both, output16's value is already used (takes precedence)
490+
}
491+
}
492+
return result
493+
}
494+
495+
func mergePriceUpdaters(updaters1, updaters2 fqops.AuthorizedCallerArgs) fqops.AuthorizedCallerArgs {
496+
result := updaters1
497+
// AddedCallers: merge unique addresses from both outputs
498+
addedCallersMap := make(map[common.Address]bool)
499+
for _, addr := range result.AddedCallers {
500+
addedCallersMap[addr] = true
501+
}
502+
for _, addr := range updaters2.AddedCallers {
503+
if !addedCallersMap[addr] {
504+
result.AddedCallers = append(result.AddedCallers, addr)
505+
addedCallersMap[addr] = true
506+
}
507+
}
508+
// RemovedCallers: merge unique addresses from both outputs
509+
removedCallersMap := make(map[common.Address]bool)
510+
for _, addr := range result.RemovedCallers {
511+
removedCallersMap[addr] = true
512+
}
513+
for _, addr := range updaters2.RemovedCallers {
514+
if !removedCallersMap[addr] {
515+
result.RemovedCallers = append(result.RemovedCallers, addr)
516+
removedCallersMap[addr] = true
517+
}
518+
}
519+
return result
520+
}
521+
522+
func mergeDestChainConfigs(cfgs1, cfgs2 []fqops.DestChainConfigArgs) []fqops.DestChainConfigArgs {
523+
// Create a map of dest chain selectors from cfgs1
524+
destChainMap := make(map[uint64]fqops.DestChainConfigArgs)
525+
for _, cfg := range cfgs1 {
526+
destChainMap[cfg.DestChainSelector] = cfg
527+
}
528+
result := cfgs1
529+
// Add configs from cfgs2 that don't exist in cfgs1
530+
for _, cfg := range cfgs2 {
531+
if _, exists := destChainMap[cfg.DestChainSelector]; !exists {
532+
result = append(result, cfg)
533+
}
534+
// If it exists in both, cfgs1's value is already used (takes precedence)
535+
}
536+
if len(destChainMap) == 0 {
537+
return nil
538+
}
539+
return result
540+
}

0 commit comments

Comments
 (0)