mirror of
https://github.com/0glabs/0g-chain.git
synced 2025-02-23 12:36:45 +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