Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CCIP-4160 Token Transfer Tests #15278

Open
wants to merge 32 commits into
base: develop
Choose a base branch
from

Conversation

0xsuryansh
Copy link
Member

@0xsuryansh 0xsuryansh commented Nov 18, 2024

CCIP Integration test covering the following scenarios

  1. Send token to EOA
  2. Send token to contract
  3. Send 2 tokens to receiver
  4. Send N tokens to contract

@0xsuryansh 0xsuryansh changed the title CCIP-4160 test refactoring CCIP-4160 Token Transfer Tests Nov 18, 2024
Copy link
Contributor

github-actions bot commented Nov 18, 2024

AER Report: CI Core ran successfully ✅

aer_workflow , commit

AER Report: Operator UI CI ran successfully ✅

aer_workflow , commit

@0xsuryansh 0xsuryansh force-pushed the CCIP-4160_Implement_token_transfer_tests branch from 99c3452 to 3bfac63 Compare November 19, 2024 11:33
@0xsuryansh 0xsuryansh marked this pull request as ready for review November 19, 2024 11:35
@0xsuryansh 0xsuryansh requested review from a team as code owners November 19, 2024 11:35
Copy link
Collaborator

@mateusz-sekara mateusz-sekara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job, some minor comments

return srcToken, dstToken
}

func mintAndApprove(t *testing.T, e ccdeploy.DeployedEnv, state ccdeploy.CCIPOnChainState, token *burn_mint_erc677.BurnMintERC677, chainSel uint64, amount *big.Int) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have a very similar helper for the USDC, it would be great to dedup these

// Fetch initial balance
if _, exists := initialBalances[dstToken.Address()]; !exists {
balance, err := dstToken.BalanceOf(nil, scenario.receiver)
require.NoError(t, err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar story already for USDC, if worth the effort / makes sense we can dedup this code

},
},
receiver: e.Chains[tenv.FeedChainSel].DeployerKey.From,
data: []byte(""),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest making data as nil or empty slice to make it more explicit

_, err = e.Chains[tenv.HomeChainSel].Confirm(tx)
require.NoError(t, err)
// Deploy and approve tokens.
srcToken1, dstToken1 := deployAndApproveTokens(t, tenv, state, "Token1")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was part of the ticket to also deploy some tokens in self serve manner. Right now, we deploy everything using the DeployerKey. We want to also verify it token transfers work properly in the self-serve deployed pool. Probably you need to create a new EOA and deploy token contracts from that

integration-tests/smoke/ccip_test.go Outdated Show resolved Hide resolved
integration-tests/smoke/ccip_test.go Outdated Show resolved Hide resolved
dstChain uint64
tokenAmounts []router.ClientEVMTokenAmount
receiver common.Address
data []byte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If data is always nil for this test, do we need this in the scenario?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For programmable token transfer tests data will not be nil right ?

integration-tests/smoke/ccip_test.go Outdated Show resolved Hide resolved
integration-tests/smoke/ccip_test.go Outdated Show resolved Hide resolved
…IP-4160_Implement_token_transfer_tests

# Conflicts:
#	deployment/ccip/changeset/test_helpers.go
@0xsuryansh 0xsuryansh requested a review from a team as a code owner November 27, 2024 16:15
@mateusz-sekara mateusz-sekara requested review from a team as code owners November 28, 2024 12:32
Copy link
Contributor

@dimkouv dimkouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly minor comments, approving. Feel free to resolve and re-request review if you agree with any.

for _, token := range tokens {
twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2))

owner, ok := owners[chain]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be moved in the outer loop.

expectedSeqNum := make(map[SourceDestPair]uint64)
expectedSeqNumExec := make(map[SourceDestPair][]uint64)

latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(testcontext.Get(t), nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better to pass ctx to this func?

require.NoError(t, err)

require.Eventually(t, func() bool {
actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe pass ctx to this func? to avoid getting a new one everyime.

tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client)
require.NoError(t, err)

balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar for ctx

inMemoryEnv := false

// use this if you are testing locally in memory
// tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be better if we can do this using some env var. So we can easily switch in CI or run without touching code.

selfServeDestTokenPoolDeployer,
state,
e.ExistingAddresses,
"SELF_SERVE_TOKEN",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


tinyOneCoin := new(big.Int).SetUint64(1)

// Test scenarios are defined here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment probably not necessary, it's obvious

tokenAmounts: []router.ClientEVMTokenAmount{
{
Token: srcToken.Address(),
Amount: tinyOneCoin,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name is a bit confusing for me tinyOneCoin maybe just one and oneE18, fiveE18 etc ?

},
receiver: state.Chains[sourceChain].Receiver.Address(),
expectedTokenBalances: map[common.Address]*big.Int{
selfServeSrcToken.Address(): new(big.Int).SetUint64(2),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can set two to a variable to follow same pattern with tinyOneCoin

require.NoError(t, err)

// Simulated backend sets chainID to 1337 always
chainID := big.NewInt(1337)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i believe it's similar for the commented out environment setup.

@@ -75,134 +73,3 @@ func TestInitialDeployOnLocal(t *testing.T) {

// TODO: Apply the proposal.
}

func TestTokenTransfer(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +191 to +216
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)
}
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is quite sequential. I would recommend splitting this test into multiple smaller tests and enabling parallel execution.

A few options we could consider include:

  1. Using multiple wallet addresses.
  2. Breaking the test into separate segments (though this will require repeating the setup), and assigning a dedicated runner for each segment. This would reduce the overall execution time, as the message processing wait time can be parallelized across the different tests. With this approach, we could potentially achieve at least a 3x speedup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants