mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 21:47:27 +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 ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"math/big" | ||||||
|  | 	"sort" | ||||||
| 
 | 
 | ||||||
| 	"github.com/cockroachdb/errors" | 	"github.com/cockroachdb/errors" | ||||||
| 	abci "github.com/cometbft/cometbft/abci/types" | 	abci "github.com/cometbft/cometbft/abci/types" | ||||||
| @ -13,6 +15,8 @@ import ( | |||||||
| 	"github.com/cosmos/cosmos-sdk/x/auth/signing" | 	"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | const gasPriceSuggestionBlockNum int64 = 5 | ||||||
|  | 
 | ||||||
| type ( | type ( | ||||||
| 	// GasTx defines the contract that a transaction with a gas limit must implement.
 | 	// GasTx defines the contract that a transaction with a gas limit must implement.
 | ||||||
| 	GasTx interface { | 	GasTx interface { | ||||||
| @ -30,17 +34,22 @@ type ( | |||||||
| 	// DefaultProposalHandler defines the default ABCI PrepareProposal and
 | 	// DefaultProposalHandler defines the default ABCI PrepareProposal and
 | ||||||
| 	// ProcessProposal handlers.
 | 	// ProcessProposal handlers.
 | ||||||
| 	DefaultProposalHandler struct { | 	DefaultProposalHandler struct { | ||||||
| 		mempool    mempool.Mempool | 		mempool         mempool.Mempool | ||||||
| 		txVerifier ProposalTxVerifier | 		txVerifier      ProposalTxVerifier | ||||||
| 		txSelector TxSelector | 		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{ | 	return &DefaultProposalHandler{ | ||||||
| 		mempool:    mp, | 		mempool:         mp, | ||||||
| 		txVerifier: txVerifier, | 		txVerifier:      txVerifier, | ||||||
| 		txSelector: NewDefaultTxSelector(), | 		txSelector:      NewDefaultTxSelector(), | ||||||
|  | 		feemarketKeeper: feemarketKeeper, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -97,11 +106,25 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan | |||||||
| 			return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} | 			return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		gasPriceSlice := make([]*big.Int, 0, h.mempool.CountTx()) | ||||||
|  | 
 | ||||||
| 		iterator := h.mempool.Select(ctx, req.Txs) | 		iterator := h.mempool.Select(ctx, req.Txs) | ||||||
| 		selectedTxsSignersSeqs := make(map[string]uint64) | 		selectedTxsSignersSeqs := make(map[string]uint64) | ||||||
| 		var selectedTxsNums int | 		var selectedTxsNums int | ||||||
| 		for iterator != nil { | 		for iterator != nil { | ||||||
| 			memTx := iterator.Tx() | 			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() | 			sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				panic(fmt.Errorf("failed to get signatures: %w", err)) | 				panic(fmt.Errorf("failed to get signatures: %w", err)) | ||||||
| @ -198,6 +221,28 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan | |||||||
| 
 | 
 | ||||||
| 			iterator = iterator.Next() | 			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()} | 		return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,13 +52,17 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 	tApp := app.TestApp{ | 	tApp := app.TestApp{ | ||||||
| 		App: *app.NewApp( | 		App: *app.NewApp( | ||||||
| 			log.NewNopLogger(), |  | ||||||
| 			tmdb.NewMemDB(), |  | ||||||
| 			chaincfg.DefaultNodeHome, | 			chaincfg.DefaultNodeHome, | ||||||
| 			nil, | 			nil, | ||||||
| 			encodingConfig, | 			encodingConfig, | ||||||
| 			opts, | 			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 | 	packetForwardKeeper   *packetforwardkeeper.Keeper | ||||||
| 	evmKeeper             *evmkeeper.Keeper | 	evmKeeper             *evmkeeper.Keeper | ||||||
| 	evmutilKeeper         evmutilkeeper.Keeper | 	evmutilKeeper         evmutilkeeper.Keeper | ||||||
| 	feeMarketKeeper       feemarketkeeper.Keeper | 	feeMarketKeeper       *feemarketkeeper.Keeper | ||||||
| 	upgradeKeeper         upgradekeeper.Keeper | 	upgradeKeeper         upgradekeeper.Keeper | ||||||
| 	evidenceKeeper        evidencekeeper.Keeper | 	evidenceKeeper        evidencekeeper.Keeper | ||||||
| 	transferKeeper        ibctransferkeeper.Keeper | 	transferKeeper        ibctransferkeeper.Keeper | ||||||
| @ -313,6 +313,7 @@ func NewApp( | |||||||
| 	encodingConfig chainparams.EncodingConfig, | 	encodingConfig chainparams.EncodingConfig, | ||||||
| 	options Options, | 	options Options, | ||||||
| 	bApp *baseapp.BaseApp, | 	bApp *baseapp.BaseApp, | ||||||
|  | 	setAbciProposalHandler func(feemarketKeeper FeeMarketKeeper) sdk.PrepareProposalHandler, | ||||||
| ) *App { | ) *App { | ||||||
| 	appCodec := encodingConfig.Marshaler | 	appCodec := encodingConfig.Marshaler | ||||||
| 	legacyAmino := encodingConfig.Amino | 	legacyAmino := encodingConfig.Amino | ||||||
| @ -901,6 +902,10 @@ func NewApp( | |||||||
| 	app.SetBeginBlocker(app.BeginBlocker) | 	app.SetBeginBlocker(app.BeginBlocker) | ||||||
| 	app.SetEndBlocker(app.EndBlocker) | 	app.SetEndBlocker(app.EndBlocker) | ||||||
| 
 | 
 | ||||||
|  | 	if setAbciProposalHandler != nil { | ||||||
|  | 		abciProposalHandler := setAbciProposalHandler(app.feeMarketKeeper) | ||||||
|  | 		bApp.SetPrepareProposal(abciProposalHandler) | ||||||
|  | 	} | ||||||
| 	// load store
 | 	// load store
 | ||||||
| 	if !options.SkipLoadLatest { | 	if !options.SkipLoadLatest { | ||||||
| 		if err := app.LoadLatestVersion(); err != nil { | 		if err := app.LoadLatestVersion(); err != nil { | ||||||
|  | |||||||
| @ -28,19 +28,36 @@ import ( | |||||||
| func TestNewApp(t *testing.T) { | func TestNewApp(t *testing.T) { | ||||||
| 	chaincfg.SetSDKConfig() | 	chaincfg.SetSDKConfig() | ||||||
| 	NewApp( | 	NewApp( | ||||||
| 		log.NewTMLogger(log.NewSyncWriter(os.Stdout)), |  | ||||||
| 		db.NewMemDB(), |  | ||||||
| 		chaincfg.DefaultNodeHome, | 		chaincfg.DefaultNodeHome, | ||||||
| 		nil, | 		nil, | ||||||
| 		MakeEncodingConfig(), | 		MakeEncodingConfig(), | ||||||
| 		DefaultOptions, | 		DefaultOptions, | ||||||
|  | 		NewBaseApp( | ||||||
|  | 			log.NewTMLogger(log.NewSyncWriter(os.Stdout)), | ||||||
|  | 			db.NewMemDB(), | ||||||
|  | 			MakeEncodingConfig(), | ||||||
|  | 			baseapp.SetChainID(TestChainId), | ||||||
|  | 		), | ||||||
|  | 		nil, | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestExport(t *testing.T) { | func TestExport(t *testing.T) { | ||||||
| 	chaincfg.SetSDKConfig() | 	chaincfg.SetSDKConfig() | ||||||
| 	db := db.NewMemDB() | 	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()) | 	genesisState := GenesisStateWithSingleValidator(&TestApp{App: *app}, NewDefaultGenesisState()) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -96,7 +96,7 @@ func NewTestAppFromSealed() TestApp { | |||||||
| 	bApp := NewBaseApp(log.NewNopLogger(), db, encCfg, baseapp.SetChainID(TestChainId)) | 	bApp := NewBaseApp(log.NewNopLogger(), db, encCfg, baseapp.SetChainID(TestChainId)) | ||||||
| 	app := NewApp( | 	app := NewApp( | ||||||
| 		chaincfg.DefaultNodeHome, nil, | 		chaincfg.DefaultNodeHome, nil, | ||||||
| 		encCfg, DefaultOptions, bApp, | 		encCfg, DefaultOptions, bApp, nil, | ||||||
| 	) | 	) | ||||||
| 	return TestApp{App: *app} | 	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) GetCommitteeKeeper() committeekeeper.Keeper     { return tApp.committeeKeeper } | ||||||
| func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper         { return tApp.evmutilKeeper } | func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper         { return tApp.evmutilKeeper } | ||||||
| func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper                { return tApp.evmKeeper } | 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) GetDASignersKeeper() dasignerskeeper.Keeper     { return tApp.dasignersKeeper } | ||||||
| func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper } | func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper } | ||||||
| func (tApp TestApp) GetWrappedA0GIBaseKeeper() wrappeda0gibasekeeper.Keeper { | func (tApp TestApp) GetWrappedA0GIBaseKeeper() wrappeda0gibasekeeper.Keeper { | ||||||
|  | |||||||
| @ -1,434 +1 @@ | |||||||
| package app_test | 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), | 		baseapp.SetMempool(mempool), | ||||||
| 	) | 	) | ||||||
| 	bApp.SetTxEncoder(ac.encodingConfig.TxConfig.TxEncoder()) | 	bApp.SetTxEncoder(ac.encodingConfig.TxConfig.TxEncoder()) | ||||||
| 	abciProposalHandler := app.NewDefaultProposalHandler(mempool, bApp) |  | ||||||
| 	bApp.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) |  | ||||||
| 
 | 
 | ||||||
| 	newApp := app.NewApp( | 	newApp := app.NewApp( | ||||||
| 		homeDir, traceStore, ac.encodingConfig, | 		homeDir, traceStore, ac.encodingConfig, | ||||||
| @ -142,6 +140,10 @@ func (ac appCreator) newApp( | |||||||
| 			EVMMaxGasWanted:       cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)), | 			EVMMaxGasWanted:       cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)), | ||||||
| 		}, | 		}, | ||||||
| 		bApp, | 		bApp, | ||||||
|  | 		func(k app.FeeMarketKeeper) sdk.PrepareProposalHandler { | ||||||
|  | 			abciProposalHandler := app.NewDefaultProposalHandler(mempool, bApp, k) | ||||||
|  | 			return abciProposalHandler.PrepareProposalHandler() | ||||||
|  | 		}, | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	return newApp | 	return newApp | ||||||
| @ -170,14 +172,14 @@ func (ac appCreator) appExport( | |||||||
| 	var tempApp *app.App | 	var tempApp *app.App | ||||||
| 	if height != -1 { | 	if height != -1 { | ||||||
| 		bApp := app.NewBaseApp(logger, db, ac.encodingConfig) | 		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 { | 		if err := tempApp.LoadHeight(height); err != nil { | ||||||
| 			return servertypes.ExportedApp{}, err | 			return servertypes.ExportedApp{}, err | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		bApp := app.NewBaseApp(logger, db, ac.encodingConfig) | 		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) | 	return tempApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Solovyov1796
						Solovyov1796