mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 14:27:40 +00:00 
			
		
		
		
	generate suggestion gas price during prepare proposal and pass it to ethermint via fee market keeper
This commit is contained in:
		
							parent
							
								
									e6b13d85a1
								
							
						
					
					
						commit
						ec7e0c3163
					
				| @ -2,6 +2,8 @@ package app | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"sort" | ||||
| 
 | ||||
| 	"github.com/cockroachdb/errors" | ||||
| 	abci "github.com/cometbft/cometbft/abci/types" | ||||
| @ -13,6 +15,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 +34,22 @@ 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) | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| 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 +106,25 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan | ||||
| 			return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} | ||||
| 		} | ||||
| 
 | ||||
| 		gasPriceSlice := make([]*big.Int, 0, h.mempool.CountTx()) | ||||
| 
 | ||||
| 		iterator := h.mempool.Select(ctx, req.Txs) | ||||
| 		selectedTxsSignersSeqs := make(map[string]uint64) | ||||
| 		var selectedTxsNums int | ||||
| 		for iterator != nil { | ||||
| 			memTx := iterator.Tx() | ||||
| 
 | ||||
| 			for _, msg := range memTx.GetMsgs() { | ||||
| 				msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) | ||||
| 				if ok { | ||||
| 					txData, err := evmtypes.UnpackTxData(msgEthTx.Data) | ||||
| 					if err == nil { | ||||
| 						gp := txData.GetGasPrice() | ||||
| 						gasPriceSlice = append(gasPriceSlice, gp) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2() | ||||
| 			if err != nil { | ||||
| 				panic(fmt.Errorf("failed to get signatures: %w", err)) | ||||
| @ -198,6 +221,28 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan | ||||
| 
 | ||||
| 			iterator = iterator.Next() | ||||
| 		} | ||||
| 
 | ||||
| 		sort.Slice(gasPriceSlice, func(i, j int) bool { | ||||
| 			return gasPriceSlice[i].Cmp(gasPriceSlice[j]) > 0 | ||||
| 		}) | ||||
| 
 | ||||
| 		remaing := gasPriceSuggestionBlockNum * int64(maxBlockGas) | ||||
| 		for _, gp := range gasPriceSlice { | ||||
| 			if remaing <= 0 { | ||||
| 				h.feemarketKeeper.SetSuggestionGasPrice(ctx, gp) | ||||
| 				break | ||||
| 			} | ||||
| 			remaing -= gp.Int64() | ||||
| 		} | ||||
| 
 | ||||
| 		if remaing > 0 { | ||||
| 			if len(gasPriceSlice) > 0 { | ||||
| 				h.feemarketKeeper.SetSuggestionGasPrice(ctx, gasPriceSlice[len(gasPriceSlice)-1]) | ||||
| 			} else { | ||||
| 				h.feemarketKeeper.SetSuggestionGasPrice(ctx, big.NewInt(0)) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -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, | ||||
| 		), | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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()) | ||||
| 
 | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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", | ||||
| 			) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -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) | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Solovyov1796
						Solovyov1796