diff --git a/execute/exectypes/costly_messages_test.go b/execute/exectypes/costly_messages_test.go index dadde90d9..ef05a385a 100644 --- a/execute/exectypes/costly_messages_test.go +++ b/execute/exectypes/costly_messages_test.go @@ -2,19 +2,15 @@ package exectypes import ( "context" - "fmt" "math/big" "testing" "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-ccip/internal/plugintypes" - gasmock "github.com/smartcontractkit/chainlink-ccip/mocks/execute/internal_/gas" readerpkg_mock "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/reader" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) @@ -289,269 +285,3 @@ func TestCCIPMessageFeeE18USDCalculator_MessageFeeE18USD(t *testing.T) { }) } } - -func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) { - destChainSelector := ccipocr3.ChainSelector(1) - nativeTokenPrice := ccipocr3.BigInt{ - Int: new(big.Int).Mul(big.NewInt(2), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))} - - tests := []struct { - name string - messages []ccipocr3.Message - messageGases []uint64 - executionFee *big.Int - dataAvailabilityFee *big.Int - feeComponentsError error - daGasConfig ccipocr3.DataAvailabilityGasConfig - want map[ccipocr3.Bytes32]plugintypes.USD18 - wantErr bool - }{ - { - name: "happy path, no DA cost", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b2, DestChainSelector: destChainSelector}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b3, DestChainSelector: destChainSelector}, - }, - }, - messageGases: []uint64{100, 200, 300}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: big.NewInt(0), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1, - DestGasPerDataAvailabilityByte: 1, - DestDataAvailabilityMultiplierBps: 1, - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(20000), // 10000 * 2 (price conversion) - b2: plugintypes.NewUSD18FromUSD(40000), // 20000 * 2 - b3: plugintypes.NewUSD18FromUSD(60000), // 30000 * 2 - }, - wantErr: false, - }, - { - name: "happy path, with DA cost", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b2, DestChainSelector: destChainSelector}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b3, DestChainSelector: destChainSelector}, - }, - }, - messageGases: []uint64{100, 200, 300}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: new(big.Int).Mul(big.NewInt(400), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1200, - DestGasPerDataAvailabilityByte: 10, - DestDataAvailabilityMultiplierBps: 200, - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(110400), // 20_000 (exec) + 90_400 (da) - b2: plugintypes.NewUSD18FromUSD(130400), // 40_000 (exec) + 90_400 (da) - b3: plugintypes.NewUSD18FromUSD(150400), // 60_000 (exec) + 90_400 (da) - }, - wantErr: false, - }, - { - name: "message with token amounts affects DA gas calculation", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - TokenAmounts: []ccipocr3.RampTokenAmount{ - { - SourcePoolAddress: []byte("source_pool"), - DestTokenAddress: []byte("dest_token"), - ExtraData: []byte("extra"), - DestExecData: []byte("exec_data"), - Amount: ccipocr3.NewBigInt(big.NewInt(1)), - }, - }, - Data: []byte("some_data"), - Sender: []byte("sender"), - Receiver: []byte("receiver"), - ExtraArgs: []byte("extra_args"), - }, - }, - messageGases: []uint64{100}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: new(big.Int).Mul(big.NewInt(400), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1000, - DestGasPerDataAvailabilityByte: 10, - DestDataAvailabilityMultiplierBps: 200, - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(158_400), // 20_000 (exec) + 138_400 (da) - }, - wantErr: false, - }, - { - name: "zero DA multiplier results in only overhead gas", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - Data: []byte("some_data"), - }, - }, - messageGases: []uint64{100}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: new(big.Int).Mul(big.NewInt(400), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1000, - DestGasPerDataAvailabilityByte: 10, - DestDataAvailabilityMultiplierBps: 0, // Zero multiplier - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(20000), // Only exec cost, DA cost is 0 - }, - wantErr: false, - }, - { - name: "large message with multiple tokens", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - TokenAmounts: []ccipocr3.RampTokenAmount{ - { - SourcePoolAddress: make([]byte, 100), // Large token data - DestTokenAddress: make([]byte, 100), - ExtraData: make([]byte, 100), - DestExecData: make([]byte, 100), - Amount: ccipocr3.NewBigInt(big.NewInt(1)), - }, - { - SourcePoolAddress: make([]byte, 100), // Second token - DestTokenAddress: make([]byte, 100), - ExtraData: make([]byte, 100), - DestExecData: make([]byte, 100), - Amount: ccipocr3.NewBigInt(big.NewInt(1)), - }, - }, - Data: make([]byte, 1000), // Large message data - Sender: make([]byte, 100), - Receiver: make([]byte, 100), - ExtraArgs: make([]byte, 100), - }, - }, - messageGases: []uint64{100}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: new(big.Int).Mul(big.NewInt(400), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1000, - DestGasPerDataAvailabilityByte: 10, - DestDataAvailabilityMultiplierBps: 200, - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(439_200), // 20_000 (exec) + 437_200 (da) - }, - wantErr: false, - }, - { - name: "fee components error", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b2}, - }, - { - Header: ccipocr3.RampMessageHeader{MessageID: b3}, - }, - }, - messageGases: []uint64{100, 200, 300}, - executionFee: big.NewInt(100), - dataAvailabilityFee: big.NewInt(0), - feeComponentsError: fmt.Errorf("error"), - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1, - DestGasPerDataAvailabilityByte: 1, - DestDataAvailabilityMultiplierBps: 1, - }, - want: nil, - wantErr: true, - }, - { - name: "minimal message - only constant parts", - messages: []ccipocr3.Message{ - { - Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector}, - }, - }, - messageGases: []uint64{100}, - executionFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - dataAvailabilityFee: new(big.Int).Mul(big.NewInt(400), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)), - feeComponentsError: nil, - daGasConfig: ccipocr3.DataAvailabilityGasConfig{ - DestDataAvailabilityOverheadGas: 1000, - DestGasPerDataAvailabilityByte: 10, - DestDataAvailabilityMultiplierBps: 200, - }, - want: map[ccipocr3.Bytes32]plugintypes.USD18{ - b1: plugintypes.NewUSD18FromUSD(107_200), // 20_000 (exec) + 87_200 (da) - }, - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - lggr := logger.Test(t) - - mockReader := readerpkg_mock.NewMockCCIPReader(t) - feeComponents := types.ChainFeeComponents{ - ExecutionFee: tt.executionFee, - DataAvailabilityFee: tt.dataAvailabilityFee, - } - mockReader.EXPECT().GetDestChainFeeComponents(ctx).Return(feeComponents, tt.feeComponentsError) - mockReader.EXPECT().GetWrappedNativeTokenPriceUSD( - ctx, - []ccipocr3.ChainSelector{destChainSelector}, - ).Return( - map[ccipocr3.ChainSelector]ccipocr3.BigInt{ - destChainSelector: nativeTokenPrice, - }, - ).Maybe() - if !tt.wantErr { - mockReader.EXPECT().GetMedianDataAvailabilityGasConfig(ctx).Return(tt.daGasConfig, nil) - } - - ep := gasmock.NewMockEstimateProvider(t) - if !tt.wantErr { - for _, messageGas := range tt.messageGases { - ep.EXPECT().CalculateMessageMaxGas(mock.Anything).Return(messageGas).Once() - } - } - - calculator := CCIPMessageExecCostUSD18Calculator{ - lggr: lggr, - ccipReader: mockReader, - estimateProvider: ep, - } - - got, err := calculator.MessageExecCostUSD18(ctx, tt.messages) - if tt.wantErr { - assert.Error(t, err) - return - } - assert.NoError(t, err) - assert.Equal(t, tt.want, got) - }) - } -}