diff --git a/app/upgrades.go b/app/upgrades.go index cf486d04..067bcf73 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -3,21 +3,16 @@ package app import ( "fmt" - sdkmath "cosmossdk.io/math" - - evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" - 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" + wrappeda0gibasetypes "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) const ( - UpgradeName_Testnet = "v0.4.0" + UpgradeName_Testnet = "v0.5.0" ) // RegisterUpgradeHandlers registers the upgrade handlers for the app. @@ -37,7 +32,7 @@ func (app App) RegisterUpgradeHandlers() { if doUpgrade && !app.upgradeKeeper.IsSkipHeight(upgradeInfo.Height) { storeUpgrades := storetypes.StoreUpgrades{ Added: []string{ - precisebanktypes.ModuleName, + wrappeda0gibasetypes.ModuleName, }, } @@ -65,204 +60,12 @@ func upgradeHandler( return nil, err } + app.mintKeeper.InitGenesis(ctx, app.accountKeeper, &minttypes.GenesisState{ + BondDenom: "ua0gi", + }) + logger.Info("completed store migrations") - // Migration of fractional balances from x/evmutil to x/precisebank - if err := MigrateEvmutilToPrecisebank( - ctx, - app.accountKeeper, - app.bankKeeper, - app.evmutilKeeper, - app.precisebankKeeper, - ); err != nil { - return nil, err - } - - logger.Info("completed x/evmutil to x/precisebank migration") - return versionMap, nil } } - -// MigrateEvmutilToPrecisebank migrates all required state from x/evmutil to -// x/precisebank and ensures the resulting state is correct. -// This migrates the following state: -// - Fractional balances -// - Fractional balance reserve -// Initializes the following state in x/precisebank: -// - Remainder amount -func MigrateEvmutilToPrecisebank( - ctx sdk.Context, - accountKeeper evmutiltypes.AccountKeeper, - bankKeeper bankkeeper.Keeper, - evmutilKeeper evmutilkeeper.Keeper, - precisebankKeeper precisebankkeeper.Keeper, -) error { - logger := ctx.Logger() - - aggregateSum, err := TransferFractionalBalances( - ctx, - evmutilKeeper, - precisebankKeeper, - ) - if err != nil { - return fmt.Errorf("fractional balances transfer: %w", err) - } - logger.Info( - "fractional balances transferred from x/evmutil to x/precisebank", - "aggregate sum", aggregateSum, - ) - - remainder := InitializeRemainder(ctx, precisebankKeeper, aggregateSum) - logger.Info("remainder amount initialized in x/precisebank", "remainder", remainder) - - // Migrate fractional balances, reserve, and ensure reserve fully backs all - // fractional balances. - if err := TransferFractionalBalanceReserve( - ctx, - accountKeeper, - bankKeeper, - precisebankKeeper, - ); err != nil { - return fmt.Errorf("reserve transfer: %w", err) - } - - return nil -} - -// TransferFractionalBalances migrates fractional balances from x/evmutil to -// x/precisebank. It sets the fractional balance in x/precisebank and deletes -// the account from x/evmutil. Returns the aggregate sum of all fractional -// balances. -func TransferFractionalBalances( - ctx sdk.Context, - evmutilKeeper evmutilkeeper.Keeper, - precisebankKeeper precisebankkeeper.Keeper, -) (sdkmath.Int, error) { - aggregateSum := sdkmath.ZeroInt() - - var iterErr error - - evmutilKeeper.IterateAllAccounts(ctx, func(acc evmutiltypes.Account) bool { - // Set account balance in x/precisebank - precisebankKeeper.SetFractionalBalance(ctx, acc.Address, acc.Balance) - - // Delete account from x/evmutil - iterErr := evmutilKeeper.SetAccount(ctx, evmutiltypes.Account{ - Address: acc.Address, - // Set balance to 0 to delete it - Balance: sdkmath.ZeroInt(), - }) - - // Halt iteration if there was an error - if iterErr != nil { - return true - } - - // Aggregate sum of all fractional balances - aggregateSum = aggregateSum.Add(acc.Balance) - - // Continue iterating - return false - }) - - return aggregateSum, iterErr -} - -// InitializeRemainder initializes the remainder amount in x/precisebank. It -// calculates the remainder amount that is needed to ensure that the sum of all -// fractional balances is a multiple of the conversion factor. The remainder -// amount is stored in the store and returned. -func InitializeRemainder( - ctx sdk.Context, - precisebankKeeper precisebankkeeper.Keeper, - aggregateSum sdkmath.Int, -) sdkmath.Int { - // Extra fractional coins that exceed the conversion factor. - // This extra + remainder should equal the conversion factor to ensure - // (sum(fBalances) + remainder) % conversionFactor = 0 - extraFractionalAmount := aggregateSum.Mod(precisebanktypes.ConversionFactor()) - remainder := precisebanktypes.ConversionFactor(). - Sub(extraFractionalAmount). - // Mod conversion factor to ensure remainder is valid. - // If extraFractionalAmount is a multiple of conversion factor, the - // remainder is 0. - Mod(precisebanktypes.ConversionFactor()) - - // Panics if the remainder is invalid. In a correct chain state and only - // mint/burns due to transfers, this would be 0. - precisebankKeeper.SetRemainderAmount(ctx, remainder) - - return remainder -} - -// TransferFractionalBalanceReserve migrates the fractional balance reserve from -// x/evmutil to x/precisebank. It transfers the reserve balance from x/evmutil -// to x/precisebank and ensures that the reserve fully backs all fractional -// balances. It mints or burns coins to back the fractional balances exactly. -func TransferFractionalBalanceReserve( - ctx sdk.Context, - accountKeeper evmutiltypes.AccountKeeper, - bankKeeper bankkeeper.Keeper, - precisebankKeeper precisebankkeeper.Keeper, -) error { - logger := ctx.Logger() - - // Transfer x/evmutil reserve to x/precisebank. - evmutilAddr := accountKeeper.GetModuleAddress(evmutiltypes.ModuleName) - reserveBalance := bankKeeper.GetBalance(ctx, evmutilAddr, precisebanktypes.IntegerCoinDenom) - - if err := bankKeeper.SendCoinsFromModuleToModule( - ctx, - evmutiltypes.ModuleName, // from x/evmutil - precisebanktypes.ModuleName, // to x/precisebank - sdk.NewCoins(reserveBalance), - ); err != nil { - return fmt.Errorf("failed to transfer reserve from x/evmutil to x/precisebank: %w", err) - } - - logger.Info(fmt.Sprintf("transferred reserve balance: %s", reserveBalance)) - - // Ensure x/precisebank reserve fully backs all fractional balances. - totalFractionalBalances := precisebankKeeper.GetTotalSumFractionalBalances(ctx) - - // Does NOT ensure state is correct, total fractional balances should be a - // multiple of conversion factor but is not guaranteed due to the remainder. - // Remainder initialization is handled by InitializeRemainder. - - // Determine how much the reserve is off by, e.g. unbacked amount - expectedReserveBalance := totalFractionalBalances.Quo(precisebanktypes.ConversionFactor()) - - // If there is a remainder (totalFractionalBalances % conversionFactor != 0), - // then expectedReserveBalance is rounded up to the nearest integer. - if totalFractionalBalances.Mod(precisebanktypes.ConversionFactor()).IsPositive() { - expectedReserveBalance = expectedReserveBalance.Add(sdkmath.OneInt()) - } - - unbackedAmount := expectedReserveBalance.Sub(reserveBalance.Amount) - logger.Info(fmt.Sprintf("total account fractional balances: %s", totalFractionalBalances)) - - // Three possible cases: - // 1. Reserve is not enough, mint coins to back the fractional balances - // 2. Reserve is too much, burn coins to back the fractional balances exactly - // 3. Reserve is exactly enough, no action needed - if unbackedAmount.IsPositive() { - coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount)) - if err := bankKeeper.MintCoins(ctx, precisebanktypes.ModuleName, coins); err != nil { - return fmt.Errorf("failed to mint extra reserve coins: %w", err) - } - - logger.Info(fmt.Sprintf("unbacked amount minted to reserve: %s", unbackedAmount)) - } else if unbackedAmount.IsNegative() { - coins := sdk.NewCoins(sdk.NewCoin(precisebanktypes.IntegerCoinDenom, unbackedAmount.Neg())) - if err := bankKeeper.BurnCoins(ctx, precisebanktypes.ModuleName, coins); err != nil { - return fmt.Errorf("failed to burn extra reserve coins: %w", err) - } - - logger.Info(fmt.Sprintf("extra reserve amount burned: %s", unbackedAmount.Neg())) - } else { - logger.Info("reserve exactly backs fractional balances, no mint/burn needed") - } - - return nil -} diff --git a/go.mod b/go.mod index 4fd1eac0..f26169f0 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( cosmossdk.io/simapp v0.0.0-20231127212628-044ff4d8c015 github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51 github.com/cenkalti/backoff/v4 v4.1.3 + github.com/cockroachdb/errors v1.11.1 github.com/cometbft/cometbft v0.37.9 github.com/cometbft/cometbft-db v0.9.1 github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 @@ -28,6 +29,7 @@ require ( github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/huandu/skiplist v1.2.0 github.com/linxGnu/grocksdb v1.8.13 github.com/pelletier/go-toml/v2 v2.1.0 github.com/shopspring/decimal v1.4.0 @@ -76,7 +78,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect @@ -146,7 +147,6 @@ require ( github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.1 // indirect - github.com/huandu/skiplist v1.2.0 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iancoleman/orderedmap v0.2.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect @@ -242,7 +242,7 @@ replace ( github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2 // Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support // github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.46.11-kava.3 - github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.9 + github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.10 github.com/cosmos/iavl => github.com/kava-labs/iavl v1.2.0-kava.1 // See https://github.com/cosmos/cosmos-sdk/pull/13093 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index a59d63a5..a56db589 100644 --- a/go.sum +++ b/go.sum @@ -211,8 +211,10 @@ git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFN git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= github.com/0glabs/cometbft v0.37.9-0glabs.1 h1:KQJG17Y21suKP3QNICLto4b5Ak73XbSmKxeLbg0ZM68= github.com/0glabs/cometbft v0.37.9-0glabs.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I= -github.com/0glabs/ethermint v0.21.0-0g.v3.1.8 h1:/jxCtO5B8amXgGZ0MWcoIH32PmoU9Z+WfPxA8nLaZI8= -github.com/0glabs/ethermint v0.21.0-0g.v3.1.8/go.mod h1:1GrxH8zkhO/x8sinIxaFtolK50spzSAZISbdP1MDLy8= +github.com/0glabs/cosmos-sdk v0.47.10-0glabs.10 h1:NJp0RwczHBO4EvrQdDxxftHOgUDBtNh7M/vpaG7wFtQ= +github.com/0glabs/cosmos-sdk v0.47.10-0glabs.10/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.9 h1:oTHp7tSAqoML7D/+RXsBzA9DsbZ80MX93VJYjR/Akh4= +github.com/0glabs/ethermint v0.21.0-0g.v3.1.9/go.mod h1:6e/gOcDLhvlDWK3JLJVBgki0gD6H4E1eG7l9byocgWA= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=