Skip to content

Commit 6eee37e

Browse files
authored
add fq dests changeset (#1921)
* wip * tests * tests * comments * cr comments * cr comments
1 parent c60412b commit 6eee37e

29 files changed

Lines changed: 1532 additions & 233 deletions

chains/evm/deployment/v1_0_0/adapters/pool_adapter.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ func (a *EVMPoolAdapter) ManualRegistration() *cldf_ops.Sequence[tokensapi.Manua
178178
return sequences.OnChainOutput{}, fmt.Errorf("failed to get token admin registry address for chain %d: %w", chain.Selector, err)
179179
}
180180

181+
// Token address resolution strategy:
182+
// 1. If TokenRef already has an address, use it directly (skip datastore).
183+
// 2. Otherwise look up the token in the datastore using TokenRef fields.
184+
// 3. If step 2 fails (e.g. ambiguous or missing), fall back to reading
185+
// the token address from the on-chain token pool contract via TokenPoolRef.
186+
// 4. If none of the above work, return an error.
181187
tokenRef := input.TokenRef
182188
if tokenRef.Address == "" {
183189
if tokRef, err := datastore_utils.FindAndFormatRef(input.ExistingDataStore, tokenRef, chain.Selector, datastore_utils.FullRef); err != nil {

chains/evm/deployment/v1_5_0/adapters/fees.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
evmseq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/sequences"
1313
"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp"
1414
"github.com/smartcontractkit/chainlink-ccip/deployment/fees"
15+
"github.com/smartcontractkit/chainlink-ccip/deployment/lanes"
1516
datastore_utils "github.com/smartcontractkit/chainlink-ccip/deployment/utils/datastore"
1617
"github.com/smartcontractkit/chainlink-ccip/deployment/utils/sequences"
1718
cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
@@ -306,3 +307,25 @@ func (a *FeesAdapter) SetTokenTransferFee(e cldf.Environment) *operations.Sequen
306307
},
307308
)
308309
}
310+
311+
// GetDefaultDestChainConfig is not supported for v1.5 (no FeeQuoter contract).
312+
func (a *FeesAdapter) GetDefaultDestChainConfig(src, dst uint64) lanes.FeeQuoterDestChainConfig {
313+
return lanes.FeeQuoterDestChainConfig{}
314+
}
315+
316+
// GetOnchainDestChainConfig is not supported for v1.5 (no FeeQuoter contract).
317+
func (a *FeesAdapter) GetOnchainDestChainConfig(_ cldf.Environment, _, _ uint64) (lanes.FeeQuoterDestChainConfig, error) {
318+
return lanes.FeeQuoterDestChainConfig{}, fmt.Errorf("FeeQuoter dest chain config reads are not supported for v1.5 (no FeeQuoter contract)")
319+
}
320+
321+
// ApplyDestChainConfigUpdates is not supported for v1.5 (no FeeQuoter contract).
322+
func (a *FeesAdapter) ApplyDestChainConfigUpdates(e cldf.Environment) *operations.Sequence[fees.ApplyDestChainConfigSequenceInput, sequences.OnChainOutput, cldf_chain.BlockChains] {
323+
return operations.NewSequence(
324+
"ApplyDestChainConfigUpdatesV1_5",
325+
semver.MustParse("1.5.0"),
326+
"Not supported for v1.5 — no FeeQuoter contract exists",
327+
func(b operations.Bundle, chains cldf_chain.BlockChains, input fees.ApplyDestChainConfigSequenceInput) (sequences.OnChainOutput, error) {
328+
return sequences.OnChainOutput{}, fmt.Errorf("FeeQuoter dest chain config updates are not supported for v1.5 (no FeeQuoter contract)")
329+
},
330+
)
331+
}

chains/evm/deployment/v1_5_0/adapters/init.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
chainsel "github.com/smartcontractkit/chain-selectors"
66

77
"github.com/smartcontractkit/chainlink-ccip/deployment/fastcurse"
8+
"github.com/smartcontractkit/chainlink-ccip/deployment/fees"
89
)
910

1011
func init() {
@@ -15,4 +16,8 @@ func init() {
1516
CurseAdapter: NewCurseAdapter(),
1617
CurseSubjectAdapter: NewCurseAdapter(),
1718
})
19+
20+
defaultConcurrency := 10
21+
feeReg := fees.GetRegistry()
22+
feeReg.RegisterFeeAdapter(chainsel.FamilyEVM, semver.MustParse("1.5.0"), NewFeesAdapter(&defaultConcurrency))
1823
}

