Skip to content

Commit

Permalink
Minor CCIP e2e tests improvements (#15462)
Browse files Browse the repository at this point in the history
* Parallel deployment of contracts

* Parallel deployment of contracts

* Minor refactoring
  • Loading branch information
mateusz-sekara authored Nov 29, 2024
1 parent 2ca1a09 commit 314df84
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 97 deletions.
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 @@ -751,58 +753,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 @@ -1024,28 +1064,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()
}

0 comments on commit 314df84

Please sign in to comment.