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

Minor CCIP e2e tests improvements #15462

Merged
merged 3 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 100 additions & 53 deletions deployment/ccip/changeset/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"testing"
"time"

"golang.org/x/sync/errgroup"

mapset "github.com/deckarep/golang-set/v2"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -750,58 +752,96 @@ func DeployTransferableToken(
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], srcActor, addresses, token)
if err != nil {
return nil, nil, nil, nil, err
}
dstToken, dstPool, err := deployTransferTokenOneEnd(lggr, chains[dst], dstActor, addresses, token)
srcToken, srcPool, dstToken, dstPool, err := deployTokenPoolsInParallel(lggr, chains, src, dst, srcActor, dstActor, state, addresses, token)
if err != nil {
return nil, nil, nil, nil, err
}

// Attach token pools to registry
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], dstActor, dstToken.Address(), dstPool.Address()); err != nil {
return nil, nil, nil, nil, err
}

// Connect pool to each other
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, dstActor, src, srcToken.Address(), srcPool.Address()); err != nil {
// Configure pools in parallel
configurePoolGrp := errgroup.Group{}
configurePoolGrp.Go(func() error {
err := setTokenPoolCounterPart(chains[src], srcPool, srcActor, dst, dstToken.Address(), dstPool.Address())
if err != nil {
return fmt.Errorf("failed to set token pool counter part chain %d: %w", src, err)
}
err = grantMintBurnPermissions(lggr, chains[src], srcToken, srcActor, srcPool.Address())
if err != nil {
return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", src, err)
}
return nil
})
configurePoolGrp.Go(func() error {
err := setTokenPoolCounterPart(chains[dst], dstPool, dstActor, src, srcToken.Address(), srcPool.Address())
if err != nil {
return fmt.Errorf("failed to set token pool counter part chain %d: %w", dst, err)
}
if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstActor, dstPool.Address()); err != nil {
return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", dst, err)
}
return nil
})
if err := configurePoolGrp.Wait(); err != nil {
return nil, nil, nil, nil, err
}
return srcToken, srcPool, dstToken, dstPool, nil
}

// Add burn/mint permissions
if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcActor, srcPool.Address()); err != nil {
func deployTokenPoolsInParallel(
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,
) {
deployGrp := errgroup.Group{}
// Deploy token and pools
var srcToken *burn_mint_erc677.BurnMintERC677
var srcPool *burn_mint_token_pool.BurnMintTokenPool
var dstToken *burn_mint_erc677.BurnMintERC677
var dstPool *burn_mint_token_pool.BurnMintTokenPool

deployGrp.Go(func() error {
var err error
srcToken, srcPool, err = deployTransferTokenOneEnd(lggr, chains[src], srcActor, addresses, token)
if err != nil {
return err
}
if err := attachTokenToTheRegistry(chains[src], state.Chains[src], srcActor, srcToken.Address(), srcPool.Address()); err != nil {
return err
}
return nil
})
deployGrp.Go(func() error {
var err error
dstToken, dstPool, err = deployTransferTokenOneEnd(lggr, chains[dst], dstActor, addresses, token)
if err != nil {
return err
}
if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], dstActor, dstToken.Address(), dstPool.Address()); err != nil {
return err
}
return nil
})
if err := deployGrp.Wait(); err != nil {
return nil, nil, nil, nil, err
}

if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstActor, dstPool.Address()); err != nil {
return nil, nil, nil, nil, err
if srcToken == nil || srcPool == nil || dstToken == nil || dstPool == nil {
return nil, nil, nil, nil, fmt.Errorf("failed to deploy token and pool")
}

return srcToken, srcPool, dstToken, dstPool, nil
}

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(actor, address)
if err != nil {
return err
}
_, err = chain.Confirm(tx)
if err != nil {
return err
}

lggr.Infow("Granting mint permissions", "token", token.Address(), "minter", address)
tx, err = token.GrantMintRole(actor, address)
lggr.Infow("Granting burn/mint permissions", "token", token.Address(), "address", address)
tx, err := token.GrantMintAndBurnRoles(actor, address)
if err != nil {
return err
}
Expand Down Expand Up @@ -1023,28 +1063,35 @@ func MintAndAllow(
owners map[uint64]*bind.TransactOpts,
tkMap map[uint64][]*burn_mint_erc677.BurnMintERC677,
) {
configurePoolGrp := errgroup.Group{}
tenCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10))

