Skip to content

Commit

Permalink
add new e2e messaging tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jhweintraub committed Nov 19, 2024
1 parent 56e30fa commit 1da4e3e
Showing 1 changed file with 258 additions and 4 deletions.
262 changes: 258 additions & 4 deletions integration-tests/smoke/ccip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/stretchr/testify/require"

cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-ccip/pluginconfig"
jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"

Expand Down Expand Up @@ -360,7 +362,7 @@ func Test_PricingForTokenTransfers(t *testing.T) {
// Deploy the environment
lggr := logger.TestLogger(t)
ctx := ccdeploy.Context(t)
tenv, _, _ := testsetups.NewLocalDevEnvironment(t, lggr)
tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr)

// Load the test state
e := tenv.Env
Expand Down Expand Up @@ -474,7 +476,7 @@ func Test_PricingForTokenTransfers(t *testing.T) {
srcFee, err := state.Chains[src].Router.GetFee(nil, dest, ccipMessage)
require.NoError(t, err)

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage)
seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Check the fee token balance after the request and ensure fee tokens were spent
Expand Down Expand Up @@ -542,7 +544,7 @@ func Test_PricingForTokenTransfers(t *testing.T) {
ExtraArgs: nil,
}

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage)
seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Wait for all commit reports to land.
Expand Down Expand Up @@ -628,7 +630,7 @@ func Test_PricingForTokenTransfers(t *testing.T) {
srcFee, err := state.Chains[src].Router.GetFee(nil, dest, ccipMessage)
require.NoError(t, err)

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage)
seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Check the fee token balance after the request and ensure fee tokens were spent
Expand Down Expand Up @@ -727,3 +729,255 @@ func Test_PricingForTokenTransfers(t *testing.T) {
require.Nil(t, tx)
})
}

func Test_PricingForMessages(t *testing.T) {
// Deploy the environment
lggr := logger.TestLogger(t)
ctx := ccdeploy.Context(t)
tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr)

// Load the test state
e := tenv.Env
state, err := ccdeploy.LoadOnchainState(e)
require.NoError(t, err)

feeds := state.Chains[tenv.FeedChainSel].USDFeeds
tokenConfig := ccdeploy.NewTokenConfig()
tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol,
pluginconfig.TokenInfo{
AggregatorAddress: cciptypes.UnknownEncodedAddress(feeds[ccdeploy.LinkSymbol].Address().String()),
Decimals: ccdeploy.LinkDecimals,
DeviationPPB: cciptypes.NewBigIntFromInt64(1e9),
},
)

// Apply migration
output, err := changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{
HomeChainSel: tenv.HomeChainSel,
FeedChainSel: tenv.FeedChainSel,
ChainsToDeploy: e.AllChainSelectors(),
TokenConfig: tokenConfig,
MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e),
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)

// Ensure capreg logs are up to date.
ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks)

// Create an empty tokenAmounts map since we are sending a message without a token
tokens := []router.ClientEVMTokenAmount{}

// Apply the jobs.
for nodeID, jobs := range output.JobSpecs {
for _, job := range jobs {
// Note these auto-accept
_, err := e.Offchain.ProposeJob(ctx,
&jobv1.ProposeJobRequest{
NodeId: nodeID,
Spec: job,
})
require.NoError(t, err)
}
}

// 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)

// Mint 2 tokens to be transferred
twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2))

linkToken := state.Chains[tenv.HomeChainSel].LinkToken

t.Run("Send Token Pay with Link token home chain -> remote", func(t *testing.T) {
// Approve to spend link token
tx, err := linkToken.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)

// Assign Src to the Home Chain Selector and destChain to the Feed Chain Selector
src := tenv.HomeChainSel
dest, destChain := tenv.FeedChainSel, e.Chains[tenv.FeedChainSel]

// get the header for the destination chain and the relevant block number
latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
block := latesthdr.Number.Uint64()
startBlocks[dest] = &block

// Send to the receiver on the destination chain paying with LINK token
var (
receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32)
data = []byte("hello world")
feeToken = linkToken.Address()
)

ccipMessage := router.ClientEVM2AnyMessage{
Receiver: receiver,
Data: data,
TokenAmounts: tokens,
FeeToken: feeToken,
ExtraArgs: nil,
}

// Get the fee Token Balance Before
feeTokenBalanceBefore, err := linkToken.BalanceOf(nil, e.Chains[tenv.HomeChainSel].DeployerKey.From)
require.NoError(t, err)

