Skip to content

Commit 9ecd146

Browse files
yihuanglukitsbrian
authored andcommitted
Problem: base fee conversion could panic on overflow (#433)
* prevent integer overflow use sdkmath.MaxBitLen cleanup * changelog --------- Co-authored-by: Brian Luk <brian6.dev@gmail.com>
1 parent 426480e commit 9ecd146

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ Ref: https://keepachangelog.com/en/1.0.0/
3737

3838
## Unreleased
3939

40+
### Bug Fixes
41+
42+
- (ante) [#422](https://github.com/crypto-org-chain/ethermint/pull/422) vendor `NewDeductFeeDecorator` to re-use the custom `checkTxFeeWithValidatorMinGasPrices` method, so it'll repsect the `DefaultPriorityReduction` config.
43+
- (feemarket) [#433](https://github.com/crypto-org-chain/ethermint/pull/433) Fix sdk int conversion panic with baseFee.
44+
45+
### Features
46+
47+
## v0.21.x-cronos
48+
4049
### Features
4150

4251
* (rpc) [#1682](https://github.com/evmos/ethermint/pull/1682) Add config for maximum number of bytes returned from eth_call.

types/int.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,23 @@ import (
1919
fmt "fmt"
2020
math "math"
2121
"math/big"
22+
"math/bits"
2223

2324
errorsmod "cosmossdk.io/errors"
2425
sdkmath "cosmossdk.io/math"
2526
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
2627
)
2728

28-
const maxBitLen = 256
29+
const (
30+
maxWordLen = sdkmath.MaxBitLen / bits.UintSize
31+
)
32+
33+
var MaxInt256 *big.Int
34+
35+
func init() {
36+
var tmp big.Int
37+
MaxInt256 = tmp.Lsh(big.NewInt(1), sdkmath.MaxBitLen).Sub(&tmp, big.NewInt(1))
38+
}
2939

3040
// SafeInt64 checks for overflows while casting a uint64 to int64 value.
3141
func SafeInt64(value uint64) (int64, error) {
@@ -52,7 +62,28 @@ func SafeNewIntFromBigInt(i *big.Int) (sdkmath.Int, error) {
5262
return sdkmath.NewIntFromBigInt(i), nil
5363
}
5464

65+
// SaturatedNewInt constructs Int from big.Int, truncate if more than 256bits
66+
func SaturatedNewInt(i *big.Int) sdkmath.Int {
67+
if !IsValidInt256(i) {
68+
i = MaxInt256
69+
}
70+
return sdkmath.NewIntFromBigInt(i)
71+
}
72+
5573
// IsValidInt256 check the bound of 256 bit number
5674
func IsValidInt256(i *big.Int) bool {
57-
return i == nil || i.BitLen() <= maxBitLen
75+
return i == nil || !bigIntOverflows(i)
76+
}
77+
78+
// check if the big int overflows,
79+
// NOTE: copied from cosmos-sdk.
80+
func bigIntOverflows(i *big.Int) bool {
81+
// overflow is defined as i.BitLen() > MaxBitLen
82+
// however this check can be expensive when doing many operations.
83+
// So we first check if the word length is greater than maxWordLen.
84+
// However the most significant word could be zero, hence we still do the bitlen check.
85+
if len(i.Bits()) > maxWordLen {
86+
return i.BitLen() > sdkmath.MaxBitLen
87+
}
88+
return false
5889
}

types/int_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package types
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
7+
sdkmath "cosmossdk.io/math"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestMaxInt256(t *testing.T) {
12+
maxInt256Plus1 := new(big.Int).Add(MaxInt256, big.NewInt(1))
13+
require.Equal(t, sdkmath.MaxBitLen, MaxInt256.BitLen())
14+
require.Equal(t, sdkmath.MaxBitLen+1, maxInt256Plus1.BitLen())
15+
16+
require.True(t, IsValidInt256(MaxInt256))
17+
require.False(t, IsValidInt256(maxInt256Plus1))
18+
}

x/feemarket/keeper/params.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package keeper
1818
import (
1919
"math/big"
2020

21+
ethermint "github.com/evmos/ethermint/types"
2122
"github.com/evmos/ethermint/x/feemarket/types"
2223

2324
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -79,7 +80,7 @@ func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
7980
// SetBaseFee set's the base fee in the store
8081
func (k Keeper) SetBaseFee(ctx sdk.Context, baseFee *big.Int) {
8182
params := k.GetParams(ctx)
82-
params.BaseFee = sdk.NewIntFromBigInt(baseFee)
83+
params.BaseFee = ethermint.SaturatedNewInt(baseFee)
8384
err := k.SetParams(ctx, params)
8485
if err != nil {
8586
return

0 commit comments

Comments
 (0)