chains/evm/deployment/v1_5_1/adapters/tokens.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
tarseq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/sequences"
1414
tpOps "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/token_pool"
1515
tpSeq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/sequences/token_pool"
16-
v1_6_0_seq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_6_0/sequences"
16+
v1_5_1_seq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/sequences"
1717
"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/token_pool"
1818
tokensapi "github.com/smartcontractkit/chainlink-ccip/deployment/tokens"
1919
"github.com/smartcontractkit/chainlink-ccip/deployment/utils/sequences"
@@ -38,7 +38,7 @@ func NewTokenAdapter() *TokenAdapter {
3838
return &TokenAdapter{
3939
EVMPoolAdapter: evm1_0_0.EVMPoolAdapter{
4040
Ops: &poolOpsV151{},
41-
DeployTokenPoolSeq: v1_6_0_seq.DeployTokenPool,
41+
DeployTokenPoolSeq: v1_5_1_seq.DeployTokenPool,
4242
},
4343
}
4444
}
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
package sequences
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
7+
"github.com/ethereum/go-ethereum/common"
8+
mcms_types "github.com/smartcontractkit/mcms/types"
9+
10+
cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
11+
"github.com/smartcontractkit/chainlink-deployments-framework/datastore"
12+
"github.com/smartcontractkit/chainlink-deployments-framework/deployment"
13+
cldf_ops "github.com/smartcontractkit/chainlink-deployments-framework/operations"
14+
"github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/initial/burn_mint_erc20"
15+
16+
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/operations/contract"
17+
rmnproxyops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/operations/rmn_proxy"
18+
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_2_0/operations/router"
19+
v1_5_1_burn_from_mint_token_pool "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/burn_from_mint_token_pool"
20+
v1_5_1_burn_mint_token_pool "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/burn_mint_token_pool"
21+
v1_5_1_burn_to_address_mint_token_pool "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/burn_to_address_mint_token_pool"
22+
v1_5_1_burn_with_from_mint_token_pool "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/burn_with_from_mint_token_pool"
23+
v1_5_1_lock_release_token_pool "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_1/operations/lock_release_token_pool"
24+
tokenapi "github.com/smartcontractkit/chainlink-ccip/deployment/tokens"
25+
common_utils "github.com/smartcontractkit/chainlink-ccip/deployment/utils"
26+
datastore_utils "github.com/smartcontractkit/chainlink-ccip/deployment/utils/datastore"
27+
"github.com/smartcontractkit/chainlink-ccip/deployment/utils/sequences"
28+
)
29+
30+
var DeployTokenPool = cldf_ops.NewSequence(
31+
"deploy-token-pool-v1.5.1",
32+
common_utils.Version_1_5_1,
33+
"Deploy v1.5.1 token pool contracts",
34+
func(b cldf_ops.Bundle, chains cldf_chain.BlockChains, input tokenapi.DeployTokenPoolInput) (sequences.OnChainOutput, error) {
35+
if input.TokenPoolVersion == nil {
36+
return sequences.OnChainOutput{}, fmt.Errorf("TokenPoolVersion is required")
37+
}
38+
39+
chain := chains.EVMChains()[input.ChainSelector]
40+
qualifier := input.TokenPoolQualifier
41+
42+
tokenAddr, err := resolveTokenAddress(input)
43+
if err != nil {
44+
return sequences.OnChainOutput{}, err
45+
}
46+
if qualifier == "" {
47+
qualifier = tokenAddr
48+
}
49+
50+
matches := input.ExistingDataStore.Addresses().Filter(
51+
datastore.AddressRefByType(datastore.ContractType(input.PoolType)),
52+
datastore.AddressRefByChainSelector(input.ChainSelector),
53+
datastore.AddressRefByQualifier(qualifier),
54+
datastore.AddressRefByVersion(input.TokenPoolVersion),
55+
)
56+
if len(matches) > 1 {
57+
return sequences.OnChainOutput{}, fmt.Errorf(
58+
"multiple token pools found in datastore with type '%s', version '%s', qualifier '%s' on chain with selector %d",
59+
input.PoolType, input.TokenPoolVersion.String(), qualifier, input.ChainSelector,
60+
)
61+
}
62+
if len(matches) == 1 {
63+
b.Logger.Info("Token pool already deployed at address:", matches[0].Address)
64+
return sequences.OnChainOutput{}, nil
65+
}
66+
67+
token, err := burn_mint_erc20.NewBurnMintERC20(common.HexToAddress(tokenAddr), chain.Client)
68+
if err != nil {
69+
return sequences.OnChainOutput{}, fmt.Errorf("failed to instantiate token contract at address '%s': %w", tokenAddr, err)
70+
}
71+
tokenDecimal, err := token.Decimals(&bind.CallOpts{Context: b.GetContext()})
72+
if err != nil {
73+
return sequences.OnChainOutput{}, fmt.Errorf("failed to get token decimals for token at address '%s': %w", tokenAddr, err)
74+
}
75+
76+
routerAddr, err := datastore_utils.FindAndFormatRef(input.ExistingDataStore, datastore.AddressRef{
77+
ChainSelector: input.ChainSelector,
78+
Type: datastore.ContractType(router.ContractType),
79+
}, input.ChainSelector, datastore_utils.FullRef)
80+
if err != nil {
81+
return sequences.OnChainOutput{}, fmt.Errorf("failed to find router address in datastore for chain with selector %d: %w", input.ChainSelector, err)
82+
}
83+
84+
rmpProxyAddr, err := datastore_utils.FindAndFormatRef(input.ExistingDataStore, datastore.AddressRef{
85+
ChainSelector: input.ChainSelector,
86+
Type: datastore.ContractType(rmnproxyops.ContractType),
87+
}, input.ChainSelector, datastore_utils.FullRef)
88+
if err != nil {
89+
return sequences.OnChainOutput{}, fmt.Errorf("failed to find rmnproxy address in datastore for chain with selector %d: %w", input.ChainSelector, err)
90+
}
91+
92+
var allowlist []common.Address
93+
if len(input.Allowlist) > 0 {
94+
allowlist = make([]common.Address, 0, len(input.Allowlist))
95+
for _, addr := range input.Allowlist {
96+
allowlist = append(allowlist, common.HexToAddress(addr))
97+
}
98+
}
99+
100+
var poolRef datastore.AddressRef
101+
typeAndVersion := deployment.NewTypeAndVersion(deployment.ContractType(input.PoolType), *input.TokenPoolVersion).String()
102+
103+
switch typeAndVersion {
104+
case v1_5_1_burn_mint_token_pool.TypeAndVersion.String():
105+
poolRef, err = contract.MaybeDeployContract(b, v1_5_1_burn_mint_token_pool.Deploy, chain, contract.DeployInput[v1_5_1_burn_mint_token_pool.ConstructorArgs]{
106+
TypeAndVersion: v1_5_1_burn_mint_token_pool.TypeAndVersion,
107+
ChainSelector: chain.Selector,
108+
Args: v1_5_1_burn_mint_token_pool.ConstructorArgs{
109+
Token: common.HexToAddress(tokenAddr),
110+
LocalTokenDecimals: tokenDecimal,
111+
Allowlist: allowlist,
112+
RmnProxy: common.HexToAddress(rmpProxyAddr.Address),
113+
Router: common.HexToAddress(routerAddr.Address),
114+
},
115+
Qualifier: &qualifier,
116+
}, nil)
117+
if err != nil {
118+
return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy BurnMintTokenPool v1.5.1: %w", err)
119+
}
120+
121+
case v1_5_1_burn_from_mint_token_pool.TypeAndVersion.String():
122+
poolRef, err = contract.MaybeDeployContract(b, v1_5_1_burn_from_mint_token_pool.Deploy, chain, contract.DeployInput[v1_5_1_burn_from_mint_token_pool.ConstructorArgs]{
123+
TypeAndVersion: v1_5_1_burn_from_mint_token_pool.TypeAndVersion,
124+
ChainSelector: chain.Selector,
125+
Args: v1_5_1_burn_from_mint_token_pool.ConstructorArgs{
126+
Token: common.HexToAddress(tokenAddr),
127+
LocalTokenDecimals: tokenDecimal,
128+
Allowlist: allowlist,
129+
RmnProxy: common.HexToAddress(rmpProxyAddr.Address),
130+
Router: common.HexToAddress(routerAddr.Address),
131+
},
132+
Qualifier: &qualifier,
133+
}, nil)
134+
if err != nil {
135+
return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy BurnFromMintTokenPool v1.5.1: %w", err)
136+
}
137+
138+
case v1_5_1_burn_to_address_mint_token_pool.TypeAndVersion.String():
139+
poolRef, err = contract.MaybeDeployContract(b, v1_5_1_burn_to_address_mint_token_pool.Deploy, chain, contract.DeployInput[v1_5_1_burn_to_address_mint_token_pool.ConstructorArgs]{
140+
TypeAndVersion: v1_5_1_burn_to_address_mint_token_pool.TypeAndVersion,
141+
ChainSelector: chain.Selector,
142+
Args: v1_5_1_burn_to_address_mint_token_pool.ConstructorArgs{
143+
Token: common.HexToAddress(tokenAddr),
144+
LocalTokenDecimals: tokenDecimal,
145+
Allowlist: allowlist,
146+
RmnProxy: common.HexToAddress(rmpProxyAddr.Address),
147+
Router: common.HexToAddress(routerAddr.Address),
148+
BurnAddress: common.HexToAddress(input.BurnAddress),
149+
},
150+
Qualifier: &qualifier,
151+
}, nil)
152+
if err != nil {
153+
return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy BurnToAddressMintTokenPool v1.5.1: %w", err)
154+
}
155+
156+
case v1_5_1_burn_with_from_mint_token_pool.TypeAndVersion.String():
157+
poolRef, err = contract.MaybeDeployContract(b, v1_5_1_burn_with_from_mint_token_pool.Deploy, chain, contract.DeployInput[v1_5_1_burn_with_from_mint_token_pool.ConstructorArgs]{
158+
TypeAndVersion: v1_5_1_burn_with_from_mint_token_pool.TypeAndVersion,
159+
ChainSelector: chain.Selector,
160+
Args: v1_5_1_burn_with_from_mint_token_pool.ConstructorArgs{
161+
Token: common.HexToAddress(tokenAddr),
162+
LocalTokenDecimals: tokenDecimal,
163+
Allowlist: allowlist,
164+
RmnProxy: common.HexToAddress(rmpProxyAddr.Address),
165+
Router: common.HexToAddress(routerAddr.Address),
166+
},
167+
Qualifier: &qualifier,
168+
}, nil)
169+
if err != nil {
170+
return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy BurnWithFromMintTokenPool v1.5.1: %w", err)
171+
}
172+
173+
case v1_5_1_lock_release_token_pool.TypeAndVersion.String():
174+
poolRef, err = contract.MaybeDeployContract(b, v1_5_1_lock_release_token_pool.Deploy, chain, contract.DeployInput[v1_5_1_lock_release_token_pool.ConstructorArgs]{
175+
TypeAndVersion: v1_5_1_lock_release_token_pool.TypeAndVersion,
176+
ChainSelector: chain.Selector,
177+
Args: v1_5_1_lock_release_token_pool.ConstructorArgs{
178+
Token: common.HexToAddress(tokenAddr),
179+
LocalTokenDecimals: tokenDecimal,
180+
Allowlist: allowlist,
181+
RmnProxy: common.HexToAddress(rmpProxyAddr.Address),
182+
AcceptLiquidity: *input.AcceptLiquidity,
183+
Router: common.HexToAddress(routerAddr.Address),
184+
},
185+
Qualifier: &qualifier,
186+
}, nil)
187+
if err != nil {
188+
return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy LockReleaseTokenPool v1.5.1: %w", err)
189+
}
190+
191+
default:
192+
return sequences.OnChainOutput{}, fmt.Errorf("unsupported v1.5.1 token pool type and version: %s", typeAndVersion)
193+
}
194+
195+
batchOp, err := contract.NewBatchOperationFromWrites(nil)
196+
if err != nil {
197+
return sequences.OnChainOutput{}, fmt.Errorf("failed to create batch operation from writes: %w", err)
198+
}
199+
200+
return sequences.OnChainOutput{
201+
Addresses: []datastore.AddressRef{poolRef},
202+
BatchOps: []mcms_types.BatchOperation{batchOp},
203+
}, nil
204+
},
205+
)
206+
207+
func resolveTokenAddress(input tokenapi.DeployTokenPoolInput) (string, error) {
208+
var tokenAddr string
209+
if input.TokenRef != nil && input.TokenRef.Address != "" {
210+
tokenAddr = input.TokenRef.Address
211+
}
212+
if input.TokenRef != nil && input.TokenRef.Qualifier != "" {
213+
storedAddr, err := datastore_utils.FindAndFormatRef(input.ExistingDataStore, *input.TokenRef, input.ChainSelector, datastore_utils.FullRef)
214+
if err != nil {
215+
return "", fmt.Errorf("token with symbol '%s' is not found in datastore, %v", input.TokenRef.Qualifier, err)
216+
}
217+
if tokenAddr != "" && storedAddr.Address != tokenAddr {
218+
return "", fmt.Errorf("provided token address '%s' does not match address '%s' found in datastore for symbol '%s'", tokenAddr, storedAddr.Address, input.TokenRef.Qualifier)
219+
}
220+
if tokenAddr == "" {
221+
tokenAddr = storedAddr.Address
222+
}
223+
}
224+
if tokenAddr == "" {
225+
return "", fmt.Errorf("token address must be provided either directly or via a datastore reference")
226+
}
227+
return tokenAddr, nil
228+
}

0 commit comments

Comments
 (0)