@@ -262,6 +262,12 @@ type TokenPoolConfig struct {
262262
263263 // SkipOwnershipValidation, if true, skips validation of ownership on the token pool. Optional, defaults to false.
264264 SkipOwnershipValidation bool `json:"skipOwnershipValidation,omitempty"`
265+
266+ // AllowAdditiveRemotePools, if true, allows adding additional remote pools to existing chain configurations
267+ // without removing and re-adding the chain selector. When false (default), the behavior is to remove
268+ // the chain selector and re-add it with the new pool configuration (spot replacement).
269+ // This is particularly useful for Solana and other chains where multiple pools may need to coexist.
270+ AllowAdditiveRemotePools bool `json:"allowAdditiveRemotePools,omitempty"`
265271}
266272
267273func (c TokenPoolConfig ) Validate (ctx context.Context , chain cldf_evm.Chain , ccipState stateview.CCIPOnChainState , useMcms bool , tokenSymbol shared.TokenSymbol ) error {
@@ -482,13 +488,29 @@ func configureTokenPool(
482488 break
483489 }
484490 }
485- if ! bytes .Equal (remoteTokenAddress .Bytes (), remoteToken ) || ! isRemotePoolSupported {
486- // Remove & later re-add the chain if the remote token has changed OR the remote pool address is not supported
491+
492+ // Determine the action based on token and pool status
493+ switch {
494+ case ! bytes .Equal (remoteTokenAddress .Bytes (), remoteToken ):
495+ // Remote token has changed - this always requires chain removal/re-addition
487496 chainRemovals = append (chainRemovals , remoteChainSelector )
488497 addChain = true
489- } else {
490- // Update the rate limits if the chain is already supported
491- // We dont need to add a new remote pool because solana only supports one remote pool per token
498+ case ! isRemotePoolSupported :
499+ // Remote pool is not supported - behavior depends on AllowAdditiveRemotePools flag
500+ if poolUpdate .AllowAdditiveRemotePools {
501+ // Add the new remote pool without removing the chain
502+ remotePoolAddressAdditions [remoteChainSelector ] = common .LeftPadBytes (remotePoolAddress .Bytes (), 32 )
503+ // Also update rate limits
504+ remoteChainSelectorsToUpdate = append (remoteChainSelectorsToUpdate , remoteChainSelector )
505+ updatedOutboundConfigs = append (updatedOutboundConfigs , chainUpdate .RateLimiterConfig .Outbound )
506+ updatedInboundConfigs = append (updatedInboundConfigs , chainUpdate .RateLimiterConfig .Inbound )
507+ } else {
508+ // Default behavior: Remove & later re-add the chain (spot replacement)
509+ chainRemovals = append (chainRemovals , remoteChainSelector )
510+ addChain = true
511+ }
512+ default :
513+ // Remote pool is already supported, just update the rate limits
492514 remoteChainSelectorsToUpdate = append (remoteChainSelectorsToUpdate , remoteChainSelector )
493515 updatedOutboundConfigs = append (updatedOutboundConfigs , chainUpdate .RateLimiterConfig .Outbound )
494516 updatedInboundConfigs = append (updatedInboundConfigs , chainUpdate .RateLimiterConfig .Inbound )
@@ -500,8 +522,8 @@ func configureTokenPool(
500522 RemoteChainSelector : remoteChainSelector ,
501523 InboundRateLimiterConfig : chainUpdate .RateLimiterConfig .Inbound ,
502524 OutboundRateLimiterConfig : chainUpdate .RateLimiterConfig .Outbound ,
503- RemoteTokenAddress : remoteTokenAddress .Bytes (),
504- RemotePoolAddresses : [][]byte {remotePoolAddress .Bytes ()},
525+ RemoteTokenAddress : common . LeftPadBytes ( remoteTokenAddress .Bytes (), 32 ),
526+ RemotePoolAddresses : [][]byte {common . LeftPadBytes ( remotePoolAddress .Bytes (), 32 )},
505527 })
506528 }
507529 }
@@ -587,7 +609,9 @@ func configureTokenPool(
587609 }
588610 }
589611 // Check if the remote pool to-be-set is non-empty and not already configured on the token pool
590- if len (remotePoolAddress ) == 0 && ! isRemotePoolSupported {
612+ // For Sui, the default behavior has always been additive, so we maintain backward compatibility
613+ // The AllowAdditiveRemotePools flag doesn't change Sui's existing behavior
614+ if len (remotePoolAddress ) > 0 && ! isRemotePoolSupported {
591615 remotePoolAddressAdditions [remoteChainSelector ] = common .LeftPadBytes (remotePoolAddress , 32 )
592616 }
593617 } else {
0 commit comments