Skip to content

Commit

Permalink
Fix slice bounds out of range error in performBatchCall (#1145)
Browse files Browse the repository at this point in the history
Catching `err` if the evm call fails
  • Loading branch information
0xnogo committed Jul 5, 2024
1 parent 572cc60 commit 5b6e1d6
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ func (d *DynamicPriceGetter) performBatchCall(ctx context.Context, chainID uint6
calls = append(calls, batchCalls.latestRoundDataCalls...)

results, err := evmCaller.BatchCall(ctx, 0, calls)
if err != nil {
return fmt.Errorf("batch call on chain %d failed: %w", chainID, err)
}

// Extract results.
decimals := make([]uint8, 0, nbDecimalCalls)
Expand Down
61 changes: 61 additions & 0 deletions core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type testParameters struct {
evmClients map[uint64]DynamicPriceGetterClient
tokens []common.Address
expectedTokenPrices map[common.Address]big.Int
evmCallErr bool
invalidConfigErrorExpected bool
priceResolutionErrorExpected bool
}
Expand Down Expand Up @@ -58,6 +59,10 @@ func TestDynamicPriceGetter(t *testing.T) {
name: "no_aggregator_for_token",
param: testParamNoAggregatorForToken(t),
},
{
name: "batchCall_returns_err",
param: testParamBatchCallReturnsErr(t),
},
}

for _, test := range tests {
Expand All @@ -82,6 +87,12 @@ func TestDynamicPriceGetter(t *testing.T) {
tokens = append(tokens, tokenAddr)
}
prices, err := pg.TokenPricesUSD(ctx, tokens)

if test.param.evmCallErr {
require.Error(t, err)
return
}

if test.param.priceResolutionErrorExpected {
require.Error(t, err)
return
Expand Down Expand Up @@ -454,6 +465,50 @@ func testParamNoAggregatorForToken(t *testing.T) testParameters {
}
}

func testParamBatchCallReturnsErr(t *testing.T) testParameters {
tk1 := utils.RandomAddress()
tk2 := utils.RandomAddress()
tk3 := utils.RandomAddress()
cfg := config.DynamicPriceGetterConfig{
AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{
tk1: {
ChainID: 101,
AggregatorContractAddress: utils.RandomAddress(),
},
tk2: {
ChainID: 102,
AggregatorContractAddress: utils.RandomAddress(),
},
},
StaticPrices: map[common.Address]config.StaticPriceConfig{
tk3: {
ChainID: 103,
Price: big.NewInt(1_234_000),
},
},
}
// Real LINK/USD example from OP.
round1 := aggregator_v3_interface.LatestRoundData{
RoundId: big.NewInt(1000),
Answer: big.NewInt(1396818990),
StartedAt: big.NewInt(1704896575),
UpdatedAt: big.NewInt(1704896575),
AnsweredInRound: big.NewInt(1000),
}
evmClients := map[uint64]DynamicPriceGetterClient{
uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}),
uint64(102): {
BatchCaller: mockErrCaller(t),
},
}
return testParameters{
cfg: cfg,
evmClients: evmClients,
tokens: []common.Address{tk1, tk2, tk3},
evmCallErr: true,
}
}

func mockClient(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface.LatestRoundData) DynamicPriceGetterClient {
return DynamicPriceGetterClient{
BatchCaller: mockCaller(t, decimals, rounds),
Expand All @@ -479,6 +534,12 @@ func mockCaller(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface
return caller
}

func mockErrCaller(t *testing.T) *rpclibmocks.EvmBatchCaller {
caller := rpclibmocks.NewEvmBatchCaller(t)
caller.On("BatchCall", mock.Anything, uint64(0), mock.Anything).Return(nil, assert.AnError).Maybe()
return caller
}

// multExp returns the result of multiplying x by 10^e.
func multExp(x *big.Int, e int64) *big.Int {
return big.NewInt(0).Mul(x, big.NewInt(0).Exp(big.NewInt(10), big.NewInt(e), nil))
Expand Down

0 comments on commit 5b6e1d6

Please sign in to comment.