// Check the fee Amount
srcFee, err := state.Chains[src].Router.GetFee(nil, dest, ccipMessage)
require.NoError(t, err)

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Check the fee token balance after the request and ensure fee tokens were spent
feeTokenBalanceAfter, err := linkToken.BalanceOf(nil, e.Chains[tenv.HomeChainSel].DeployerKey.From)
require.NoError(t, err)
require.Equal(t, feeTokenBalanceAfter, new(big.Int).Sub(feeTokenBalanceBefore, srcFee))

// Wait for all commit reports to land.
ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks)

// After commit is reported on all chains, token prices should be updated in FeeQuoter.
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)

// Wait for all exec reports to land
ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks)

// Delete from the expcted seq num the chain that was just tested so that we don't pass it to the
// commit report in the next test
delete(expectedSeqNum, dest)
})

t.Run("Send Token Pay with native remote chain -> home", func(t *testing.T) {
// Assign Src to the Home Chain Selector and destChain to the Feed Chain Selector
src := tenv.FeedChainSel
dest, destChain := tenv.HomeChainSel, e.Chains[tenv.HomeChainSel]

// get the header for the destination chain and the relevant block number
latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
block := latesthdr.Number.Uint64()
startBlocks[dest] = &block

// Send to the receiver on the destination chain paying with native token
var (
receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32)
data = []byte("")
feeToken = common.HexToAddress("0x0")
)

ccipMessage := router.ClientEVM2AnyMessage{
Receiver: receiver,
Data: data,
TokenAmounts: tokens,
FeeToken: feeToken,
ExtraArgs: nil,
}

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Wait for all commit reports to land.
ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks)

// After commit is reported on all chains, token prices should be updated in FeeQuoter.
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)

// Wait for all exec reports to land
ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks)

delete(expectedSeqNum, dest)
})

t.Run("Send Token pay with wrapped native home chain -> remote", func(t *testing.T) {
WETH := state.Chains[tenv.HomeChainSel].Weth9

// We need to acquire some WETH to send with the tx so we deposit some ETH into the WETH contract
// but deployerKey is a reference so we need to dereference it and then reassign it
depositOps := *e.Chains[tenv.HomeChainSel].DeployerKey
depositOps.Value = twoCoins
tx, err := WETH.Deposit(&depositOps)
require.NoError(t, err)
_, err = e.Chains[tenv.HomeChainSel].Confirm(tx)
require.NoError(t, err)

// Approve to spend WETH token as feeToken
tx, err = WETH.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)

// Assign Src to the Home Chain Selector and destChain to the Feed Chain Selector
src := tenv.HomeChainSel
dest, destChain := tenv.FeedChainSel, e.Chains[tenv.FeedChainSel]

// get the header for the destination chain and the relevant block number
latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil)
require.NoError(t, err)
block := latesthdr.Number.Uint64()
startBlocks[dest] = &block

// Send to the receiver on the destination chain paying with LINK token
var (
receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32)
data = []byte("hello world")
feeToken = state.Chains[src].Weth9.Address()
)

ccipMessage := router.ClientEVM2AnyMessage{
Receiver: receiver,
Data: data,
TokenAmounts: tokens,
FeeToken: feeToken,
ExtraArgs: nil,
}

// Get the fee Token Balance Before
feeTokenBalanceBefore, err := WETH.BalanceOf(nil, e.Chains[src].DeployerKey.From)
require.NoError(t, err)

// Check the fee Amount
srcFee, err := state.Chains[src].Router.GetFee(nil, dest, ccipMessage)
require.NoError(t, err)

seqNum := ccdeploy.TestSendRequest(t, e, state, src, dest, false, ccipMessage).SequenceNumber
expectedSeqNum[dest] = seqNum

// Check the fee token balance after the request and ensure fee tokens were spent
feeTokenBalanceAfter, err := WETH.BalanceOf(nil, e.Chains[tenv.HomeChainSel].DeployerKey.From)
require.NoError(t, err)
require.Equal(t, feeTokenBalanceAfter, new(big.Int).Sub(feeTokenBalanceBefore, srcFee))

// Wait for all commit reports to land.
ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks)

// After commit is reported on all chains, token prices should be updated in FeeQuoter.
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)

// Wait for all exec reports to land
ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks)
})
}

0 comments on commit 1da4e3e

Please sign in to comment.