for chain, tokens := range tkMap {
owner, ok := owners[chain]
require.True(t, ok)

for _, token := range tokens {
tx, err := token.Mint(
owner,
e.Chains[chain].DeployerKey.From,
new(big.Int).Mul(tenCoins, 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(), tenCoins)
require.NoError(t, err)
_, err = e.Chains[chain].Confirm(tx)
require.NoError(t, err)
}
tokens := tokens
configurePoolGrp.Go(func() error {
for _, token := range tokens {
tx, err := token.Mint(
owner,
e.Chains[chain].DeployerKey.From,
new(big.Int).Mul(tenCoins, 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(), tenCoins)
require.NoError(t, err)
_, err = e.Chains[chain].Confirm(tx)
require.NoError(t, err)
}
return nil
})
}

require.NoError(t, configurePoolGrp.Wait())
}

// TransferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed
Expand Down
99 changes: 63 additions & 36 deletions deployment/ccip/changeset/test_usdc_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package changeset
import (
"math/big"

"golang.org/x/sync/errgroup"

"github.com/ethereum/go-ethereum/common"

"github.com/smartcontractkit/chainlink-ccip/pkg/reader"
Expand All @@ -27,53 +29,78 @@ func ConfigureUSDCTokenPools(
srcPool := state.Chains[src].USDCTokenPool
dstPool := state.Chains[dst].USDCTokenPool

// Attach token pools to registry
if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil {
lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address())
return nil, nil, err
args := []struct {
sourceChain deployment.Chain
dstChainSel uint64
state CCIPChainState
srcToken *burn_mint_erc677.BurnMintERC677
srcPool *usdc_token_pool.USDCTokenPool
dstToken *burn_mint_erc677.BurnMintERC677
dstPool *usdc_token_pool.USDCTokenPool
}{
{
chains[src],
dst,
state.Chains[src],
srcToken,
srcPool,
dstToken,
dstPool,
},
{
chains[dst],
src,
state.Chains[dst],
dstToken,
dstPool,
srcToken,
srcPool,
},
}

if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil {
lggr.Errorw("Failed to attach token to the registry", "err", err, "token", dstToken.Address(), "pool", dstPool.Address())
return nil, nil, err
configurePoolGrp := errgroup.Group{}
for _, arg := range args {
configurePoolGrp.Go(configureSingleChain(lggr, arg.sourceChain, arg.dstChainSel, arg.state, arg.srcToken, arg.srcPool, arg.dstToken, arg.dstPool))
}

// Connect pool to each other
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())
if err := configurePoolGrp.Wait(); err != nil {
return nil, nil, err
}
return srcToken, dstToken, 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
}
func configureSingleChain(
lggr logger.Logger,
sourceChain deployment.Chain,
dstChainSel uint64,
state CCIPChainState,
srcToken *burn_mint_erc677.BurnMintERC677,
srcPool *usdc_token_pool.USDCTokenPool,
dstToken *burn_mint_erc677.BurnMintERC677,
dstPool *usdc_token_pool.USDCTokenPool,
) func() error {
return func() error {
if err := attachTokenToTheRegistry(sourceChain, state, sourceChain.DeployerKey, srcToken.Address(), srcPool.Address()); err != nil {
lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address())
return err
}

// Add burn/mint permissions for source
for _, addr := range []common.Address{
srcPool.Address(),
state.Chains[src].MockUSDCTokenMessenger.Address(),
state.Chains[src].MockUSDCTransmitter.Address(),
} {
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
if err := setUSDCTokenPoolCounterPart(sourceChain, srcPool, dstChainSel, sourceChain.DeployerKey, dstToken.Address(), dstPool.Address()); err != nil {
lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address())
return err
}
}

// Add burn/mint permissions for dest
for _, addr := range []common.Address{
dstPool.Address(),
state.Chains[dst].MockUSDCTokenMessenger.Address(),
state.Chains[dst].MockUSDCTransmitter.Address(),
} {
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
for _, addr := range []common.Address{
srcPool.Address(),
state.MockUSDCTokenMessenger.Address(),
state.MockUSDCTransmitter.Address(),
} {
if err := grantMintBurnPermissions(lggr, sourceChain, srcToken, sourceChain.DeployerKey, addr); err != nil {
lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "address", addr)
return err
}
}
return nil
}

return srcToken, dstToken, nil
}

func UpdateFeeQuoterForUSDC(
Expand Down
35 changes: 27 additions & 8 deletions integration-tests/smoke/ccip/ccip_usdc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"golang.org/x/exp/maps"
"golang.org/x/sync/errgroup"

"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"
Expand Down Expand Up @@ -79,19 +82,15 @@ func TestUSDCTokenTransfer(t *testing.T) {
map[uint64]*bind.TransactOpts{
chainA: ownerChainA,
chainB: ownerChainB,
chainC: ownerChainC}, map[uint64][]*burn_mint_erc677.BurnMintERC677{
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)

err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC)
require.NoError(t, err)

err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC)
err = updateFeeQuoters(lggr, e, state, chainA, chainB, chainC, aChainUSDC, bChainUSDC, cChainUSDC)
require.NoError(t, err)

// MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details
Expand Down Expand Up @@ -257,3 +256,23 @@ func TestUSDCTokenTransfer(t *testing.T) {
changeset.WaitForTheTokenBalance(ctx, t, cChainUSDC.Address(), receiver, e.Chains[chainC], expectedBalance)
})
}

func updateFeeQuoters(
lggr logger.Logger,
e deployment.Environment,
state changeset.CCIPOnChainState,
chainA, chainB, chainC uint64,
aChainUSDC, bChainUSDC, cChainUSDC *burn_mint_erc677.BurnMintERC677,
) error {
updateFeeQtrGrp := errgroup.Group{}
updateFeeQtrGrp.Go(func() error {
return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC)
})
updateFeeQtrGrp.Go(func() error {
return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC)
})
updateFeeQtrGrp.Go(func() error {
return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC)
})
return updateFeeQtrGrp.Wait()
}
Loading