diff --git a/app/abci_utils.go b/app/abci_utils.go index c1a3a661..dcc299cc 100644 --- a/app/abci_utils.go +++ b/app/abci_utils.go @@ -2,7 +2,10 @@ package app import ( "fmt" + "math/big" + "sort" + "github.com/0glabs/0g-chain/chaincfg" "github.com/cockroachdb/errors" abci "github.com/cometbft/cometbft/abci/types" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -13,6 +16,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/signing" ) +const gasPriceSuggestionBlockNum int64 = 5 + type ( // GasTx defines the contract that a transaction with a gas limit must implement. GasTx interface { @@ -30,17 +35,29 @@ type ( // DefaultProposalHandler defines the default ABCI PrepareProposal and // ProcessProposal handlers. DefaultProposalHandler struct { - mempool mempool.Mempool - txVerifier ProposalTxVerifier - txSelector TxSelector + mempool mempool.Mempool + txVerifier ProposalTxVerifier + txSelector TxSelector + feemarketKeeper FeeMarketKeeper + } + FeeMarketKeeper interface { + SetSuggestionGasPrice(ctx sdk.Context, gas *big.Int) + } + + txnInfo struct { + gasPrice *big.Int + gasLimit uint64 + nonce uint64 + sender string } ) -func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier) *DefaultProposalHandler { +func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier, feemarketKeeper FeeMarketKeeper) *DefaultProposalHandler { return &DefaultProposalHandler{ - mempool: mp, - txVerifier: txVerifier, - txSelector: NewDefaultTxSelector(), + mempool: mp, + txVerifier: txVerifier, + txSelector: NewDefaultTxSelector(), + feemarketKeeper: feemarketKeeper, } } @@ -97,11 +114,14 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} } + txnInfoMap := make(map[string][]*txnInfo, h.mempool.CountTx()) + iterator := h.mempool.Select(ctx, req.Txs) selectedTxsSignersSeqs := make(map[string]uint64) var selectedTxsNums int for iterator != nil { memTx := iterator.Tx() + sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2() if err != nil { panic(fmt.Errorf("failed to get signatures: %w", err)) @@ -134,10 +154,42 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan txSignersSeqs[signer] = nonce } } + + if _, exists := txnInfoMap[signer]; !exists { + txnInfoMap[signer] = make([]*txnInfo, 0, 128) + } + + txnInfoMap[signer] = append(txnInfoMap[signer], &txnInfo{ + gasPrice: ethTx.GasPrice(), + gasLimit: ethTx.Gas(), + nonce: nonce, + sender: signer, + }) } } } } else { + // ignore multisig case now + fee := memTx.(sdk.Fee) + if len(sigs) == 1 { + signer := sdk.AccAddress(sigs[0].PubKey.Address()).String() + + if _, exists := txnInfoMap[signer]; !exists { + txnInfoMap[signer] = make([]*txnInfo, 0, 16) + } + + evmGasPrice, err := utilCosmosDemonGasPriceToEvmDemonGasPrice(fee.GetAmount()) + + if err == nil { + txnInfoMap[signer] = append(txnInfoMap[signer], &txnInfo{ + gasPrice: evmGasPrice, + gasLimit: utilCosmosDemonGasLimitToEvmDemonGasLimit(fee.GetGas()), + nonce: sigs[0].Sequence, + sender: signer, + }) + } + } + for _, sig := range sigs { signer := sdk.AccAddress(sig.PubKey.Address()).String() seq, ok := selectedTxsSignersSeqs[signer] @@ -198,6 +250,65 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan iterator = iterator.Next() } + + if len(txnInfoMap) == 0 { + h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0)) + } else { + senderCnt := 0 + txnCnt := 0 + for sender := range txnInfoMap { + sort.Slice(txnInfoMap[sender], func(i, j int) bool { + return txnInfoMap[sender][i].nonce < txnInfoMap[sender][j].nonce + }) + txnCnt += len(txnInfoMap[sender]) + senderCnt++ + } + + remaing := gasPriceSuggestionBlockNum * int64(maxBlockGas) + var lastProcessedTx *txnInfo + + for remaing > 0 && len(txnInfoMap) > 0 { + // Find the highest gas price among the first transaction of each account + var highestGasPrice *big.Int + var selectedSender string + + // Compare first transaction (lowest nonce) from each account + for sender, txns := range txnInfoMap { + if len(txns) == 0 { + delete(txnInfoMap, sender) + continue + } + + // First tx has lowest nonce due to earlier sorting + if highestGasPrice == nil || txns[0].gasPrice.Cmp(highestGasPrice) > 0 { + highestGasPrice = txns[0].gasPrice + selectedSender = sender + } + } + + if selectedSender == "" { + break + } + + // Process the selected transaction + selectedTx := txnInfoMap[selectedSender][0] + remaing -= int64(selectedTx.gasLimit) + lastProcessedTx = selectedTx + + // Remove processed transaction + txnInfoMap[selectedSender] = txnInfoMap[selectedSender][1:] + if len(txnInfoMap[selectedSender]) == 0 { + delete(txnInfoMap, selectedSender) + } + } + + if lastProcessedTx != nil && remaing <= 0 { + h.feemarketKeeper.SetSuggestionGasPrice(ctx, lastProcessedTx.gasPrice) + } else { + h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0)) + } + } + return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} } } @@ -336,3 +447,22 @@ func (ts *defaultTxSelector) SelectTxForProposal(maxTxBytes, maxBlockGas uint64, // check if we've reached capacity; if so, we cannot select any more transactions return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas)) } + +func utilCosmosDemonGasPriceToEvmDemonGasPrice(gasGroup sdk.Coins) (*big.Int, error) { + gasPrice := big.NewInt(0) + for _, coin := range gasGroup { + if coin.Denom == chaincfg.GasDenom { + thisGasPrice := big.NewInt(0).SetUint64(coin.Amount.Uint64()) + thisGasPrice = thisGasPrice.Mul(thisGasPrice, big.NewInt(0).SetInt64(chaincfg.GasDenomConversionMultiplier)) + gasPrice = gasPrice.Add(gasPrice, thisGasPrice) + } else { + return big.NewInt(0), fmt.Errorf("invalid denom: %s", coin.Denom) + } + } + + return gasPrice, nil +} + +func utilCosmosDemonGasLimitToEvmDemonGasLimit(gasLimit uint64) uint64 { + return gasLimit * chaincfg.GasDenomConversionMultiplier +} diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index c96a5239..eb5aad35 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -52,13 +52,17 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { tApp := app.TestApp{ App: *app.NewApp( - log.NewNopLogger(), - tmdb.NewMemDB(), chaincfg.DefaultNodeHome, nil, encodingConfig, opts, - baseapp.SetChainID(app.TestChainId), + app.NewBaseApp( + log.NewNopLogger(), + tmdb.NewMemDB(), + encodingConfig, + baseapp.SetChainID(app.TestChainId), + ), + nil, ), } diff --git a/app/app.go b/app/app.go index b10fd016..49c71347 100644 --- a/app/app.go +++ b/app/app.go @@ -267,7 +267,7 @@ type App struct { packetForwardKeeper *packetforwardkeeper.Keeper evmKeeper *evmkeeper.Keeper evmutilKeeper evmutilkeeper.Keeper - feeMarketKeeper feemarketkeeper.Keeper + feeMarketKeeper *feemarketkeeper.Keeper upgradeKeeper upgradekeeper.Keeper evidenceKeeper evidencekeeper.Keeper transferKeeper ibctransferkeeper.Keeper @@ -313,6 +313,7 @@ func NewApp( encodingConfig chainparams.EncodingConfig, options Options, bApp *baseapp.BaseApp, + setAbciProposalHandler func(feemarketKeeper FeeMarketKeeper) sdk.PrepareProposalHandler, ) *App { appCodec := encodingConfig.Marshaler legacyAmino := encodingConfig.Amino @@ -901,6 +902,10 @@ func NewApp( app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) + if setAbciProposalHandler != nil { + abciProposalHandler := setAbciProposalHandler(app.feeMarketKeeper) + bApp.SetPrepareProposal(abciProposalHandler) + } // load store if !options.SkipLoadLatest { if err := app.LoadLatestVersion(); err != nil { diff --git a/app/app_test.go b/app/app_test.go index 7ab5b262..becb9464 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -28,19 +28,36 @@ import ( func TestNewApp(t *testing.T) { chaincfg.SetSDKConfig() NewApp( - log.NewTMLogger(log.NewSyncWriter(os.Stdout)), - db.NewMemDB(), chaincfg.DefaultNodeHome, nil, MakeEncodingConfig(), DefaultOptions, + NewBaseApp( + log.NewTMLogger(log.NewSyncWriter(os.Stdout)), + db.NewMemDB(), + MakeEncodingConfig(), + baseapp.SetChainID(TestChainId), + ), + nil, ) } func TestExport(t *testing.T) { chaincfg.SetSDKConfig() db := db.NewMemDB() - app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, chaincfg.DefaultNodeHome, nil, MakeEncodingConfig(), DefaultOptions, baseapp.SetChainID(TestChainId)) + app := NewApp( + chaincfg.DefaultNodeHome, + nil, + MakeEncodingConfig(), + DefaultOptions, + NewBaseApp( + log.NewTMLogger(log.NewSyncWriter(os.Stdout)), + db, + MakeEncodingConfig(), + baseapp.SetChainID(TestChainId), + ), + nil, + ) genesisState := GenesisStateWithSingleValidator(&TestApp{App: *app}, NewDefaultGenesisState()) diff --git a/app/test_common.go b/app/test_common.go index 52b527e0..6c469e4a 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -96,7 +96,7 @@ func NewTestAppFromSealed() TestApp { bApp := NewBaseApp(log.NewNopLogger(), db, encCfg, baseapp.SetChainID(TestChainId)) app := NewApp( chaincfg.DefaultNodeHome, nil, - encCfg, DefaultOptions, bApp, + encCfg, DefaultOptions, bApp, nil, ) return TestApp{App: *app} } @@ -117,7 +117,7 @@ func (tApp TestApp) GetPriceFeedKeeper() pricefeedkeeper.Keeper { return tAp func (tApp TestApp) GetCommitteeKeeper() committeekeeper.Keeper { return tApp.committeeKeeper } func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } -func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } +func (tApp TestApp) GetFeeMarketKeeper() *feemarketkeeper.Keeper { return tApp.feeMarketKeeper } func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper } func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper } func (tApp TestApp) GetWrappedA0GIBaseKeeper() wrappeda0gibasekeeper.Keeper { diff --git a/app/upgrades_test.go b/app/upgrades_test.go index d4783904..9e88d52a 100644 --- a/app/upgrades_test.go +++ b/app/upgrades_test.go @@ -1,434 +1 @@ package app_test - -import ( - "strconv" - "testing" - "time" - - sdkmath "cosmossdk.io/math" - "github.com/0glabs/0g-chain/app" - evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" - precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper" - precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" -) - -func TestMigrateEvmutilToPrecisebank(t *testing.T) { - // Full test case with all components together - tests := []struct { - name string - initialReserve sdkmath.Int - fractionalBalances []sdkmath.Int - }{ - { - "no fractional balances", - sdkmath.NewInt(0), - []sdkmath.Int{}, - }, - { - "sufficient reserve, 0 remainder", - // Accounts adding up to 2 int units, same as reserve - sdkmath.NewInt(2), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "insufficient reserve, 0 remainder", - // Accounts adding up to 2 int units, but only 1 int unit in reserve - sdkmath.NewInt(1), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "excess reserve, 0 remainder", - // Accounts adding up to 2 int units, but 3 int unit in reserve - sdkmath.NewInt(3), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "sufficient reserve, non-zero remainder", - // Accounts adding up to 1.5 int units, same as reserve - sdkmath.NewInt(2), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "insufficient reserve, non-zero remainder", - // Accounts adding up to 1.5 int units, less than reserve, - // Reserve should be 2 and remainder 0.5 - sdkmath.NewInt(1), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "excess reserve, non-zero remainder", - // Accounts adding up to 1.5 int units, 3 int units in reserve - sdkmath.NewInt(3), - []sdkmath.Int{ - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tApp := app.NewTestApp() - tApp.InitializeFromGenesisStates() - ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) - - ak := tApp.GetAccountKeeper() - bk := tApp.GetBankKeeper() - evmuk := tApp.GetEvmutilKeeper() - pbk := tApp.GetPrecisebankKeeper() - - reserveCoin := sdk.NewCoin(precisebanktypes.IntegerCoinDenom, tt.initialReserve) - err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(reserveCoin)) - require.NoError(t, err) - - oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName) - newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName) - - // Double check balances - oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) - newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) - - require.Equal(t, tt.initialReserve, oldReserveBalance.Amount, "initial x/evmutil reserve balance") - require.True(t, newReserveBalance.IsZero(), "empty initial new reserve") - - // Set accounts - for i, balance := range tt.fractionalBalances { - addr := sdk.AccAddress([]byte(strconv.Itoa(i))) - - err := evmuk.SetBalance(ctx, addr, balance) - require.NoError(t, err) - } - - // Run full x/evmutil -> x/precisebank migration - err = app.MigrateEvmutilToPrecisebank( - ctx, - ak, - bk, - evmuk, - pbk, - ) - require.NoError(t, err) - - // Check old reserve is empty - oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) - require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty") - - // Check new reserve fully backs fractional balances - newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) - fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx) - remainder := pbk.GetRemainderAmount(ctx) - - expectedReserveBal := fractionalBalanceTotal.Add(remainder) - require.Equal( - t, - expectedReserveBal, - newReserveBalanceAfter.Amount.Mul(precisebanktypes.ConversionFactor()), - "new reserve should equal total fractional balances", - ) - - // Check balances are deleted in evmutil and migrated to precisebank - for i := range tt.fractionalBalances { - addr := sdk.AccAddress([]byte(strconv.Itoa(i))) - acc := evmuk.GetAccount(ctx, addr) - require.Nil(t, acc, "account should be deleted") - - balance := pbk.GetFractionalBalance(ctx, addr) - require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated") - } - - // Checks balances valid and remainder - res, stop := precisebankkeeper.AllInvariants(pbk)(ctx) - require.Falsef(t, stop, "invariants should pass: %s", res) - }) - } -} - -func TestTransferFractionalBalances(t *testing.T) { - tests := []struct { - name string - fractionalBalances []sdkmath.Int - }{ - { - "no fractional balances", - []sdkmath.Int{}, - }, - { - "balanced fractional balances", - []sdkmath.Int{ - // 4 accounts - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "unbalanced balances", - []sdkmath.Int{ - // 3 accounts - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tApp := app.NewTestApp() - tApp.InitializeFromGenesisStates() - ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) - - evmutilk := tApp.GetEvmutilKeeper() - pbk := tApp.GetPrecisebankKeeper() - - for i, balance := range tt.fractionalBalances { - addr := sdk.AccAddress([]byte(strconv.Itoa(i))) - - err := evmutilk.SetBalance(ctx, addr, balance) - require.NoError(t, err) - } - - // Run balance transfer - aggregateSum, err := app.TransferFractionalBalances( - ctx, - evmutilk, - pbk, - ) - require.NoError(t, err) - - // Check balances are deleted in evmutil and migrated to precisebank - sum := sdkmath.ZeroInt() - for i := range tt.fractionalBalances { - sum = sum.Add(tt.fractionalBalances[i]) - - addr := sdk.AccAddress([]byte(strconv.Itoa(i))) - acc := evmutilk.GetAccount(ctx, addr) - require.Nil(t, acc, "account should be deleted") - - balance := pbk.GetFractionalBalance(ctx, addr) - require.Equal(t, tt.fractionalBalances[i], balance, "balance should be migrated") - } - - require.Equal(t, sum, aggregateSum, "aggregate sum should be correct") - }) - } -} - -func TestInitializeRemainder(t *testing.T) { - tests := []struct { - name string - giveAggregateSum sdkmath.Int - wantRemainder sdkmath.Int - }{ - { - "0 remainder, 1ukava", - precisebanktypes.ConversionFactor(), - sdkmath.NewInt(0), - }, - { - "0 remainder, multiple ukava", - precisebanktypes.ConversionFactor().MulRaw(5), - sdkmath.NewInt(0), - }, - { - "non-zero remainder, min", - precisebanktypes.ConversionFactor().SubRaw(1), - sdkmath.NewInt(1), - }, - { - "non-zero remainder, max", - sdkmath.NewInt(1), - precisebanktypes.ConversionFactor().SubRaw(1), - }, - { - "non-zero remainder, half", - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tApp := app.NewTestApp() - tApp.InitializeFromGenesisStates() - - pbk := tApp.GetPrecisebankKeeper() - - ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) - - remainder := app.InitializeRemainder( - ctx, - tApp.GetPrecisebankKeeper(), - tt.giveAggregateSum, - ) - require.Equal(t, tt.wantRemainder, remainder) - - // Check actual state - remainderAfter := pbk.GetRemainderAmount(ctx) - require.Equal(t, tt.wantRemainder, remainderAfter) - - // Not checking invariants here since it requires actual balance state - aggregateSumWithRemainder := tt.giveAggregateSum.Add(remainder) - require.True( - t, - aggregateSumWithRemainder. - Mod(precisebanktypes.ConversionFactor()). - IsZero(), - "remainder + aggregate sum should be a multiple of the conversion factor", - ) - }) - } -} - -func TestTransferFractionalBalanceReserve(t *testing.T) { - tests := []struct { - name string - initialReserve sdk.Coin - fractionalBalances []sdkmath.Int - }{ - { - "balanced reserve, no remainder", - sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), - []sdkmath.Int{ - // 2 accounts - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "insufficient reserve", - sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), - []sdkmath.Int{ - // 4 accounts, total 2 int units - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "extra reserve funds", - sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(2)), - []sdkmath.Int{ - // 2 accounts, total 1 int units - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "insufficient reserve, with remainder", - sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(1)), - []sdkmath.Int{ - // 5 accounts, total 2.5 int units - // Expected 3 int units in reserve, 0.5 remainder - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - { - "extra reserve funds, with remainder", - sdk.NewCoin(precisebanktypes.IntegerCoinDenom, sdk.NewInt(3)), - []sdkmath.Int{ - // 3 accounts, total 1.5 int units. - // Expected 2 int units in reserve, 0.5 remainder - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - precisebanktypes.ConversionFactor().QuoRaw(2), - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tApp := app.NewTestApp() - tApp.InitializeFromGenesisStates() - ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: time.Now()}) - - bk := tApp.GetBankKeeper() - pbk := tApp.GetPrecisebankKeeper() - err := bk.MintCoins(ctx, evmutiltypes.ModuleName, sdk.NewCoins(tt.initialReserve)) - require.NoError(t, err) - - oldReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(evmutiltypes.ModuleName) - newReserveAddr := tApp.GetAccountKeeper().GetModuleAddress(precisebanktypes.ModuleName) - - // Double check balances - oldReserveBalance := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) - newReserveBalance := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) - - require.Equal(t, tt.initialReserve, oldReserveBalance) - require.True(t, newReserveBalance.IsZero(), "empty initial new reserve") - - for i, balance := range tt.fractionalBalances { - addr := sdk.AccAddress([]byte{byte(i)}) - - require.NotPanics(t, func() { - pbk.SetFractionalBalance(ctx, addr, balance) - }, "given fractional balances should be valid") - } - - // Run reserve migration - err = app.TransferFractionalBalanceReserve( - ctx, - tApp.GetAccountKeeper(), - bk, - tApp.GetPrecisebankKeeper(), - ) - require.NoError(t, err) - - // Check old reserve is empty - oldReserveBalanceAfter := bk.GetBalance(ctx, oldReserveAddr, precisebanktypes.IntegerCoinDenom) - require.True(t, oldReserveBalanceAfter.IsZero(), "old reserve should be empty") - - // Check new reserve fully backs fractional balances - newReserveBalanceAfter := bk.GetBalance(ctx, newReserveAddr, precisebanktypes.IntegerCoinDenom) - fractionalBalanceTotal := pbk.GetTotalSumFractionalBalances(ctx) - - expectedReserveBal := fractionalBalanceTotal. - Quo(precisebanktypes.ConversionFactor()) - - // Check if theres a remainder - if fractionalBalanceTotal.Mod(precisebanktypes.ConversionFactor()).IsPositive() { - expectedReserveBal = expectedReserveBal.Add(sdkmath.OneInt()) - } - - require.Equal( - t, - expectedReserveBal, - newReserveBalanceAfter.Amount, - "new reserve should equal total fractional balances + remainder", - ) - }) - } -} diff --git a/cmd/0gchaind/app.go b/cmd/0gchaind/app.go index f09ec847..d8d3d10b 100644 --- a/cmd/0gchaind/app.go +++ b/cmd/0gchaind/app.go @@ -126,8 +126,6 @@ func (ac appCreator) newApp( baseapp.SetMempool(mempool), ) bApp.SetTxEncoder(ac.encodingConfig.TxConfig.TxEncoder()) - abciProposalHandler := app.NewDefaultProposalHandler(mempool, bApp) - bApp.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) newApp := app.NewApp( homeDir, traceStore, ac.encodingConfig, @@ -142,6 +140,10 @@ func (ac appCreator) newApp( EVMMaxGasWanted: cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)), }, bApp, + func(k app.FeeMarketKeeper) sdk.PrepareProposalHandler { + abciProposalHandler := app.NewDefaultProposalHandler(mempool, bApp, k) + return abciProposalHandler.PrepareProposalHandler() + }, ) return newApp @@ -170,14 +172,14 @@ func (ac appCreator) appExport( var tempApp *app.App if height != -1 { bApp := app.NewBaseApp(logger, db, ac.encodingConfig) - tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp) + tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp, nil) if err := tempApp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { bApp := app.NewBaseApp(logger, db, ac.encodingConfig) - tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp) + tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp, nil) } return tempApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) } diff --git a/go.mod b/go.mod index f26169f0..e8ee335e 100644 --- a/go.mod +++ b/go.mod @@ -250,7 +250,7 @@ replace ( // TODO: Tag before release github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2 // Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support - github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.9 + github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.10 // See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 // Downgraded to avoid bugs in following commits which causes "version does not exist" errors diff --git a/go.sum b/go.sum index a56db589..f17c68f4 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,8 @@ github.com/0glabs/cometbft v0.37.9-0glabs.1 h1:KQJG17Y21suKP3QNICLto4b5Ak73XbSmK github.com/0glabs/cometbft v0.37.9-0glabs.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I= github.com/0glabs/cosmos-sdk v0.47.10-0glabs.10 h1:NJp0RwczHBO4EvrQdDxxftHOgUDBtNh7M/vpaG7wFtQ= github.com/0glabs/cosmos-sdk v0.47.10-0glabs.10/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog= -github.com/0glabs/ethermint v0.21.0-0g.v3.1.9 h1:oTHp7tSAqoML7D/+RXsBzA9DsbZ80MX93VJYjR/Akh4= -github.com/0glabs/ethermint v0.21.0-0g.v3.1.9/go.mod h1:6e/gOcDLhvlDWK3JLJVBgki0gD6H4E1eG7l9byocgWA= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.10 h1:DE8hK2OJp9rKYdT2Y0G259/6nAFcOQi383l2e7/VFnE= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.10/go.mod h1:6e/gOcDLhvlDWK3JLJVBgki0gD6H4E1eG7l9byocgWA= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=