From 3bfac631c59835b3c66e494e428dc9f59ef652fa Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Mon, 18 Nov 2024 10:46:21 +0530 Subject: [PATCH 01/22] CCIP-4160 test refactoring --- integration-tests/smoke/ccip_test.go | 349 ++++++++++++++++++--------- 1 file changed, 231 insertions(+), 118 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 007a3c37e52..8b737d2035e 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,6 +1,7 @@ package smoke import ( + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "math/big" "testing" @@ -112,54 +113,36 @@ func TestInitialDeployOnLocal(t *testing.T) { func TestTokenTransfer(t *testing.T) { t.Parallel() - lggr := logger.TestLogger(t) - ctx := ccdeploy.Context(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + tenv, state := setupEnvironment(t) - e := tenv.Env - state, err := ccdeploy.LoadOnchainState(e) - require.NoError(t, err) - - output, err := changeset.DeployPrerequisites(e, changeset.DeployPrerequisiteConfig{ - ChainSelectors: e.AllChainSelectors(), + output, err := changeset.DeployPrerequisites(tenv.Env, changeset.DeployPrerequisiteConfig{ + ChainSelectors: tenv.Env.AllChainSelectors(), }) + require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) - // Apply migration - output, err = changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{ + // Deploy CCIP contracts + output, err = changeset.InitialDeploy(tenv.Env, ccdeploy.DeployCCIPContractConfig{ HomeChainSel: tenv.HomeChainSel, FeedChainSel: tenv.FeedChainSel, - ChainsToDeploy: e.AllChainSelectors(), + ChainsToDeploy: tenv.Env.AllChainSelectors(), TokenConfig: ccdeploy.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), - MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, tenv.Env), OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), }) require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - // Get new state after migration and mock USDC token deployment. - state, err = ccdeploy.LoadOnchainState(e) - require.NoError(t, err) - - srcToken, _, dstToken, _, err := ccdeploy.DeployTransferableToken( - lggr, - tenv.Env.Chains, - tenv.HomeChainSel, - tenv.FeedChainSel, - state, - e.ExistingAddresses, - "MY_TOKEN", - ) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + state, err = ccdeploy.LoadOnchainState(tenv.Env) require.NoError(t, err) - // Ensure capreg logs are up to date. - ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + // Replay logs + ccdeploy.ReplayLogs(t, tenv.Env.Offchain, tenv.ReplayBlocks) - // Apply the jobs. + // Apply the jobs for nodeID, jobs := range output.JobSpecs { for _, job := range jobs { - // Note these auto-accept - _, err := e.Offchain.ProposeJob(ctx, + _, err := tenv.Env.Offchain.ProposeJob(ccdeploy.Context(t), &jobv1.ProposeJobRequest{ NodeId: nodeID, Spec: job, @@ -169,104 +152,234 @@ func TestTokenTransfer(t *testing.T) { } // Add all lanes - require.NoError(t, ccdeploy.AddLanesForAll(e, state)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[uint64]uint64) - - twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) - tx, err := srcToken.Mint( - e.Chains[tenv.HomeChainSel].DeployerKey, - e.Chains[tenv.HomeChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = dstToken.Mint( - e.Chains[tenv.FeedChainSel].DeployerKey, - e.Chains[tenv.FeedChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) + require.NoError(t, ccdeploy.AddLanesForAll(tenv.Env, state)) + + // Deploy and approve tokens + srcToken1, dstToken1 := deployAndApproveTokens(t, tenv, state, "Token1") + srcToken2, dstToken2 := deployAndApproveTokens(t, tenv, state, "Token2") + + // Define your scenarios + scenarios := []struct { + name string + srcChain uint64 + dstChain uint64 + tokenAmounts []router.ClientEVMTokenAmount + receiver common.Address + data []byte + }{ + { + name: "Send token to EOA", + srcChain: tenv.HomeChainSel, + dstChain: tenv.FeedChainSel, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken1.Address(), + Amount: big.NewInt(1e18), + }, + }, + receiver: tenv.Env.Chains[tenv.FeedChainSel].DeployerKey.From, + data: []byte(""), + }, + { + name: "Send token to contract", + srcChain: tenv.HomeChainSel, // Will be set in the test + dstChain: tenv.FeedChainSel, // Will be set in the test + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken1.Address(), // Will be set in the test + Amount: big.NewInt(1e18), + }, + }, + receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), // Will be set in the test + data: []byte(""), + }, + { + name: "Send 2 tokens to receiver", + srcChain: tenv.HomeChainSel, + dstChain: tenv.FeedChainSel, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken1.Address(), + Amount: big.NewInt(1e18), + }, + { + Token: srcToken2.Address(), + Amount: big.NewInt(2e18), + }, + }, + receiver: tenv.Env.Chains[tenv.FeedChainSel].DeployerKey.From, + data: []byte(""), + }, + { + name: "Send N tokens to contract", + srcChain: tenv.HomeChainSel, + dstChain: tenv.FeedChainSel, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken1.Address(), + Amount: big.NewInt(1e18), + }, + { + Token: srcToken2.Address(), + Amount: big.NewInt(2e18), + }, + { + Token: srcToken1.Address(), + Amount: big.NewInt(3e18), + }, + }, + receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), + data: []byte(""), + }, + } - tx, err = srcToken.Approve(e.Chains[tenv.HomeChainSel].DeployerKey, state.Chains[tenv.HomeChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - tx, err = dstToken.Approve(e.Chains[tenv.FeedChainSel].DeployerKey, state.Chains[tenv.FeedChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) + for _, scenario := range scenarios { + scenario := scenario // Capture range variable + t.Run(scenario.name, func(t *testing.T) { - tokens := map[uint64][]router.ClientEVMTokenAmount{ - tenv.HomeChainSel: {{ - Token: srcToken.Address(), - Amount: twoCoins, - }}, - tenv.FeedChainSel: {{ - Token: dstToken.Address(), - Amount: twoCoins, - }}, - } + // Prepare for message sending + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[uint64]uint64) - for src := range e.Chains { - for dest, destChain := range e.Chains { - if src == dest { - continue - } + destChain := tenv.Env.Chains[scenario.dstChain] latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) require.NoError(t, err) block := latesthdr.Number.Uint64() - startBlocks[dest] = &block + startBlocks[scenario.dstChain] = &block + + // Fetch initial balances and aggregate total amounts + initialBalances := make(map[common.Address]*big.Int) + totalAmountsTransferred := make(map[common.Address]*big.Int) + + for _, tokenAmount := range scenario.tokenAmounts { + dstToken := getDestinationToken(scenario, tenv, srcToken1, dstToken1, srcToken2, dstToken2, tokenAmount.Token) + require.NotNil(t, dstToken, "Destination token not found") + + // Fetch initial balance + if _, exists := initialBalances[dstToken.Address()]; !exists { + balance, err := dstToken.BalanceOf(nil, scenario.receiver) + require.NoError(t, err) + initialBalances[dstToken.Address()] = balance + } + + // Initialize and sum up total amounts + if _, exists := totalAmountsTransferred[dstToken.Address()]; !exists { + totalAmountsTransferred[dstToken.Address()] = big.NewInt(0) + } + totalAmountsTransferred[dstToken.Address()].Add(totalAmountsTransferred[dstToken.Address()], tokenAmount.Amount) + } - var ( - receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32) - data = []byte("hello world") - feeToken = common.HexToAddress("0x0") - ) - if src == tenv.HomeChainSel && dest == tenv.FeedChainSel { - msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: tokens[src], - FeeToken: feeToken, - ExtraArgs: nil, - }) - expectedSeqNum[dest] = msgSentEvent.SequenceNumber - } else { - msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: nil, - FeeToken: feeToken, - ExtraArgs: nil, - }) - expectedSeqNum[dest] = msgSentEvent.SequenceNumber + // Prepare message + msg := router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(scenario.receiver.Bytes(), 32), + Data: scenario.data, + TokenAmounts: scenario.tokenAmounts, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, } - } + + // Send the message + msgSentEvent := ccdeploy.TestSendRequest(t, tenv.Env, state, scenario.srcChain, scenario.dstChain, false, msg) + expectedSeqNum[scenario.dstChain] = msgSentEvent.SequenceNumber + + // Wait for commit and execution + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, tenv.Env, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmExecWithSeqNrForAll(t, tenv.Env, state, expectedSeqNum, startBlocks) + + // Fetch final balances and assert + for tokenAddress, totalAmount := range totalAmountsTransferred { + dstToken := getTokenByAddress(dstToken1, dstToken2, tokenAddress) + require.NotNil(t, dstToken, "Destination token not found for address %s", tokenAddress.Hex()) + + finalBalance, err := dstToken.BalanceOf(nil, scenario.receiver) + require.NoError(t, err) + + initialBalance := initialBalances[dstToken.Address()] + expectedBalance := new(big.Int).Add(initialBalance, totalAmount) + + require.Equal(t, expectedBalance, finalBalance, "Incorrect balance for token %s", dstToken.Address().Hex()) + } + }) } +} - // Wait for all commit reports to land. - ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) +func getTokenByAddress(dstToken1, dstToken2 *burn_mint_erc677.BurnMintERC677, tokenAddress common.Address) *burn_mint_erc677.BurnMintERC677 { + if dstToken1.Address() == tokenAddress { + return dstToken1 + } else if dstToken2.Address() == tokenAddress { + return dstToken2 + } + return nil +} - // After commit is reported on all chains, token prices should be updated in FeeQuoter. - for dest := range e.Chains { - linkAddress := state.Chains[dest].LinkToken.Address() - feeQuoter := state.Chains[dest].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) - require.NoError(t, err) - require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) +// Helper function to determine the destination token +func getDestinationToken(scenario struct { + name string + srcChain uint64 + dstChain uint64 + tokenAmounts []router.ClientEVMTokenAmount + receiver common.Address + data []byte +}, tenv ccdeploy.DeployedEnv, srcToken1, dstToken1, srcToken2, dstToken2 *burn_mint_erc677.BurnMintERC677, tokenAddress common.Address) *burn_mint_erc677.BurnMintERC677 { + if scenario.srcChain == tenv.HomeChainSel && scenario.dstChain == tenv.FeedChainSel { + if tokenAddress == srcToken1.Address() { + return dstToken1 + } else if tokenAddress == srcToken2.Address() { + return dstToken2 + } + } else if scenario.srcChain == tenv.FeedChainSel && scenario.dstChain == tenv.HomeChainSel { + if tokenAddress == dstToken1.Address() { + return srcToken1 + } else if tokenAddress == dstToken2.Address() { + return srcToken2 + } } + return nil +} - // Wait for all exec reports to land - ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) +func setupEnvironment(t *testing.T) (ccdeploy.DeployedEnv, ccdeploy.CCIPOnChainState) { + lggr := logger.TestLogger(t) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 2, 4, ccdeploy.MockLinkPrice, ccdeploy.MockWethPrice) + state, err := ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, err) + return tenv, state +} + +func deployAndApproveTokens(t *testing.T, e ccdeploy.DeployedEnv, state ccdeploy.CCIPOnChainState, tokenName string) (*burn_mint_erc677.BurnMintERC677, *burn_mint_erc677.BurnMintERC677) { + srcToken, _, dstToken, _, err := ccdeploy.DeployTransferableToken( + logger.TestLogger(t), + e.Env.Chains, + e.HomeChainSel, + e.FeedChainSel, + state, + e.Env.ExistingAddresses, + tokenName, + ) + require.NoError(t, err) + + tenTokens := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)) + mintAndApprove(t, e, state, srcToken, e.HomeChainSel, tenTokens) + mintAndApprove(t, e, state, dstToken, e.FeedChainSel, tenTokens) + + return srcToken, dstToken +} - balance, err := dstToken.BalanceOf(nil, state.Chains[tenv.FeedChainSel].Receiver.Address()) +func mintAndApprove(t *testing.T, e ccdeploy.DeployedEnv, state ccdeploy.CCIPOnChainState, token *burn_mint_erc677.BurnMintERC677, chainSel uint64, amount *big.Int) { + tx, err := token.Mint( + e.Env.Chains[chainSel].DeployerKey, + e.Env.Chains[chainSel].DeployerKey.From, + amount, + ) + require.NoError(t, err) + _, err = e.Env.Chains[chainSel].Confirm(tx) + require.NoError(t, err) + + tx, err = token.Approve( + e.Env.Chains[chainSel].DeployerKey, + state.Chains[chainSel].Router.Address(), + amount, + ) + require.NoError(t, err) + _, err = e.Env.Chains[chainSel].Confirm(tx) require.NoError(t, err) - require.Equal(t, twoCoins, balance) } From 46176218a92bf84b84bf050203ddc9871b612e29 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Tue, 19 Nov 2024 18:21:19 +0530 Subject: [PATCH 02/22] resolving imports and using local dev env --- integration-tests/smoke/ccip_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 8b737d2035e..1ee01a085ed 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,21 +1,21 @@ package smoke import ( - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "math/big" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -339,7 +339,7 @@ func getDestinationToken(scenario struct { func setupEnvironment(t *testing.T) (ccdeploy.DeployedEnv, ccdeploy.CCIPOnChainState) { lggr := logger.TestLogger(t) - tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 2, 4, ccdeploy.MockLinkPrice, ccdeploy.MockWethPrice) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) state, err := ccdeploy.LoadOnchainState(tenv.Env) require.NoError(t, err) return tenv, state From 24dd4f65c0758074f52372d37e3b13646126a12d Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Tue, 19 Nov 2024 19:34:43 +0530 Subject: [PATCH 03/22] comments fix --- integration-tests/smoke/ccip_test.go | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 1ee01a085ed..a1d485d12ec 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -114,35 +114,35 @@ func TestInitialDeployOnLocal(t *testing.T) { func TestTokenTransfer(t *testing.T) { t.Parallel() tenv, state := setupEnvironment(t) - + e := tenv.Env output, err := changeset.DeployPrerequisites(tenv.Env, changeset.DeployPrerequisiteConfig{ - ChainSelectors: tenv.Env.AllChainSelectors(), + ChainSelectors: e.AllChainSelectors(), }) require.NoError(t, err) - require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) // Deploy CCIP contracts - output, err = changeset.InitialDeploy(tenv.Env, ccdeploy.DeployCCIPContractConfig{ + output, err = changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{ HomeChainSel: tenv.HomeChainSel, FeedChainSel: tenv.FeedChainSel, - ChainsToDeploy: tenv.Env.AllChainSelectors(), + ChainsToDeploy: e.AllChainSelectors(), TokenConfig: ccdeploy.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), - MCMSConfig: ccdeploy.NewTestMCMSConfig(t, tenv.Env), + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), }) require.NoError(t, err) - require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) - state, err = ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + state, err = ccdeploy.LoadOnchainState(e) require.NoError(t, err) - // Replay logs - ccdeploy.ReplayLogs(t, tenv.Env.Offchain, tenv.ReplayBlocks) + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) - // Apply the jobs + // Apply the jobs. for nodeID, jobs := range output.JobSpecs { for _, job := range jobs { - _, err := tenv.Env.Offchain.ProposeJob(ccdeploy.Context(t), + _, err := e.Offchain.ProposeJob(ccdeploy.Context(t), &jobv1.ProposeJobRequest{ NodeId: nodeID, Spec: job, @@ -151,14 +151,14 @@ func TestTokenTransfer(t *testing.T) { } } - // Add all lanes - require.NoError(t, ccdeploy.AddLanesForAll(tenv.Env, state)) + // Add all lanes. + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) - // Deploy and approve tokens + // Deploy and approve tokens. srcToken1, dstToken1 := deployAndApproveTokens(t, tenv, state, "Token1") srcToken2, dstToken2 := deployAndApproveTokens(t, tenv, state, "Token2") - // Define your scenarios + // Define your scenarios. scenarios := []struct { name string srcChain uint64 @@ -177,7 +177,7 @@ func TestTokenTransfer(t *testing.T) { Amount: big.NewInt(1e18), }, }, - receiver: tenv.Env.Chains[tenv.FeedChainSel].DeployerKey.From, + receiver: e.Chains[tenv.FeedChainSel].DeployerKey.From, data: []byte(""), }, { @@ -207,7 +207,7 @@ func TestTokenTransfer(t *testing.T) { Amount: big.NewInt(2e18), }, }, - receiver: tenv.Env.Chains[tenv.FeedChainSel].DeployerKey.From, + receiver: e.Chains[tenv.FeedChainSel].DeployerKey.From, data: []byte(""), }, { @@ -241,7 +241,7 @@ func TestTokenTransfer(t *testing.T) { startBlocks := make(map[uint64]*uint64) expectedSeqNum := make(map[uint64]uint64) - destChain := tenv.Env.Chains[scenario.dstChain] + destChain := e.Chains[scenario.dstChain] latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) require.NoError(t, err) block := latesthdr.Number.Uint64() @@ -279,12 +279,12 @@ func TestTokenTransfer(t *testing.T) { } // Send the message - msgSentEvent := ccdeploy.TestSendRequest(t, tenv.Env, state, scenario.srcChain, scenario.dstChain, false, msg) + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, scenario.srcChain, scenario.dstChain, false, msg) expectedSeqNum[scenario.dstChain] = msgSentEvent.SequenceNumber // Wait for commit and execution - ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, tenv.Env, state, expectedSeqNum, startBlocks) - ccdeploy.ConfirmExecWithSeqNrForAll(t, tenv.Env, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) // Fetch final balances and assert for tokenAddress, totalAmount := range totalAmountsTransferred { From 8bae382f8fcdf681d2ceaa2042dd07042352d6b9 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Tue, 19 Nov 2024 19:48:59 +0530 Subject: [PATCH 04/22] comments fix --- integration-tests/smoke/ccip_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index a1d485d12ec..1991b5bedb4 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -158,7 +158,7 @@ func TestTokenTransfer(t *testing.T) { srcToken1, dstToken1 := deployAndApproveTokens(t, tenv, state, "Token1") srcToken2, dstToken2 := deployAndApproveTokens(t, tenv, state, "Token2") - // Define your scenarios. + // Test scenarios are defined here scenarios := []struct { name string srcChain uint64 @@ -182,15 +182,15 @@ func TestTokenTransfer(t *testing.T) { }, { name: "Send token to contract", - srcChain: tenv.HomeChainSel, // Will be set in the test - dstChain: tenv.FeedChainSel, // Will be set in the test + srcChain: tenv.HomeChainSel, + dstChain: tenv.FeedChainSel, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: srcToken1.Address(), // Will be set in the test + Token: srcToken1.Address(), Amount: big.NewInt(1e18), }, }, - receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), // Will be set in the test + receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), data: []byte(""), }, { @@ -234,10 +234,9 @@ func TestTokenTransfer(t *testing.T) { } for _, scenario := range scenarios { - scenario := scenario // Capture range variable + scenario := scenario t.Run(scenario.name, func(t *testing.T) { - // Prepare for message sending startBlocks := make(map[uint64]*uint64) expectedSeqNum := make(map[uint64]uint64) @@ -269,7 +268,6 @@ func TestTokenTransfer(t *testing.T) { totalAmountsTransferred[dstToken.Address()].Add(totalAmountsTransferred[dstToken.Address()], tokenAmount.Amount) } - // Prepare message msg := router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(scenario.receiver.Bytes(), 32), Data: scenario.data, From 94a2527584d548550ea42eb485a7fa8bb2eddff5 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 21 Nov 2024 19:38:25 +0530 Subject: [PATCH 05/22] test update with common methods --- integration-tests/smoke/ccip_test.go | 396 ++++++--------------------- 1 file changed, 78 insertions(+), 318 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 28a6b4e7e58..410e99a8e65 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,6 +1,8 @@ package smoke import ( + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "golang.org/x/exp/maps" "math/big" "testing" @@ -72,74 +74,73 @@ func TestInitialDeployOnLocal(t *testing.T) { } func TestTokenTransfer(t *testing.T) { - t.Parallel() - tenv, state := setupEnvironment(t) - e := tenv.Env -<<<<<<< HEAD - output, err := changeset.DeployPrerequisites(tenv.Env, changeset.DeployPrerequisiteConfig{ - ChainSelectors: e.AllChainSelectors(), - }) + lggr := logger.TestLogger(t) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + e := tenv.Env + state, err := changeset.LoadOnchainState(e) require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - // Deploy CCIP contracts - output, err = changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{ - HomeChainSel: tenv.HomeChainSel, - FeedChainSel: tenv.FeedChainSel, - ChainsToDeploy: e.AllChainSelectors(), - TokenConfig: ccdeploy.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), - MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - }) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - state, err = ccdeploy.LoadOnchainState(e) - require.NoError(t, err) + allChainSelectors := maps.Keys(e.Chains) + sourceChain := allChainSelectors[0] + destChain := allChainSelectors[1] - // Ensure capreg logs are up to date. - ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + srcToken1, _, destToken1, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + state, + e.ExistingAddresses, + "MY_TOKEN_1", + ) + require.NoError(t, err) - // Apply the jobs. - for nodeID, jobs := range output.JobSpecs { - for _, job := range jobs { - _, err := e.Offchain.ProposeJob(ccdeploy.Context(t), - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } + srcToken2, _, destToken2, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + state, + e.ExistingAddresses, + "MY_TOKEN_2", + ) + require.NoError(t, err) // Add all lanes. - require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + require.NoError(t, changeset.AddLanesForAll(e, state)) + + mintAndAllow(t, e, state, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {srcToken1, srcToken2}, + destChain: {destToken1, destToken2}, + }) - // Deploy and approve tokens. - srcToken1, dstToken1 := deployAndApproveTokens(t, tenv, state, "Token1") - srcToken2, dstToken2 := deployAndApproveTokens(t, tenv, state, "Token2") + tinyOneCoin := new(big.Int).SetUint64(1) // Test scenarios are defined here scenarios := []struct { - name string - srcChain uint64 - dstChain uint64 - tokenAmounts []router.ClientEVMTokenAmount - receiver common.Address - data []byte + name string + srcChain uint64 + dstChain uint64 + tokenAmounts []router.ClientEVMTokenAmount + receiver common.Address + data []byte + expectedTokenBalances map[common.Address]*big.Int }{ { name: "Send token to EOA", - srcChain: tenv.HomeChainSel, - dstChain: tenv.FeedChainSel, + srcChain: sourceChain, + dstChain: destChain, tokenAmounts: []router.ClientEVMTokenAmount{ { Token: srcToken1.Address(), - Amount: big.NewInt(1e18), + Amount: tinyOneCoin, }, }, - receiver: e.Chains[tenv.FeedChainSel].DeployerKey.From, - data: []byte(""), + receiver: utils.RandomAddress(), + expectedTokenBalances: map[common.Address]*big.Int{ + srcToken1.Address(): tinyOneCoin, + }, }, { name: "Send token to contract", @@ -148,11 +149,10 @@ func TestTokenTransfer(t *testing.T) { tokenAmounts: []router.ClientEVMTokenAmount{ { Token: srcToken1.Address(), - Amount: big.NewInt(1e18), + Amount: tinyOneCoin, }, }, receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), - data: []byte(""), }, { name: "Send 2 tokens to receiver", @@ -161,15 +161,14 @@ func TestTokenTransfer(t *testing.T) { tokenAmounts: []router.ClientEVMTokenAmount{ { Token: srcToken1.Address(), - Amount: big.NewInt(1e18), + Amount: tinyOneCoin, }, { Token: srcToken2.Address(), - Amount: big.NewInt(2e18), + Amount: tinyOneCoin, }, }, - receiver: e.Chains[tenv.FeedChainSel].DeployerKey.From, - data: []byte(""), + receiver: e.Chains[destChain].DeployerKey.From, }, { name: "Send N tokens to contract", @@ -178,286 +177,47 @@ func TestTokenTransfer(t *testing.T) { tokenAmounts: []router.ClientEVMTokenAmount{ { Token: srcToken1.Address(), - Amount: big.NewInt(1e18), + Amount: tinyOneCoin, }, { Token: srcToken2.Address(), - Amount: big.NewInt(2e18), + Amount: tinyOneCoin, }, { Token: srcToken1.Address(), - Amount: big.NewInt(3e18), + Amount: tinyOneCoin, }, }, - receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), - data: []byte(""), + receiver: state.Chains[destChain].Receiver.Address(), }, } for _, scenario := range scenarios { scenario := scenario t.Run(scenario.name, func(t *testing.T) { -======= - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - srcToken, _, dstToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - tenv.HomeChainSel, - tenv.FeedChainSel, - state, - e.ExistingAddresses, - "MY_TOKEN", - ) - require.NoError(t, err) - - // Add all lanes - require.NoError(t, changeset.AddLanesForAll(e, state)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - - twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) - tx, err := srcToken.Mint( - e.Chains[tenv.HomeChainSel].DeployerKey, - e.Chains[tenv.HomeChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = dstToken.Mint( - e.Chains[tenv.FeedChainSel].DeployerKey, - e.Chains[tenv.FeedChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = srcToken.Approve(e.Chains[tenv.HomeChainSel].DeployerKey, state.Chains[tenv.HomeChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - tx, err = dstToken.Approve(e.Chains[tenv.FeedChainSel].DeployerKey, state.Chains[tenv.FeedChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) - - tokens := map[uint64][]router.ClientEVMTokenAmount{ - tenv.HomeChainSel: {{ - Token: srcToken.Address(), - Amount: twoCoins, - }}, - tenv.FeedChainSel: {{ - Token: dstToken.Address(), - Amount: twoCoins, - }}, - } - - for src := range e.Chains { - for dest, destChain := range e.Chains { - if src == dest { - continue - } - latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[dest] = &block - - var ( - receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32) - data = []byte("hello world") - feeToken = common.HexToAddress("0x0") - ) - if src == tenv.HomeChainSel && dest == tenv.FeedChainSel { - msgSentEvent := changeset.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: tokens[src], - FeeToken: feeToken, - ExtraArgs: nil, - }) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber - } else { - msgSentEvent := changeset.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: nil, - FeeToken: feeToken, - ExtraArgs: nil, - }) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber - } - } - } - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - - // After commit is reported on all chains, token prices should be updated in FeeQuoter. - for dest := range e.Chains { - linkAddress := state.Chains[dest].LinkToken.Address() - feeQuoter := state.Chains[dest].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) - require.NoError(t, err) - require.Equal(t, changeset.MockLinkPrice, timestampedPrice.Value) - } - - // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) ->>>>>>> develop - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[uint64]uint64) - - destChain := e.Chains[scenario.dstChain] - latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[scenario.dstChain] = &block - - // Fetch initial balances and aggregate total amounts - initialBalances := make(map[common.Address]*big.Int) - totalAmountsTransferred := make(map[common.Address]*big.Int) - - for _, tokenAmount := range scenario.tokenAmounts { - dstToken := getDestinationToken(scenario, tenv, srcToken1, dstToken1, srcToken2, dstToken2, tokenAmount.Token) - require.NotNil(t, dstToken, "Destination token not found") - - // Fetch initial balance - if _, exists := initialBalances[dstToken.Address()]; !exists { - balance, err := dstToken.BalanceOf(nil, scenario.receiver) - require.NoError(t, err) - initialBalances[dstToken.Address()] = balance + t.Run(scenario.name, func(t *testing.T) { + initialBalances := map[common.Address]*big.Int{} + for token := range scenario.expectedTokenBalances { + initialBalance := getTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain]) + initialBalances[token] = initialBalance } - // Initialize and sum up total amounts - if _, exists := totalAmountsTransferred[dstToken.Address()]; !exists { - totalAmountsTransferred[dstToken.Address()] = big.NewInt(0) + transferAndWaitForSuccess( + t, + e, + state, + scenario.srcChain, + scenario.dstChain, + scenario.tokenAmounts, + scenario.receiver, + scenario.data, + ) + + for token, balance := range scenario.expectedTokenBalances { + expected := new(big.Int).Add(initialBalances[token], balance) + waitForTheTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain], expected) } - totalAmountsTransferred[dstToken.Address()].Add(totalAmountsTransferred[dstToken.Address()], tokenAmount.Amount) - } - - msg := router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(scenario.receiver.Bytes(), 32), - Data: scenario.data, - TokenAmounts: scenario.tokenAmounts, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - } - - // Send the message - msgSentEvent := ccdeploy.TestSendRequest(t, e, state, scenario.srcChain, scenario.dstChain, false, msg) - expectedSeqNum[scenario.dstChain] = msgSentEvent.SequenceNumber - - // Wait for commit and execution - ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) - - // Fetch final balances and assert - for tokenAddress, totalAmount := range totalAmountsTransferred { - dstToken := getTokenByAddress(dstToken1, dstToken2, tokenAddress) - require.NotNil(t, dstToken, "Destination token not found for address %s", tokenAddress.Hex()) - - finalBalance, err := dstToken.BalanceOf(nil, scenario.receiver) - require.NoError(t, err) - - initialBalance := initialBalances[dstToken.Address()] - expectedBalance := new(big.Int).Add(initialBalance, totalAmount) - - require.Equal(t, expectedBalance, finalBalance, "Incorrect balance for token %s", dstToken.Address().Hex()) - } + }) }) } } - -func getTokenByAddress(dstToken1, dstToken2 *burn_mint_erc677.BurnMintERC677, tokenAddress common.Address) *burn_mint_erc677.BurnMintERC677 { - if dstToken1.Address() == tokenAddress { - return dstToken1 - } else if dstToken2.Address() == tokenAddress { - return dstToken2 - } - return nil -} - -// Helper function to determine the destination token -func getDestinationToken(scenario struct { - name string - srcChain uint64 - dstChain uint64 - tokenAmounts []router.ClientEVMTokenAmount - receiver common.Address - data []byte -}, tenv ccdeploy.DeployedEnv, srcToken1, dstToken1, srcToken2, dstToken2 *burn_mint_erc677.BurnMintERC677, tokenAddress common.Address) *burn_mint_erc677.BurnMintERC677 { - if scenario.srcChain == tenv.HomeChainSel && scenario.dstChain == tenv.FeedChainSel { - if tokenAddress == srcToken1.Address() { - return dstToken1 - } else if tokenAddress == srcToken2.Address() { - return dstToken2 - } - } else if scenario.srcChain == tenv.FeedChainSel && scenario.dstChain == tenv.HomeChainSel { - if tokenAddress == dstToken1.Address() { - return srcToken1 - } else if tokenAddress == dstToken2.Address() { - return srcToken2 - } - } - return nil -} - -func setupEnvironment(t *testing.T) (ccdeploy.DeployedEnv, ccdeploy.CCIPOnChainState) { - lggr := logger.TestLogger(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) - state, err := ccdeploy.LoadOnchainState(tenv.Env) - require.NoError(t, err) - return tenv, state -} - -func deployAndApproveTokens(t *testing.T, e ccdeploy.DeployedEnv, state ccdeploy.CCIPOnChainState, tokenName string) (*burn_mint_erc677.BurnMintERC677, *burn_mint_erc677.BurnMintERC677) { - srcToken, _, dstToken, _, err := ccdeploy.DeployTransferableToken( - logger.TestLogger(t), - e.Env.Chains, - e.HomeChainSel, - e.FeedChainSel, - state, - e.Env.ExistingAddresses, - tokenName, - ) - require.NoError(t, err) - - tenTokens := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)) - mintAndApprove(t, e, state, srcToken, e.HomeChainSel, tenTokens) - mintAndApprove(t, e, state, dstToken, e.FeedChainSel, tenTokens) - - return srcToken, dstToken -} - -func mintAndApprove(t *testing.T, e ccdeploy.DeployedEnv, state ccdeploy.CCIPOnChainState, token *burn_mint_erc677.BurnMintERC677, chainSel uint64, amount *big.Int) { - tx, err := token.Mint( - e.Env.Chains[chainSel].DeployerKey, - e.Env.Chains[chainSel].DeployerKey.From, - amount, - ) - require.NoError(t, err) - _, err = e.Env.Chains[chainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = token.Approve( - e.Env.Chains[chainSel].DeployerKey, - state.Chains[chainSel].Router.Address(), - amount, - ) - require.NoError(t, err) - _, err = e.Env.Chains[chainSel].Confirm(tx) - require.NoError(t, err) -} From 9be196667cd21031f46e9cf796d20eee905bc99c Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 21 Nov 2024 19:46:02 +0530 Subject: [PATCH 06/22] import fix for lint --- integration-tests/smoke/ccip_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 410e99a8e65..95a178c3dd7 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,18 +1,19 @@ package smoke import ( - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "golang.org/x/exp/maps" "math/big" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" From 3d969d69ce0697b241e949a365d46f9a0fd4bdbb Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Fri, 22 Nov 2024 21:13:23 +0530 Subject: [PATCH 07/22] refactor: updated test with new setup --- integration-tests/smoke/ccip/ccip_test.go | 72 +++++++++++++++-------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index b1bbbc39146..e5bd39be519 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,6 +1,7 @@ package smoke import ( + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "math/big" "testing" @@ -13,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -81,7 +81,14 @@ func TestInitialDeployOnLocal(t *testing.T) { func TestTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, nil) + config := &changeset.TestConfigs{} + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + + /* + * use this if you are testing locally in memory + * tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) + */ + e := tenv.Env state, err := changeset.LoadOnchainState(e) require.NoError(t, err) @@ -124,13 +131,14 @@ func TestTokenTransfer(t *testing.T) { // Test scenarios are defined here scenarios := []struct { - name string - srcChain uint64 - dstChain uint64 - tokenAmounts []router.ClientEVMTokenAmount - receiver common.Address - data []byte - expectedTokenBalances map[common.Address]*big.Int + name string + srcChain uint64 + dstChain uint64 + tokenAmounts []router.ClientEVMTokenAmount + receiver common.Address + data []byte + expectedTokenBalances map[common.Address]*big.Int + expectedExecutionState int }{ { name: "Send token to EOA", @@ -144,56 +152,71 @@ func TestTokenTransfer(t *testing.T) { }, receiver: utils.RandomAddress(), expectedTokenBalances: map[common.Address]*big.Int{ - srcToken1.Address(): tinyOneCoin, + destToken1.Address(): tinyOneCoin, }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, { name: "Send token to contract", - srcChain: tenv.HomeChainSel, - dstChain: tenv.FeedChainSel, + srcChain: sourceChain, + dstChain: destChain, tokenAmounts: []router.ClientEVMTokenAmount{ { Token: srcToken1.Address(), Amount: tinyOneCoin, }, }, - receiver: state.Chains[tenv.FeedChainSel].Receiver.Address(), + receiver: state.Chains[destChain].Receiver.Address(), + expectedTokenBalances: map[common.Address]*big.Int{ + destToken1.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, { name: "Send 2 tokens to receiver", - srcChain: tenv.HomeChainSel, - dstChain: tenv.FeedChainSel, + srcChain: destChain, + dstChain: sourceChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: srcToken1.Address(), + Token: destToken1.Address(), Amount: tinyOneCoin, }, { - Token: srcToken2.Address(), + Token: destToken2.Address(), Amount: tinyOneCoin, }, }, - receiver: e.Chains[destChain].DeployerKey.From, + receiver: e.Chains[sourceChain].DeployerKey.From, + expectedTokenBalances: map[common.Address]*big.Int{ + srcToken1.Address(): tinyOneCoin, + srcToken2.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, { name: "Send N tokens to contract", - srcChain: tenv.HomeChainSel, - dstChain: tenv.FeedChainSel, + srcChain: destChain, + dstChain: sourceChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: srcToken1.Address(), + Token: destToken1.Address(), Amount: tinyOneCoin, }, { - Token: srcToken2.Address(), + Token: destToken2.Address(), Amount: tinyOneCoin, }, { - Token: srcToken1.Address(), + Token: destToken1.Address(), Amount: tinyOneCoin, }, }, - receiver: state.Chains[destChain].Receiver.Address(), + receiver: state.Chains[sourceChain].Receiver.Address(), + expectedTokenBalances: map[common.Address]*big.Int{ + srcToken1.Address(): new(big.Int).SetUint64(2), + srcToken2.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, } @@ -216,6 +239,7 @@ func TestTokenTransfer(t *testing.T) { scenario.tokenAmounts, scenario.receiver, scenario.data, + scenario.expectedExecutionState, ) for token, balance := range scenario.expectedTokenBalances { From e2182dd1d89c199f00d5f4e3b1bb12aae6fd6452 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Fri, 22 Nov 2024 21:26:08 +0530 Subject: [PATCH 08/22] fix: lint (imports) --- integration-tests/smoke/ccip/ccip_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index e5bd39be519..2d8e573b8fd 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,7 +1,6 @@ package smoke import ( - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "math/big" "testing" @@ -14,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" From 1bc99b34d1588da6e0ea81e71fee3077b3a3ab8f Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Wed, 27 Nov 2024 12:51:59 +0100 Subject: [PATCH 09/22] Yolo --- deployment/ccip/changeset/test_helpers.go | 44 +++++------ .../ccip/changeset/test_usdc_helpers.go | 4 +- integration-tests/smoke/ccip/ccip_test.go | 73 ++++++++++++++++--- .../smoke/ccip/ccip_usdc_test.go | 10 ++- 4 files changed, 94 insertions(+), 37 deletions(-) diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index ac14a720035..9c225213c7a 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -697,53 +697,54 @@ func DeployTransferableToken( lggr logger.Logger, chains map[uint64]deployment.Chain, src, dst uint64, + srcActor, dstActor *bind.TransactOpts, state CCIPOnChainState, addresses deployment.AddressBook, token string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { // Deploy token and pools - srcToken, srcPool, err := deployTransferTokenOneEnd(lggr, chains[src], addresses, token) + srcToken, srcPool, err := deployTransferTokenOneEnd(lggr, chains[src], srcActor, addresses, token) if err != nil { return nil, nil, nil, nil, err } - dstToken, dstPool, err := deployTransferTokenOneEnd(lggr, chains[dst], addresses, token) + dstToken, dstPool, err := deployTransferTokenOneEnd(lggr, chains[dst], dstActor, addresses, token) if err != nil { return nil, nil, nil, nil, err } // Attach token pools to registry - if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { + if err := attachTokenToTheRegistry(chains[src], state.Chains[src], srcActor, srcToken.Address(), srcPool.Address()); err != nil { return nil, nil, nil, nil, err } - if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { + if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], dstActor, dstToken.Address(), dstPool.Address()); err != nil { return nil, nil, nil, nil, err } // Connect pool to each other - if err := setTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { + if err := setTokenPoolCounterPart(chains[src], srcPool, srcActor, dst, dstToken.Address(), dstPool.Address()); err != nil { return nil, nil, nil, nil, err } - if err := setTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { + if err := setTokenPoolCounterPart(chains[dst], dstPool, dstActor, src, srcToken.Address(), srcPool.Address()); err != nil { return nil, nil, nil, nil, err } // Add burn/mint permissions - if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcPool.Address()); err != nil { + if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcActor, srcPool.Address()); err != nil { return nil, nil, nil, nil, err } - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstPool.Address()); err != nil { + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstActor, dstPool.Address()); err != nil { return nil, nil, nil, nil, err } return srcToken, srcPool, dstToken, dstPool, nil } -func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, address common.Address) error { +func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, actor *bind.TransactOpts, address common.Address) error { lggr.Infow("Granting burn permissions", "token", token.Address(), "burner", address) - tx, err := token.GrantBurnRole(chain.DeployerKey, address) + tx, err := token.GrantBurnRole(actor, address) if err != nil { return err } @@ -753,7 +754,7 @@ func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token } lggr.Infow("Granting mint permissions", "token", token.Address(), "minter", address) - tx, err = token.GrantMintRole(chain.DeployerKey, address) + tx, err = token.GrantMintRole(actor, address) if err != nil { return err } @@ -797,18 +798,12 @@ func setUSDCTokenPoolCounterPart( return err } - return setTokenPoolCounterPart(chain, pool, destChainSelector, destTokenAddress, destTokenPoolAddress) + return setTokenPoolCounterPart(chain, pool, nil, destChainSelector, destTokenAddress, destTokenPoolAddress) } -func setTokenPoolCounterPart( - chain deployment.Chain, - tokenPool *burn_mint_token_pool.BurnMintTokenPool, - destChainSelector uint64, - destTokenAddress common.Address, - destTokenPoolAddress common.Address, -) error { +func setTokenPoolCounterPart(chain deployment.Chain, tokenPool *burn_mint_token_pool.BurnMintTokenPool, actor *bind.TransactOpts, destChainSelector uint64, destTokenAddress common.Address, destTokenPoolAddress common.Address) error { tx, err := tokenPool.ApplyChainUpdates( - chain.DeployerKey, + actor, []burn_mint_token_pool.TokenPoolChainUpdate{ { RemoteChainSelector: destChainSelector, @@ -838,7 +833,7 @@ func setTokenPoolCounterPart( } tx, err = tokenPool.SetRemotePool( - chain.DeployerKey, + actor, destChainSelector, destTokenPoolAddress.Bytes(), ) @@ -898,6 +893,7 @@ func attachTokenToTheRegistry( func deployTransferTokenOneEnd( lggr logger.Logger, chain deployment.Chain, + deployer *bind.TransactOpts, addressBook deployment.AddressBook, tokenSymbol string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { @@ -921,7 +917,7 @@ func deployTransferTokenOneEnd( tokenContract, err := deployment.DeployContract(lggr, chain, addressBook, func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { USDCTokenAddr, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, + deployer, chain.Client, tokenSymbol, tokenSymbol, @@ -937,7 +933,7 @@ func deployTransferTokenOneEnd( return nil, nil, err } - tx, err := tokenContract.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) + tx, err := tokenContract.Contract.GrantMintRole(deployer, deployer.From) if err != nil { return nil, nil, err } @@ -949,7 +945,7 @@ func deployTransferTokenOneEnd( tokenPool, err := deployment.DeployContract(lggr, chain, addressBook, func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { tokenPoolAddress, tx, tokenPoolContract, err2 := burn_mint_token_pool.DeployBurnMintTokenPool( - chain.DeployerKey, + deployer, chain.Client, tokenContract.Address, []common.Address{}, diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/changeset/test_usdc_helpers.go index 4a39f4e7ba1..ffdd2949b56 100644 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ b/deployment/ccip/changeset/test_usdc_helpers.go @@ -55,7 +55,7 @@ func ConfigureUSDCTokenPools( state.Chains[src].MockUSDCTokenMessenger.Address(), state.Chains[src].MockUSDCTransmitter.Address(), } { - if err := grantMintBurnPermissions(lggr, chains[src], srcToken, addr); err != nil { + if err := grantMintBurnPermissions(lggr, chains[src], srcToken, nil, addr); err != nil { lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "minter", addr) return nil, nil, err } @@ -67,7 +67,7 @@ func ConfigureUSDCTokenPools( state.Chains[dst].MockUSDCTokenMessenger.Address(), state.Chains[dst].MockUSDCTransmitter.Address(), } { - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, addr); err != nil { + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, nil, addr); err != nil { lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", dstToken.Address(), "minter", addr) return nil, nil, err } diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index 2d8e573b8fd..5eb5803d693 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,6 +1,11 @@ package smoke import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" "math/big" "testing" @@ -82,12 +87,10 @@ func TestInitialDeployOnLocal(t *testing.T) { func TestTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) config := &changeset.TestConfigs{} - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + //tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - /* - * use this if you are testing locally in memory - * tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) - */ + //* use this if you are testing locally in memory + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -97,11 +100,16 @@ func TestTokenTransfer(t *testing.T) { sourceChain := allChainSelectors[0] destChain := allChainSelectors[1] + sourceActor := createAndFundSelfServeActor(t, e.Chains[sourceChain].DeployerKey, e.Chains[sourceChain]) + destActor := createAndFundSelfServeActor(t, e.Chains[destChain].DeployerKey, e.Chains[destChain]) + srcToken1, _, destToken1, _, err := changeset.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, destChain, + sourceActor, + destActor, state, e.ExistingAddresses, "MY_TOKEN_1", @@ -113,6 +121,8 @@ func TestTokenTransfer(t *testing.T) { tenv.Env.Chains, sourceChain, destChain, + sourceActor, + destActor, state, e.ExistingAddresses, "MY_TOKEN_2", @@ -122,10 +132,18 @@ func TestTokenTransfer(t *testing.T) { // Add all lanes. require.NoError(t, changeset.AddLanesForAll(e, state)) - mintAndAllow(t, e, state, map[uint64][]*burn_mint_erc677.BurnMintERC677{ - sourceChain: {srcToken1, srcToken2}, - destChain: {destToken1, destToken2}, - }) + mintAndAllow( + t, + e, + state, + map[uint64]*bind.TransactOpts{ + sourceChain: sourceActor, + destChain: destActor, + }, + map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {srcToken1, srcToken2}, + destChain: {destToken1, destToken2}, + }) tinyOneCoin := new(big.Int).SetUint64(1) @@ -250,3 +268,40 @@ func TestTokenTransfer(t *testing.T) { }) } } + +func createAndFundSelfServeActor( + t *testing.T, + deployer *bind.TransactOpts, + chain deployment.Chain, +) *bind.TransactOpts { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + actor, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + + nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) + require.NoError(t, err) + + gasPrice, err := chain.Client.SuggestGasPrice(tests.Context(t)) + require.NoError(t, err) + + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: &actor.From, + Value: new(big.Int).SetUint64(1e18), + Gas: uint64(21000), + GasPrice: gasPrice, + Data: nil, + }) + + signedTx, err := deployer.Signer(deployer.From, tx) + require.NoError(t, err) + + err = chain.Client.SendTransaction(tests.Context(t), signedTx) + require.NoError(t, err) + + _, err = chain.Confirm(signedTx) + require.NoError(t, err) + + return actor +} diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index f2c2a45df86..e81c0e82812 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -60,6 +60,8 @@ func TestUSDCTokenTransfer(t *testing.T) { tenv.Env.Chains, chainA, chainC, + nil, + nil, state, e.ExistingAddresses, "MY_TOKEN", @@ -69,7 +71,7 @@ func TestUSDCTokenTransfer(t *testing.T) { // Add all lanes require.NoError(t, changeset.AddLanesForAll(e, state)) - mintAndAllow(t, e, state, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + mintAndAllow(t, e, state, nil, map[uint64][]*burn_mint_erc677.BurnMintERC677{ chainA: {aChainUSDC, aChainToken}, chainB: {bChainUSDC}, chainC: {cChainUSDC, cChainToken}, @@ -252,14 +254,18 @@ func mintAndAllow( t *testing.T, e deployment.Environment, state changeset.CCIPOnChainState, + owners map[uint64]*bind.TransactOpts, tkMap map[uint64][]*burn_mint_erc677.BurnMintERC677, ) { for chain, tokens := range tkMap { for _, token := range tokens { twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) + owner, ok := owners[chain] + require.True(t, ok) + tx, err := token.Mint( - e.Chains[chain].DeployerKey, + owner, e.Chains[chain].DeployerKey.From, new(big.Int).Mul(twoCoins, big.NewInt(10)), ) From 8f4d4c574027a70625e7029157c8ccbe4e555556 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Wed, 27 Nov 2024 21:45:16 +0530 Subject: [PATCH 10/22] feat: self serve pool test + ability to add custom deployer for token and pools --- deployment/ccip/changeset/test_helpers.go | 125 ++++++++++++- .../ccip/changeset/test_usdc_helpers.go | 8 +- integration-tests/smoke/ccip/ccip_test.go | 133 +++++++------- .../smoke/ccip/ccip_usdc_test.go | 167 +++--------------- 4 files changed, 224 insertions(+), 209 deletions(-) diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index 7806ab3c052..b1ac2c37d3e 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -3,6 +3,7 @@ package changeset import ( "context" "fmt" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "math/big" "net/http" "net/http/httptest" @@ -776,6 +777,7 @@ func setUSDCTokenPoolCounterPart( chain deployment.Chain, tokenPool *usdc_token_pool.USDCTokenPool, destChainSelector uint64, + actor *bind.TransactOpts, destTokenAddress common.Address, destTokenPoolAddress common.Address, ) error { @@ -808,7 +810,7 @@ func setUSDCTokenPoolCounterPart( return err } - return setTokenPoolCounterPart(chain, pool, nil, destChainSelector, destTokenAddress, destTokenPoolAddress) + return setTokenPoolCounterPart(chain, pool, actor, destChainSelector, destTokenAddress, destTokenPoolAddress) } func setTokenPoolCounterPart(chain deployment.Chain, tokenPool *burn_mint_token_pool.BurnMintTokenPool, actor *bind.TransactOpts, destChainSelector uint64, destTokenAddress common.Address, destTokenPoolAddress common.Address) error { @@ -976,3 +978,124 @@ func deployTransferTokenOneEnd( return tokenContract.Contract, tokenPool.Contract, nil } + +// MintAndAllow mints tokens for deployers and allow router to spend them +func MintAndAllow( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + owners map[uint64]*bind.TransactOpts, + tkMap map[uint64][]*burn_mint_erc677.BurnMintERC677, +) { + for chain, tokens := range tkMap { + for _, token := range tokens { + twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) + + owner, ok := owners[chain] + require.True(t, ok) + + tx, err := token.Mint( + owner, + e.Chains[chain].DeployerKey.From, + new(big.Int).Mul(twoCoins, big.NewInt(10)), + ) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + + tx, err = token.Approve(e.Chains[chain].DeployerKey, state.Chains[chain].Router.Address(), twoCoins) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + } + } +} + +// TransferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed +func TransferAndWaitForSuccess( + t *testing.T, + env deployment.Environment, + state CCIPOnChainState, + sourceChain, destChain uint64, + tokens []router.ClientEVMTokenAmount, + receiver common.Address, + data []byte, + expectedStatus int, +) { + identifier := SourceDestPair{ + SourceChainSelector: sourceChain, + DestChainSelector: destChain, + } + + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[SourceDestPair]uint64) + expectedSeqNumExec := make(map[SourceDestPair][]uint64) + + latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[destChain] = &block + + msgSentEvent := TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(receiver.Bytes(), 32), + Data: data, + TokenAmounts: tokens, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[identifier] = msgSentEvent.SequenceNumber + expectedSeqNumExec[identifier] = []uint64{msgSentEvent.SequenceNumber} + + // Wait for all commit reports to land. + ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) + + // Wait for all exec reports to land + states := ConfirmExecWithSeqNrsForAll(t, env, state, expectedSeqNumExec, startBlocks) + require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) +} + +func WaitForTheTokenBalance( + t *testing.T, + token common.Address, + receiver common.Address, + chain deployment.Chain, + expected *big.Int, +) { + tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) + require.NoError(t, err) + + require.Eventually(t, func() bool { + actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) + require.NoError(t, err) + + t.Log("Waiting for the token balance", + "expected", expected, + "actual", actualBalance, + "token", token, + "receiver", receiver, + ) + + return actualBalance.Cmp(expected) == 0 + }, tests.WaitTimeout(t), 100*time.Millisecond) +} + +func GetTokenBalance( + t *testing.T, + token common.Address, + receiver common.Address, + chain deployment.Chain, +) *big.Int { + tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) + require.NoError(t, err) + + balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) + require.NoError(t, err) + + t.Log("Getting token balance", + "actual", balance, + "token", token, + "receiver", receiver, + ) + + return balance +} diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/changeset/test_usdc_helpers.go index ffdd2949b56..ae03f859d13 100644 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ b/deployment/ccip/changeset/test_usdc_helpers.go @@ -39,12 +39,12 @@ func ConfigureUSDCTokenPools( } // Connect pool to each other - if err := setUSDCTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { + if err := setUSDCTokenPoolCounterPart(chains[src], srcPool, dst, chains[src].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) return nil, nil, err } - if err := setUSDCTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { + if err := setUSDCTokenPoolCounterPart(chains[dst], dstPool, src, chains[dst].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { lggr.Errorw("Failed to set counter part", "err", err, "srcPool", dstPool.Address(), "dstPool", srcPool.Address()) return nil, nil, err } @@ -55,7 +55,7 @@ func ConfigureUSDCTokenPools( state.Chains[src].MockUSDCTokenMessenger.Address(), state.Chains[src].MockUSDCTransmitter.Address(), } { - if err := grantMintBurnPermissions(lggr, chains[src], srcToken, nil, addr); err != nil { + if err := grantMintBurnPermissions(lggr, chains[src], srcToken, chains[src].DeployerKey, addr); err != nil { lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "minter", addr) return nil, nil, err } @@ -67,7 +67,7 @@ func ConfigureUSDCTokenPools( state.Chains[dst].MockUSDCTokenMessenger.Address(), state.Chains[dst].MockUSDCTransmitter.Address(), } { - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, nil, addr); err != nil { + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, chains[dst].DeployerKey, addr); err != nil { lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", dstToken.Address(), "minter", addr) return nil, nil, err } diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index be78a954f45..acba4b59154 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -89,61 +89,69 @@ func TestTokenTransfer(t *testing.T) { config := &changeset.TestConfigs{} //tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - //* use this if you are testing locally in memory + // use this if you are testing locally in memory tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) require.NoError(t, err) + // Chain and account setup allChainSelectors := maps.Keys(e.Chains) - sourceChain := allChainSelectors[0] - destChain := allChainSelectors[1] + sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] + ownerSourceChain := e.Chains[sourceChain].DeployerKey + ownerDestChain := e.Chains[destChain].DeployerKey - sourceActor := createAndFundSelfServeActor(t, e.Chains[sourceChain].DeployerKey, e.Chains[sourceChain]) - destActor := createAndFundSelfServeActor(t, e.Chains[destChain].DeployerKey, e.Chains[destChain]) + // Deploy and fund self-serve actors + selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) + selfServeDestTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) - srcToken1, _, destToken1, _, err := changeset.DeployTransferableToken( + // Deploy tokens and pool by CCIP Owner + srcToken, _, destToken, _, err := changeset.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, destChain, - sourceActor, - destActor, + ownerSourceChain, + ownerDestChain, state, e.ExistingAddresses, - "MY_TOKEN_1", + "OWNER_TOKEN", ) require.NoError(t, err) - srcToken2, _, destToken2, _, err := changeset.DeployTransferableToken( + // Deploy Self Serve tokens and pool + selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( lggr, tenv.Env.Chains, sourceChain, destChain, - sourceActor, - destActor, + selfServeSrcTokenPoolDeployer, + selfServeDestTokenPoolDeployer, state, e.ExistingAddresses, - "MY_TOKEN_2", + "SELF_SERVE_TOKEN", ) require.NoError(t, err) // Add all lanes. require.NoError(t, changeset.AddLanesForAll(e, state)) - mintAndAllow( - t, - e, - state, - map[uint64]*bind.TransactOpts{ - sourceChain: sourceActor, - destChain: destActor, - }, - map[uint64][]*burn_mint_erc677.BurnMintERC677{ - sourceChain: {srcToken1, srcToken2}, - destChain: {destToken1, destToken2}, - }) + // Mint and allow tokens for the router + changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ + sourceChain: ownerSourceChain, + destChain: ownerDestChain, + }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {srcToken}, + destChain: {destToken}, + }) + changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ + sourceChain: selfServeSrcTokenPoolDeployer, + destChain: selfServeDestTokenPoolDeployer, + }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {selfServeSrcToken}, + destChain: {selfServeDestToken}, + }) tinyOneCoin := new(big.Int).SetUint64(1) @@ -164,13 +172,13 @@ func TestTokenTransfer(t *testing.T) { dstChain: destChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: srcToken1.Address(), + Token: srcToken.Address(), Amount: tinyOneCoin, }, }, receiver: utils.RandomAddress(), expectedTokenBalances: map[common.Address]*big.Int{ - destToken1.Address(): tinyOneCoin, + destToken.Address(): tinyOneCoin, }, expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, @@ -180,13 +188,13 @@ func TestTokenTransfer(t *testing.T) { dstChain: destChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: srcToken1.Address(), + Token: srcToken.Address(), Amount: tinyOneCoin, }, }, receiver: state.Chains[destChain].Receiver.Address(), expectedTokenBalances: map[common.Address]*big.Int{ - destToken1.Address(): tinyOneCoin, + destToken.Address(): tinyOneCoin, }, expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, @@ -196,18 +204,18 @@ func TestTokenTransfer(t *testing.T) { dstChain: sourceChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: destToken1.Address(), + Token: destToken.Address(), Amount: tinyOneCoin, }, { - Token: destToken2.Address(), + Token: selfServeDestToken.Address(), Amount: tinyOneCoin, }, }, receiver: e.Chains[sourceChain].DeployerKey.From, expectedTokenBalances: map[common.Address]*big.Int{ - srcToken1.Address(): tinyOneCoin, - srcToken2.Address(): tinyOneCoin, + srcToken.Address(): tinyOneCoin, + selfServeSrcToken.Address(): tinyOneCoin, }, expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, @@ -217,22 +225,22 @@ func TestTokenTransfer(t *testing.T) { dstChain: sourceChain, tokenAmounts: []router.ClientEVMTokenAmount{ { - Token: destToken1.Address(), + Token: selfServeDestToken.Address(), Amount: tinyOneCoin, }, { - Token: destToken2.Address(), + Token: destToken.Address(), Amount: tinyOneCoin, }, { - Token: destToken1.Address(), + Token: selfServeDestToken.Address(), Amount: tinyOneCoin, }, }, receiver: state.Chains[sourceChain].Receiver.Address(), expectedTokenBalances: map[common.Address]*big.Int{ - srcToken1.Address(): new(big.Int).SetUint64(2), - srcToken2.Address(): tinyOneCoin, + selfServeSrcToken.Address(): new(big.Int).SetUint64(2), + srcToken.Address(): tinyOneCoin, }, expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, }, @@ -241,30 +249,28 @@ func TestTokenTransfer(t *testing.T) { for _, scenario := range scenarios { scenario := scenario t.Run(scenario.name, func(t *testing.T) { - t.Run(scenario.name, func(t *testing.T) { - initialBalances := map[common.Address]*big.Int{} - for token := range scenario.expectedTokenBalances { - initialBalance := getTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain]) - initialBalances[token] = initialBalance - } - - transferAndWaitForSuccess( - t, - e, - state, - scenario.srcChain, - scenario.dstChain, - scenario.tokenAmounts, - scenario.receiver, - scenario.data, - scenario.expectedExecutionState, - ) - - for token, balance := range scenario.expectedTokenBalances { - expected := new(big.Int).Add(initialBalances[token], balance) - waitForTheTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain], expected) - } - }) + initialBalances := map[common.Address]*big.Int{} + for token := range scenario.expectedTokenBalances { + initialBalance := changeset.GetTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain]) + initialBalances[token] = initialBalance + } + + changeset.TransferAndWaitForSuccess( + t, + e, + state, + scenario.srcChain, + scenario.dstChain, + scenario.tokenAmounts, + scenario.receiver, + scenario.data, + scenario.expectedExecutionState, + ) + + for token, balance := range scenario.expectedTokenBalances { + expected := new(big.Int).Add(initialBalances[token], balance) + changeset.WaitForTheTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain], expected) + } }) } } @@ -273,6 +279,7 @@ func createAndFundSelfServeActor( t *testing.T, deployer *bind.TransactOpts, chain deployment.Chain, + amountToFund *big.Int, ) *bind.TransactOpts { key, err := crypto.GenerateKey() require.NoError(t, err) @@ -288,7 +295,7 @@ func createAndFundSelfServeActor( tx := types.NewTx(&types.LegacyTx{ Nonce: nonce, To: &actor.From, - Value: new(big.Int).SetUint64(1e18), + Value: amountToFund, Gas: uint64(21000), GasPrice: gasPrice, Data: nil, diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index 658637b83ff..1c833acd49a 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -1,22 +1,17 @@ package smoke import ( - "math/big" - "testing" - "time" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + "math/big" + "testing" "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -37,8 +32,8 @@ func TestUSDCTokenTransfer(t *testing.T) { config := &changeset.TestConfigs{ IsUSDC: true, } - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) + //tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -49,6 +44,10 @@ func TestUSDCTokenTransfer(t *testing.T) { chainC := allChainSelectors[1] chainB := allChainSelectors[2] + ownerChainA := e.Chains[chainA].DeployerKey + ownerChainC := e.Chains[chainC].DeployerKey + ownerChainB := e.Chains[chainB].DeployerKey + aChainUSDC, cChainUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainA, chainC, state) require.NoError(t, err) @@ -60,8 +59,8 @@ func TestUSDCTokenTransfer(t *testing.T) { tenv.Env.Chains, chainA, chainC, - nil, - nil, + ownerChainA, + ownerChainC, state, e.ExistingAddresses, "MY_TOKEN", @@ -71,11 +70,18 @@ func TestUSDCTokenTransfer(t *testing.T) { // Add all lanes require.NoError(t, changeset.AddLanesForAll(e, state)) - mintAndAllow(t, e, state, nil, map[uint64][]*burn_mint_erc677.BurnMintERC677{ - chainA: {aChainUSDC, aChainToken}, - chainB: {bChainUSDC}, - chainC: {cChainUSDC, cChainToken}, - }) + changeset.MintAndAllow( + t, + e, + state, + map[uint64]*bind.TransactOpts{ + chainA: ownerChainA, + chainB: ownerChainB, + chainC: ownerChainC}, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + chainA: {aChainUSDC, aChainToken}, + chainB: {bChainUSDC}, + chainC: {cChainUSDC, cChainToken}, + }) err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) require.NoError(t, err) @@ -179,11 +185,11 @@ func TestUSDCTokenTransfer(t *testing.T) { t.Run(tt.name, func(t *testing.T) { initialBalances := map[common.Address]*big.Int{} for token := range tt.expectedTokenBalances { - initialBalance := getTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain]) + initialBalance := changeset.GetTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain]) initialBalances[token] = initialBalance } - transferAndWaitForSuccess( + changeset.TransferAndWaitForSuccess( t, e, state, @@ -197,7 +203,7 @@ func TestUSDCTokenTransfer(t *testing.T) { for token, balance := range tt.expectedTokenBalances { expected := new(big.Int).Add(initialBalances[token], balance) - waitForTheTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain], expected) + changeset.WaitForTheTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain], expected) } }) } @@ -245,127 +251,6 @@ func TestUSDCTokenTransfer(t *testing.T) { // We sent 1 coin from each source chain, so we should have 2 coins on the destination chain // Receiver is randomly generated so we don't need to get the initial balance first expectedBalance := new(big.Int).Add(tinyOneCoin, tinyOneCoin) - waitForTheTokenBalance(t, cChainUSDC.Address(), receiver, e.Chains[chainC], expectedBalance) - }) -} - -// mintAndAllow mints tokens for deployers and allow router to spend them -func mintAndAllow( - t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, - owners map[uint64]*bind.TransactOpts, - tkMap map[uint64][]*burn_mint_erc677.BurnMintERC677, -) { - for chain, tokens := range tkMap { - for _, token := range tokens { - twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) - - owner, ok := owners[chain] - require.True(t, ok) - - tx, err := token.Mint( - owner, - e.Chains[chain].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) - - tx, err = token.Approve(e.Chains[chain].DeployerKey, state.Chains[chain].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) - } - } -} - -// transferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed -func transferAndWaitForSuccess( - t *testing.T, - env deployment.Environment, - state changeset.CCIPOnChainState, - sourceChain, destChain uint64, - tokens []router.ClientEVMTokenAmount, - receiver common.Address, - data []byte, - expectedStatus int, -) { - identifier := changeset.SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - } - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[destChain] = &block - - msgSentEvent := changeset.TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiver.Bytes(), 32), - Data: data, - TokenAmounts: tokens, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, + changeset.WaitForTheTokenBalance(t, cChainUSDC.Address(), receiver, e.Chains[chainC], expectedBalance) }) - expectedSeqNum[identifier] = msgSentEvent.SequenceNumber - expectedSeqNumExec[identifier] = []uint64{msgSentEvent.SequenceNumber} - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) - - // Wait for all exec reports to land - states := changeset.ConfirmExecWithSeqNrsForAll(t, env, state, expectedSeqNumExec, startBlocks) - require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) -} - -func waitForTheTokenBalance( - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, - expected *big.Int, -) { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - require.Eventually(t, func() bool { - actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) - require.NoError(t, err) - - t.Log("Waiting for the token balance", - "expected", expected, - "actual", actualBalance, - "token", token, - "receiver", receiver, - ) - - return actualBalance.Cmp(expected) == 0 - }, tests.WaitTimeout(t), 100*time.Millisecond) -} - -func getTokenBalance( - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, -) *big.Int { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) - require.NoError(t, err) - - t.Log("Getting token balance", - "actual", balance, - "token", token, - "receiver", receiver, - ) - - return balance } From 36df2f62abb8f0fab5b9ed278a00bb968b5c3db2 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Wed, 27 Nov 2024 22:42:29 +0530 Subject: [PATCH 11/22] fix : Use LocalDevEnvironment --- integration-tests/smoke/ccip/ccip_test.go | 7 ++++--- integration-tests/smoke/ccip/ccip_usdc_test.go | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index acba4b59154..dbfd82c4087 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -27,7 +27,8 @@ import ( func TestInitialDeployOnLocal(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, nil) + config := &changeset.TestConfigs{} + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) require.NoError(t, err) @@ -87,10 +88,10 @@ func TestInitialDeployOnLocal(t *testing.T) { func TestTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) config := &changeset.TestConfigs{} - //tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) // use this if you are testing locally in memory - tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) + // tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index 1c833acd49a..ee27ad0c601 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -3,6 +3,7 @@ package smoke import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/stretchr/testify/require" "math/big" "testing" @@ -32,8 +33,8 @@ func TestUSDCTokenTransfer(t *testing.T) { config := &changeset.TestConfigs{ IsUSDC: true, } - //tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) From faca5a5166a937b5905aa5b4d8cc10ad64852a42 Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 28 Nov 2024 01:18:15 +0530 Subject: [PATCH 12/22] temp: trying out with AdditionalSimulatedPvtKeys --- integration-tests/smoke/ccip/ccip_test.go | 30 ++++++++++++++++++--- integration-tests/testconfig/ccip/ccip.toml | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index dbfd82c4087..be22adb0ab6 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -4,7 +4,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/deployment" "math/big" "testing" @@ -103,9 +105,11 @@ func TestTokenTransfer(t *testing.T) { ownerSourceChain := e.Chains[sourceChain].DeployerKey ownerDestChain := e.Chains[destChain].DeployerKey - // Deploy and fund self-serve actors - selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) - selfServeDestTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) + // Deploy and fund self-serve actors (when using memory) + //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) + //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) + selfServeSrcTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, sourceChain) + selfServeDestTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, destChain) // Deploy tokens and pool by CCIP Owner srcToken, _, destToken, _, err := changeset.DeployTransferableToken( @@ -285,7 +289,7 @@ func createAndFundSelfServeActor( key, err := crypto.GenerateKey() require.NoError(t, err) - actor, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + actor, err := bind.NewKeyedTransactorWithChainID(key, getChainIdFromSelector(t, chain.Selector)) nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) require.NoError(t, err) @@ -313,3 +317,21 @@ func createAndFundSelfServeActor( return actor } + +func getChainIdFromSelector(t *testing.T, selector uint64) *big.Int { + chainId, err := chain_selectors.GetChainIDFromSelector(selector) + require.NoError(t, err) + //convert chainId from string to big.Int + chainIdBigInt := new(big.Int) + chainIdBigInt.SetString(chainId, 10) + return chainIdBigInt +} + +func createDeployerKeyFromSimulatedPrivateKey(t *testing.T, selector uint64) *bind.TransactOpts { + key, err := crypto.HexToECDSA(networks.AdditionalSimulatedPvtKeys[0]) + require.NoError(t, err) + chainId := getChainIdFromSelector(t, selector) + id, err := bind.NewKeyedTransactorWithChainID(key, chainId) + require.NoError(t, err) + return id +} diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml index 85e645ed0b9..577d4404d0a 100644 --- a/integration-tests/testconfig/ccip/ccip.toml +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -11,6 +11,7 @@ evm_chain_id = 1337 evm_keys = [ "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' @@ -28,6 +29,7 @@ evm_chain_id = 2337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' @@ -45,6 +47,7 @@ evm_chain_id = 3337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' From c53e8723af7837dbbcb34c592106f0aaddd9458e Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 28 Nov 2024 15:19:47 +0530 Subject: [PATCH 13/22] fix: lints and unused function --- integration-tests/smoke/ccip/ccip_test.go | 23 ++++++++++--------- .../smoke/ccip/ccip_usdc_test.go | 9 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index be22adb0ab6..b4034c553f9 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,23 +1,21 @@ package smoke import ( - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" - "github.com/smartcontractkit/chainlink/deployment" "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" + chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -280,7 +278,9 @@ func TestTokenTransfer(t *testing.T) { } } -func createAndFundSelfServeActor( +// _createAndFundSelfServeActor is currently unused but retained for potential local testing. +// nolint:unused +func _createAndFundSelfServeActor( t *testing.T, deployer *bind.TransactOpts, chain deployment.Chain, @@ -290,6 +290,7 @@ func createAndFundSelfServeActor( require.NoError(t, err) actor, err := bind.NewKeyedTransactorWithChainID(key, getChainIdFromSelector(t, chain.Selector)) + require.NoError(t, err) nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) require.NoError(t, err) @@ -319,7 +320,7 @@ func createAndFundSelfServeActor( } func getChainIdFromSelector(t *testing.T, selector uint64) *big.Int { - chainId, err := chain_selectors.GetChainIDFromSelector(selector) + chainId, err := chainselectors.GetChainIDFromSelector(selector) require.NoError(t, err) //convert chainId from string to big.Int chainIdBigInt := new(big.Int) diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index ee27ad0c601..cf0b1994106 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -1,18 +1,17 @@ package smoke import ( - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/stretchr/testify/require" "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" From 9037d575bb2cd77661e6237279c881d3f654d74e Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 28 Nov 2024 15:26:05 +0530 Subject: [PATCH 14/22] fix: lints and unused function --- deployment/ccip/changeset/test_helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index 6bb907ba9bf..0fecf157aad 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -3,7 +3,6 @@ package changeset import ( "context" "fmt" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "math/big" "net/http" "net/http/httptest" @@ -41,6 +40,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" From f82919942acaf0251392bc1aa6958d302b71ca9d Mon Sep 17 00:00:00 2001 From: 0xsuryansh Date: Thu, 28 Nov 2024 15:36:20 +0530 Subject: [PATCH 15/22] fix: imports for lint --- integration-tests/smoke/ccip/ccip_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index b4034c553f9..a732877527b 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -12,6 +12,7 @@ import ( "golang.org/x/exp/maps" chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" From eee7c9360e53dee0be76dd5399f93f02a480f79f Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 13:32:29 +0100 Subject: [PATCH 16/22] Move tt tests to a separate file --- .github/e2e-tests.yml | 19 +- integration-tests/smoke/ccip/ccip_test.go | 267 +---------------- .../smoke/ccip/ccip_token_transfer_test.go | 276 ++++++++++++++++++ 3 files changed, 293 insertions(+), 269 deletions(-) create mode 100644 integration-tests/smoke/ccip/ccip_token_transfer_test.go diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 9f6495c46f7..1b837b76457 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -935,6 +935,19 @@ runner-test-matrix: # START: CCIPv1.6 tests + - id: smoke/ccip/ccip_test.go:* + path: integration-tests/smoke/ccip/ccip_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_test.go -timeout 12m -test.parallel=2 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.6.0 + - id: smoke/ccip/ccip_test.go:* path: integration-tests/smoke/ccip/ccip_test.go test_env_type: docker @@ -948,14 +961,14 @@ runner-test-matrix: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_batching_test.go:* - path: integration-tests/smoke/ccip/ccip_batching_test.go + - id: smoke/ccip/ccip_token_transfer_test.go:* + path: integration-tests/smoke/ccip/ccip_token_transfer_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_batching_test.go -timeout 12m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index a732877527b..ec7a0e75c08 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,28 +1,15 @@ package smoke import ( - "math/big" "testing" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - chainselectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/stretchr/testify/require" ) func TestInitialDeployOnLocal(t *testing.T) { @@ -85,255 +72,3 @@ func TestInitialDeployOnLocal(t *testing.T) { // TODO: Apply the proposal. } - -func TestTokenTransfer(t *testing.T) { - lggr := logger.TestLogger(t) - config := &changeset.TestConfigs{} - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - - // use this if you are testing locally in memory - // tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) - - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - // Chain and account setup - allChainSelectors := maps.Keys(e.Chains) - sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] - ownerSourceChain := e.Chains[sourceChain].DeployerKey - ownerDestChain := e.Chains[destChain].DeployerKey - - // Deploy and fund self-serve actors (when using memory) - //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) - //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) - selfServeSrcTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, sourceChain) - selfServeDestTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, destChain) - - // Deploy tokens and pool by CCIP Owner - srcToken, _, destToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - sourceChain, - destChain, - ownerSourceChain, - ownerDestChain, - state, - e.ExistingAddresses, - "OWNER_TOKEN", - ) - require.NoError(t, err) - - // Deploy Self Serve tokens and pool - selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - sourceChain, - destChain, - selfServeSrcTokenPoolDeployer, - selfServeDestTokenPoolDeployer, - state, - e.ExistingAddresses, - "SELF_SERVE_TOKEN", - ) - require.NoError(t, err) - - // Add all lanes. - require.NoError(t, changeset.AddLanesForAll(e, state)) - - // Mint and allow tokens for the router - changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ - sourceChain: ownerSourceChain, - destChain: ownerDestChain, - }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ - sourceChain: {srcToken}, - destChain: {destToken}, - }) - changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ - sourceChain: selfServeSrcTokenPoolDeployer, - destChain: selfServeDestTokenPoolDeployer, - }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ - sourceChain: {selfServeSrcToken}, - destChain: {selfServeDestToken}, - }) - - tinyOneCoin := new(big.Int).SetUint64(1) - - // Test scenarios are defined here - scenarios := []struct { - name string - srcChain uint64 - dstChain uint64 - tokenAmounts []router.ClientEVMTokenAmount - receiver common.Address - data []byte - expectedTokenBalances map[common.Address]*big.Int - expectedExecutionState int - }{ - { - name: "Send token to EOA", - srcChain: sourceChain, - dstChain: destChain, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: tinyOneCoin, - }, - }, - receiver: utils.RandomAddress(), - expectedTokenBalances: map[common.Address]*big.Int{ - destToken.Address(): tinyOneCoin, - }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, - }, - { - name: "Send token to contract", - srcChain: sourceChain, - dstChain: destChain, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: tinyOneCoin, - }, - }, - receiver: state.Chains[destChain].Receiver.Address(), - expectedTokenBalances: map[common.Address]*big.Int{ - destToken.Address(): tinyOneCoin, - }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, - }, - { - name: "Send 2 tokens to receiver", - srcChain: destChain, - dstChain: sourceChain, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: destToken.Address(), - Amount: tinyOneCoin, - }, - { - Token: selfServeDestToken.Address(), - Amount: tinyOneCoin, - }, - }, - receiver: e.Chains[sourceChain].DeployerKey.From, - expectedTokenBalances: map[common.Address]*big.Int{ - srcToken.Address(): tinyOneCoin, - selfServeSrcToken.Address(): tinyOneCoin, - }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, - }, - { - name: "Send N tokens to contract", - srcChain: destChain, - dstChain: sourceChain, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: selfServeDestToken.Address(), - Amount: tinyOneCoin, - }, - { - Token: destToken.Address(), - Amount: tinyOneCoin, - }, - { - Token: selfServeDestToken.Address(), - Amount: tinyOneCoin, - }, - }, - receiver: state.Chains[sourceChain].Receiver.Address(), - expectedTokenBalances: map[common.Address]*big.Int{ - selfServeSrcToken.Address(): new(big.Int).SetUint64(2), - srcToken.Address(): tinyOneCoin, - }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, - }, - } - - for _, scenario := range scenarios { - scenario := scenario - t.Run(scenario.name, func(t *testing.T) { - initialBalances := map[common.Address]*big.Int{} - for token := range scenario.expectedTokenBalances { - initialBalance := changeset.GetTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain]) - initialBalances[token] = initialBalance - } - - changeset.TransferAndWaitForSuccess( - t, - e, - state, - scenario.srcChain, - scenario.dstChain, - scenario.tokenAmounts, - scenario.receiver, - scenario.data, - scenario.expectedExecutionState, - ) - - for token, balance := range scenario.expectedTokenBalances { - expected := new(big.Int).Add(initialBalances[token], balance) - changeset.WaitForTheTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain], expected) - } - }) - } -} - -// _createAndFundSelfServeActor is currently unused but retained for potential local testing. -// nolint:unused -func _createAndFundSelfServeActor( - t *testing.T, - deployer *bind.TransactOpts, - chain deployment.Chain, - amountToFund *big.Int, -) *bind.TransactOpts { - key, err := crypto.GenerateKey() - require.NoError(t, err) - - actor, err := bind.NewKeyedTransactorWithChainID(key, getChainIdFromSelector(t, chain.Selector)) - require.NoError(t, err) - - nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) - require.NoError(t, err) - - gasPrice, err := chain.Client.SuggestGasPrice(tests.Context(t)) - require.NoError(t, err) - - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &actor.From, - Value: amountToFund, - Gas: uint64(21000), - GasPrice: gasPrice, - Data: nil, - }) - - signedTx, err := deployer.Signer(deployer.From, tx) - require.NoError(t, err) - - err = chain.Client.SendTransaction(tests.Context(t), signedTx) - require.NoError(t, err) - - _, err = chain.Confirm(signedTx) - require.NoError(t, err) - - return actor -} - -func getChainIdFromSelector(t *testing.T, selector uint64) *big.Int { - chainId, err := chainselectors.GetChainIDFromSelector(selector) - require.NoError(t, err) - //convert chainId from string to big.Int - chainIdBigInt := new(big.Int) - chainIdBigInt.SetString(chainId, 10) - return chainIdBigInt -} - -func createDeployerKeyFromSimulatedPrivateKey(t *testing.T, selector uint64) *bind.TransactOpts { - key, err := crypto.HexToECDSA(networks.AdditionalSimulatedPvtKeys[0]) - require.NoError(t, err) - chainId := getChainIdFromSelector(t, selector) - id, err := bind.NewKeyedTransactorWithChainID(key, chainId) - require.NoError(t, err) - return id -} diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go new file mode 100644 index 00000000000..18bbb8aee96 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -0,0 +1,276 @@ +package smoke + +import ( + "math/big" + "testing" + + "golang.org/x/exp/maps" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + + chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestTokenTransfer(t *testing.T) { + lggr := logger.TestLogger(t) + config := &changeset.TestConfigs{} + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + + // use this if you are testing locally in memory + // tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) + + e := tenv.Env + state, err := changeset.LoadOnchainState(e) + require.NoError(t, err) + + // Chain and account setup + allChainSelectors := maps.Keys(e.Chains) + sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] + ownerSourceChain := e.Chains[sourceChain].DeployerKey + ownerDestChain := e.Chains[destChain].DeployerKey + + // Deploy and fund self-serve actors (when using memory) + //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) + //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) + selfServeSrcTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, sourceChain) + selfServeDestTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, destChain) + + // Deploy tokens and pool by CCIP Owner + srcToken, _, destToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + ownerSourceChain, + ownerDestChain, + state, + e.ExistingAddresses, + "OWNER_TOKEN", + ) + require.NoError(t, err) + + // Deploy Self Serve tokens and pool + selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + selfServeSrcTokenPoolDeployer, + selfServeDestTokenPoolDeployer, + state, + e.ExistingAddresses, + "SELF_SERVE_TOKEN", + ) + require.NoError(t, err) + + // Add all lanes. + require.NoError(t, changeset.AddLanesForAll(e, state)) + + // Mint and allow tokens for the router + changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ + sourceChain: ownerSourceChain, + destChain: ownerDestChain, + }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {srcToken}, + destChain: {destToken}, + }) + changeset.MintAndAllow(t, e, state, map[uint64]*bind.TransactOpts{ + sourceChain: selfServeSrcTokenPoolDeployer, + destChain: selfServeDestTokenPoolDeployer, + }, map[uint64][]*burn_mint_erc677.BurnMintERC677{ + sourceChain: {selfServeSrcToken}, + destChain: {selfServeDestToken}, + }) + + tinyOneCoin := new(big.Int).SetUint64(1) + + // Test scenarios are defined here + scenarios := []struct { + name string + srcChain uint64 + dstChain uint64 + tokenAmounts []router.ClientEVMTokenAmount + receiver common.Address + data []byte + expectedTokenBalances map[common.Address]*big.Int + expectedExecutionState int + }{ + { + name: "Send token to EOA", + srcChain: sourceChain, + dstChain: destChain, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: tinyOneCoin, + }, + }, + receiver: utils.RandomAddress(), + expectedTokenBalances: map[common.Address]*big.Int{ + destToken.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + }, + { + name: "Send token to contract", + srcChain: sourceChain, + dstChain: destChain, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: tinyOneCoin, + }, + }, + receiver: state.Chains[destChain].Receiver.Address(), + expectedTokenBalances: map[common.Address]*big.Int{ + destToken.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + }, + { + name: "Send 2 tokens to receiver", + srcChain: destChain, + dstChain: sourceChain, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: destToken.Address(), + Amount: tinyOneCoin, + }, + { + Token: selfServeDestToken.Address(), + Amount: tinyOneCoin, + }, + }, + receiver: e.Chains[sourceChain].DeployerKey.From, + expectedTokenBalances: map[common.Address]*big.Int{ + srcToken.Address(): tinyOneCoin, + selfServeSrcToken.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + }, + { + name: "Send N tokens to contract", + srcChain: destChain, + dstChain: sourceChain, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: selfServeDestToken.Address(), + Amount: tinyOneCoin, + }, + { + Token: destToken.Address(), + Amount: tinyOneCoin, + }, + { + Token: selfServeDestToken.Address(), + Amount: tinyOneCoin, + }, + }, + receiver: state.Chains[sourceChain].Receiver.Address(), + expectedTokenBalances: map[common.Address]*big.Int{ + selfServeSrcToken.Address(): new(big.Int).SetUint64(2), + srcToken.Address(): tinyOneCoin, + }, + expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + initialBalances := map[common.Address]*big.Int{} + for token := range scenario.expectedTokenBalances { + initialBalance := changeset.GetTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain]) + initialBalances[token] = initialBalance + } + + changeset.TransferAndWaitForSuccess( + t, + e, + state, + scenario.srcChain, + scenario.dstChain, + scenario.tokenAmounts, + scenario.receiver, + scenario.data, + scenario.expectedExecutionState, + ) + + for token, balance := range scenario.expectedTokenBalances { + expected := new(big.Int).Add(initialBalances[token], balance) + changeset.WaitForTheTokenBalance(t, token, scenario.receiver, e.Chains[scenario.dstChain], expected) + } + }) + } +} + +// _createAndFundSelfServeActor is currently unused but retained for potential local testing. +// nolint:unused +func _createAndFundSelfServeActor( + t *testing.T, + deployer *bind.TransactOpts, + chain deployment.Chain, + amountToFund *big.Int, +) *bind.TransactOpts { + key, err := crypto.GenerateKey() + require.NoError(t, err) + + actor, err := bind.NewKeyedTransactorWithChainID(key, getChainIdFromSelector(t, chain.Selector)) + require.NoError(t, err) + + nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) + require.NoError(t, err) + + gasPrice, err := chain.Client.SuggestGasPrice(tests.Context(t)) + require.NoError(t, err) + + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: &actor.From, + Value: amountToFund, + Gas: uint64(21000), + GasPrice: gasPrice, + Data: nil, + }) + + signedTx, err := deployer.Signer(deployer.From, tx) + require.NoError(t, err) + + err = chain.Client.SendTransaction(tests.Context(t), signedTx) + require.NoError(t, err) + + _, err = chain.Confirm(signedTx) + require.NoError(t, err) + + return actor +} + +func getChainIdFromSelector(t *testing.T, selector uint64) *big.Int { + chainId, err := chainselectors.GetChainIDFromSelector(selector) + require.NoError(t, err) + //convert chainId from string to big.Int + chainIdBigInt := new(big.Int) + chainIdBigInt.SetString(chainId, 10) + return chainIdBigInt +} + +func createDeployerKeyFromSimulatedPrivateKey(t *testing.T, selector uint64) *bind.TransactOpts { + key, err := crypto.HexToECDSA(networks.AdditionalSimulatedPvtKeys[0]) + require.NoError(t, err) + chainId := getChainIdFromSelector(t, selector) + id, err := bind.NewKeyedTransactorWithChainID(key, chainId) + require.NoError(t, err) + return id +} From 947b68d0ffc0b38fdd3cc5d47d2ded9d664841e2 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 13:41:13 +0100 Subject: [PATCH 17/22] Move tt tests to a separate file --- .github/e2e-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 1b837b76457..e3c9d974d13 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -971,7 +971,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - id: smoke/ccip/ccip_usdc_test.go:* From eedb8fa26df72a3f9ceb4170b01e221a7ed01517 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 13:58:19 +0100 Subject: [PATCH 18/22] Fix --- .../smoke/ccip/ccip_token_transfer_test.go | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 18bbb8aee96..332b74737ce 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -12,9 +12,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" - chainselectors "github.com/smartcontractkit/chain-selectors" + sel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" @@ -28,9 +27,11 @@ func TestTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) config := &changeset.TestConfigs{} tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) + inMemoryEnv := false // use this if you are testing locally in memory // tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) + // inMemoryEnv := true e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -42,11 +43,9 @@ func TestTokenTransfer(t *testing.T) { ownerSourceChain := e.Chains[sourceChain].DeployerKey ownerDestChain := e.Chains[destChain].DeployerKey - // Deploy and fund self-serve actors (when using memory) - //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18)) - //selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18)) - selfServeSrcTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, sourceChain) - selfServeDestTokenPoolDeployer := createDeployerKeyFromSimulatedPrivateKey(t, destChain) + // Deploy and fund self-serve actors + selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(t, ownerSourceChain, e.Chains[sourceChain], big.NewInt(1e18), inMemoryEnv) + selfServeDestTokenPoolDeployer := createAndFundSelfServeActor(t, ownerDestChain, e.Chains[destChain], big.NewInt(1e18), inMemoryEnv) // Deploy tokens and pool by CCIP Owner srcToken, _, destToken, _, err := changeset.DeployTransferableToken( @@ -216,18 +215,26 @@ func TestTokenTransfer(t *testing.T) { } } -// _createAndFundSelfServeActor is currently unused but retained for potential local testing. -// nolint:unused -func _createAndFundSelfServeActor( +func createAndFundSelfServeActor( t *testing.T, deployer *bind.TransactOpts, chain deployment.Chain, amountToFund *big.Int, + isInMemory bool, ) *bind.TransactOpts { key, err := crypto.GenerateKey() require.NoError(t, err) - actor, err := bind.NewKeyedTransactorWithChainID(key, getChainIdFromSelector(t, chain.Selector)) + // Simulated backend sets chainID to 1337 always + chainID := big.NewInt(1337) + if !isInMemory { + // Docker environment runs real geth so chainID has to be set accordingly + stringChainID, err1 := sel.GetChainIDFromSelector(chain.Selector) + require.NoError(t, err1) + chainID, _ = new(big.Int).SetString(stringChainID, 10) + } + + actor, err := bind.NewKeyedTransactorWithChainID(key, chainID) require.NoError(t, err) nonce, err := chain.Client.PendingNonceAt(tests.Context(t), deployer.From) @@ -256,21 +263,3 @@ func _createAndFundSelfServeActor( return actor } - -func getChainIdFromSelector(t *testing.T, selector uint64) *big.Int { - chainId, err := chainselectors.GetChainIDFromSelector(selector) - require.NoError(t, err) - //convert chainId from string to big.Int - chainIdBigInt := new(big.Int) - chainIdBigInt.SetString(chainId, 10) - return chainIdBigInt -} - -func createDeployerKeyFromSimulatedPrivateKey(t *testing.T, selector uint64) *bind.TransactOpts { - key, err := crypto.HexToECDSA(networks.AdditionalSimulatedPvtKeys[0]) - require.NoError(t, err) - chainId := getChainIdFromSelector(t, selector) - id, err := bind.NewKeyedTransactorWithChainID(key, chainId) - require.NoError(t, err) - return id -} From 8308df92eb7b9c51295107c985bf7f22a0902737 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 14:20:45 +0100 Subject: [PATCH 19/22] Fix --- integration-tests/smoke/ccip/ccip_test.go | 4 +++- integration-tests/smoke/ccip/ccip_token_transfer_test.go | 1 + integration-tests/testconfig/ccip/ccip.toml | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index ec7a0e75c08..a77ef4ea839 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -3,13 +3,15 @@ package smoke import ( "testing" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/stretchr/testify/require" ) func TestInitialDeployOnLocal(t *testing.T) { diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 332b74737ce..6b90326a9ae 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" sel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml index 577d4404d0a..85e645ed0b9 100644 --- a/integration-tests/testconfig/ccip/ccip.toml +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -11,7 +11,6 @@ evm_chain_id = 1337 evm_keys = [ "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' @@ -29,7 +28,6 @@ evm_chain_id = 2337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' @@ -47,7 +45,6 @@ evm_chain_id = 3337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ] evm_simulated = true client_implementation = 'Ethereum' From 20a017e9abe78423798458589b6ae7076fcca2d5 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 14:25:34 +0100 Subject: [PATCH 20/22] Fix --- integration-tests/smoke/ccip/ccip_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index a77ef4ea839..fb6fb2cf960 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -3,9 +3,8 @@ package smoke import ( "testing" - "github.com/stretchr/testify/require" - "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" From 97c74df030a8df443a324d50a117855b48e0d772 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 14:48:28 +0100 Subject: [PATCH 21/22] Fix --- .github/e2e-tests.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index e3c9d974d13..37fa8e3d39a 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -935,19 +935,6 @@ runner-test-matrix: # START: CCIPv1.6 tests - - id: smoke/ccip/ccip_test.go:* - path: integration-tests/smoke/ccip/ccip_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_test.go -timeout 12m -test.parallel=2 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_test.go:* path: integration-tests/smoke/ccip/ccip_test.go test_env_type: docker From 7f3fb4fc23aa2e52441323be19f33b2e0340cb69 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 28 Nov 2024 14:51:44 +0100 Subject: [PATCH 22/22] Fix --- .github/e2e-tests.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 37fa8e3d39a..404b1adec3f 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -947,7 +947,20 @@ runner-test-matrix: test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - + + - id: smoke/ccip/ccip_batching_test.go:* + path: integration-tests/smoke/ccip/ccip_batching_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_batching_test.go -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 + E2E_JD_VERSION: 0.6.0 + - id: smoke/ccip/ccip_token_transfer_test.go:* path: integration-tests/smoke/ccip/ccip_token_transfer_test.go test_env_type: docker