From 81b35412e0802aae14cd9edc52b4f3973e4fbcfa Mon Sep 17 00:00:00 2001 From: dimitris Date: Wed, 27 Nov 2024 16:53:42 +0200 Subject: [PATCH] Fix flaky ccip tests (#15432) * minor change to trigger ci * minor change to trigger ci * retry until native fee is sufficient * trigger ci --- deployment/ccip/changeset/test_helpers.go | 57 +++++++++++++++---- integration-tests/smoke/ccip/ccip_rmn_test.go | 2 + 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index 188c7daedd8..a789a8c45fa 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httptest" "sort" + "strings" "testing" "time" @@ -16,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -398,19 +400,12 @@ func CCIPSendRequest( if testRouter { r = state.Chains[src].TestRouter } - fee, err := r.GetFee( - &bind.CallOpts{Context: context.Background()}, dest, msg) - if err != nil { - return nil, 0, errors.Wrap(deployment.MaybeDataErr(err), "failed to get fee") - } - if msg.FeeToken == common.HexToAddress("0x0") { - e.Chains[src].DeployerKey.Value = fee - defer func() { e.Chains[src].DeployerKey.Value = nil }() + + if msg.FeeToken == common.HexToAddress("0x0") { // fee is in native token + return retryCcipSendUntilNativeFeeIsSufficient(e, r, src, dest, msg) } - tx, err := r.CcipSend( - e.Chains[src].DeployerKey, - dest, - msg) + + tx, err := r.CcipSend(e.Chains[src].DeployerKey, dest, msg) if err != nil { return nil, 0, errors.Wrap(err, "failed to send CCIP message") } @@ -421,6 +416,44 @@ func CCIPSendRequest( return tx, blockNum, nil } +// retryCcipSendUntilNativeFeeIsSufficient sends a CCIP message with a native fee, +// and retries until the fee is sufficient. This is due to the fact that the fee is not known in advance, +// and the message will be rejected if the fee is insufficient. +func retryCcipSendUntilNativeFeeIsSufficient( + e deployment.Environment, + r *router.Router, + src, + dest uint64, + msg router.ClientEVM2AnyMessage, +) (*types.Transaction, uint64, error) { + const errCodeInsufficientFee = "0x07da6ee6" + defer func() { e.Chains[src].DeployerKey.Value = nil }() + + for { + fee, err := r.GetFee(&bind.CallOpts{Context: context.Background()}, dest, msg) + if err != nil { + return nil, 0, errors.Wrap(deployment.MaybeDataErr(err), "failed to get fee") + } + + e.Chains[src].DeployerKey.Value = fee + + tx, err := r.CcipSend(e.Chains[src].DeployerKey, dest, msg) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to send CCIP message") + } + + blockNum, err := e.Chains[src].Confirm(tx) + if err != nil { + if strings.Contains(err.Error(), errCodeInsufficientFee) { + continue + } + return nil, 0, errors.Wrap(err, "failed to confirm CCIP message") + } + + return tx, blockNum, nil + } +} + // CCIPSendCalldata packs the calldata for the Router's ccipSend method. // This is expected to be used in Multicall scenarios (i.e multiple ccipSend calls // in a single transaction). diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go index 21e239da1c4..4083be1c6be 100644 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip/ccip_rmn_test.go @@ -177,6 +177,8 @@ const ( func runRmnTestCase(t *testing.T, tc rmnTestCase) { require.NoError(t, os.Setenv("ENABLE_RMN", "true")) + t.Logf("Running RMN test case: %s", tc.name) + envWithRMN, rmnCluster := testsetups.NewLocalDevEnvironmentWithRMN(t, logger.TestLogger(t), len(tc.rmnNodes)) t.Logf("envWithRmn: %#v", envWithRMN)