mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-04-04 15:55:23 +00:00 
			
		
		
		
	feat: Use x/precisebank for x/evm keeper (#1960)
Replace x/evmutil EvmBankKeeper usage for x/evm
This commit is contained in:
		
							parent
							
								
									9de9de671e
								
							
						
					
					
						commit
						d2d661276e
					
				| @ -550,7 +550,6 @@ func NewApp( | |||||||
| 		app.accountKeeper, | 		app.accountKeeper, | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	// TODO: Pass this to evmkeeper.NewKeeper() instead of evmutilKeeper
 |  | ||||||
| 	app.precisebankKeeper = precisebankkeeper.NewKeeper( | 	app.precisebankKeeper = precisebankkeeper.NewKeeper( | ||||||
| 		app.appCodec, | 		app.appCodec, | ||||||
| 		keys[precisebanktypes.StoreKey], | 		keys[precisebanktypes.StoreKey], | ||||||
| @ -558,11 +557,13 @@ func NewApp( | |||||||
| 		app.accountKeeper, | 		app.accountKeeper, | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) |  | ||||||
| 	app.evmKeeper = evmkeeper.NewKeeper( | 	app.evmKeeper = evmkeeper.NewKeeper( | ||||||
| 		appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], | 		appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], | ||||||
| 		govAuthAddr, | 		govAuthAddr, | ||||||
| 		app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, | 		app.accountKeeper, | ||||||
|  | 		app.precisebankKeeper, // x/precisebank in place of x/bank
 | ||||||
|  | 		app.stakingKeeper, | ||||||
|  | 		app.feeMarketKeeper, | ||||||
| 		nil, // precompiled contracts
 | 		nil, // precompiled contracts
 | ||||||
| 		geth.NewEVM, | 		geth.NewEVM, | ||||||
| 		options.EVMTrace, | 		options.EVMTrace, | ||||||
|  | |||||||
| @ -1,281 +0,0 @@ | |||||||
| package keeper |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 
 |  | ||||||
| 	errorsmod "cosmossdk.io/errors" |  | ||||||
| 	sdkmath "cosmossdk.io/math" |  | ||||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" |  | ||||||
| 	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" |  | ||||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" |  | ||||||
| 
 |  | ||||||
| 	"github.com/kava-labs/kava/x/evmutil/types" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	// EvmDenom is the gas denom used by the evm
 |  | ||||||
| 	EvmDenom = "akava" |  | ||||||
| 
 |  | ||||||
| 	// CosmosDenom is the gas denom used by the kava app
 |  | ||||||
| 	CosmosDenom = "ukava" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // ConversionMultiplier is the conversion multiplier between akava and ukava
 |  | ||||||
| var ConversionMultiplier = sdkmath.NewInt(1_000_000_000_000) |  | ||||||
| 
 |  | ||||||
| var _ evmtypes.BankKeeper = EvmBankKeeper{} |  | ||||||
| 
 |  | ||||||
| // EvmBankKeeper is a BankKeeper wrapper for the x/evm module to allow the use
 |  | ||||||
| // of the 18 decimal akava coin on the evm.
 |  | ||||||
| // x/evm consumes gas and send coins by minting and burning akava coins in its module
 |  | ||||||
| // account and then sending the funds to the target account.
 |  | ||||||
| // This keeper uses both the ukava coin and a separate akava balance to manage the
 |  | ||||||
| // extra precision needed by the evm.
 |  | ||||||
| type EvmBankKeeper struct { |  | ||||||
| 	akavaKeeper Keeper |  | ||||||
| 	bk          types.BankKeeper |  | ||||||
| 	ak          types.AccountKeeper |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func NewEvmBankKeeper(akavaKeeper Keeper, bk types.BankKeeper, ak types.AccountKeeper) EvmBankKeeper { |  | ||||||
| 	return EvmBankKeeper{ |  | ||||||
| 		akavaKeeper: akavaKeeper, |  | ||||||
| 		bk:          bk, |  | ||||||
| 		ak:          ak, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetBalance returns the total **spendable** balance of akava for a given account by address.
 |  | ||||||
| func (k EvmBankKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { |  | ||||||
| 	if denom != EvmDenom { |  | ||||||
| 		panic(fmt.Errorf("only evm denom %s is supported by EvmBankKeeper", EvmDenom)) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	spendableCoins := k.bk.SpendableCoins(ctx, addr) |  | ||||||
| 	ukava := spendableCoins.AmountOf(CosmosDenom) |  | ||||||
| 	akava := k.akavaKeeper.GetBalance(ctx, addr) |  | ||||||
| 	total := ukava.Mul(ConversionMultiplier).Add(akava) |  | ||||||
| 	return sdk.NewCoin(EvmDenom, total) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SendCoins transfers akava coins from a AccAddress to an AccAddress.
 |  | ||||||
| func (k EvmBankKeeper) SendCoins(ctx sdk.Context, senderAddr sdk.AccAddress, recipientAddr sdk.AccAddress, amt sdk.Coins) error { |  | ||||||
| 	// SendCoins method is not used by the evm module, but is required by the
 |  | ||||||
| 	// evmtypes.BankKeeper interface. This must be updated if the evm module
 |  | ||||||
| 	// is updated to use SendCoins.
 |  | ||||||
| 	panic("not implemented") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SendCoinsFromModuleToAccount transfers akava coins from a ModuleAccount to an AccAddress.
 |  | ||||||
| // It will panic if the module account does not exist. An error is returned if the recipient
 |  | ||||||
| // address is black-listed or if sending the tokens fails.
 |  | ||||||
| func (k EvmBankKeeper) SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error { |  | ||||||
| 	ukava, akava, err := SplitAkavaCoins(amt) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if ukava.Amount.IsPositive() { |  | ||||||
| 		if err := k.bk.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, sdk.NewCoins(ukava)); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	senderAddr := k.GetModuleAddress(senderModule) |  | ||||||
| 	if err := k.ConvertOneUkavaToAkavaIfNeeded(ctx, senderAddr, akava); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := k.akavaKeeper.SendBalance(ctx, senderAddr, recipientAddr, akava); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return k.ConvertAkavaToUkava(ctx, recipientAddr) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SendCoinsFromAccountToModule transfers akava coins from an AccAddress to a ModuleAccount.
 |  | ||||||
| // It will panic if the module account does not exist.
 |  | ||||||
| func (k EvmBankKeeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { |  | ||||||
| 	ukava, akavaNeeded, err := SplitAkavaCoins(amt) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if ukava.IsPositive() { |  | ||||||
| 		if err := k.bk.SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, sdk.NewCoins(ukava)); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := k.ConvertOneUkavaToAkavaIfNeeded(ctx, senderAddr, akavaNeeded); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	recipientAddr := k.GetModuleAddress(recipientModule) |  | ||||||
| 	if err := k.akavaKeeper.SendBalance(ctx, senderAddr, recipientAddr, akavaNeeded); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return k.ConvertAkavaToUkava(ctx, recipientAddr) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // MintCoins mints akava coins by minting the equivalent ukava coins and any remaining akava coins.
 |  | ||||||
| // It will panic if the module account does not exist or is unauthorized.
 |  | ||||||
| func (k EvmBankKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { |  | ||||||
| 	ukava, akava, err := SplitAkavaCoins(amt) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if ukava.IsPositive() { |  | ||||||
| 		if err := k.bk.MintCoins(ctx, moduleName, sdk.NewCoins(ukava)); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	recipientAddr := k.GetModuleAddress(moduleName) |  | ||||||
| 	if err := k.akavaKeeper.AddBalance(ctx, recipientAddr, akava); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return k.ConvertAkavaToUkava(ctx, recipientAddr) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // BurnCoins burns akava coins by burning the equivalent ukava coins and any remaining akava coins.
 |  | ||||||
| // It will panic if the module account does not exist or is unauthorized.
 |  | ||||||
| func (k EvmBankKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { |  | ||||||
| 	ukava, akava, err := SplitAkavaCoins(amt) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if ukava.IsPositive() { |  | ||||||
| 		if err := k.bk.BurnCoins(ctx, moduleName, sdk.NewCoins(ukava)); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	moduleAddr := k.GetModuleAddress(moduleName) |  | ||||||
| 	if err := k.ConvertOneUkavaToAkavaIfNeeded(ctx, moduleAddr, akava); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return k.akavaKeeper.RemoveBalance(ctx, moduleAddr, akava) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsSendEnabledCoins checks the coins provided and returns an ErrSendDisabled
 |  | ||||||
| // if any of the coins are not configured for sending. Returns nil if sending is
 |  | ||||||
| // enabled for all provided coins.
 |  | ||||||
| func (k EvmBankKeeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error { |  | ||||||
| 	// IsSendEnabledCoins method is not used by the evm module, but is required by the
 |  | ||||||
| 	// evmtypes.BankKeeper interface. This must be updated if the evm module
 |  | ||||||
| 	// is updated to use IsSendEnabledCoins.
 |  | ||||||
| 	panic("not implemented") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ConvertOneUkavaToAkavaIfNeeded converts 1 ukava to akava for an address if
 |  | ||||||
| // its akava balance is smaller than the akavaNeeded amount.
 |  | ||||||
| func (k EvmBankKeeper) ConvertOneUkavaToAkavaIfNeeded(ctx sdk.Context, addr sdk.AccAddress, akavaNeeded sdkmath.Int) error { |  | ||||||
| 	akavaBal := k.akavaKeeper.GetBalance(ctx, addr) |  | ||||||
| 	if akavaBal.GTE(akavaNeeded) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ukavaToStore := sdk.NewCoins(sdk.NewCoin(CosmosDenom, sdk.OneInt())) |  | ||||||
| 	if err := k.bk.SendCoinsFromAccountToModule(ctx, addr, types.ModuleName, ukavaToStore); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// add 1ukava equivalent of akava to addr
 |  | ||||||
| 	akavaToReceive := ConversionMultiplier |  | ||||||
| 	if err := k.akavaKeeper.AddBalance(ctx, addr, akavaToReceive); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ConvertAkavaToUkava converts all available akava to ukava for a given AccAddress.
 |  | ||||||
| func (k EvmBankKeeper) ConvertAkavaToUkava(ctx sdk.Context, addr sdk.AccAddress) error { |  | ||||||
| 	totalAkava := k.akavaKeeper.GetBalance(ctx, addr) |  | ||||||
| 	ukava, _, err := SplitAkavaCoins(sdk.NewCoins(sdk.NewCoin(EvmDenom, totalAkava))) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// do nothing if account does not have enough akava for a single ukava
 |  | ||||||
| 	ukavaToReceive := ukava.Amount |  | ||||||
| 	if !ukavaToReceive.IsPositive() { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// remove akava used for converting to ukava
 |  | ||||||
| 	akavaToBurn := ukavaToReceive.Mul(ConversionMultiplier) |  | ||||||
| 	finalBal := totalAkava.Sub(akavaToBurn) |  | ||||||
| 	if err := k.akavaKeeper.SetBalance(ctx, addr, finalBal); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	fromAddr := k.GetModuleAddress(types.ModuleName) |  | ||||||
| 	if err := k.bk.SendCoins(ctx, fromAddr, addr, sdk.NewCoins(ukava)); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (k EvmBankKeeper) GetModuleAddress(moduleName string) sdk.AccAddress { |  | ||||||
| 	addr := k.ak.GetModuleAddress(moduleName) |  | ||||||
| 	if addr == nil { |  | ||||||
| 		panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) |  | ||||||
| 	} |  | ||||||
| 	return addr |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SplitAkavaCoins splits akava coins to the equivalent ukava coins and any remaining akava balance.
 |  | ||||||
| // An error will be returned if the coins are not valid or if the coins are not the akava denom.
 |  | ||||||
| func SplitAkavaCoins(coins sdk.Coins) (sdk.Coin, sdkmath.Int, error) { |  | ||||||
| 	akava := sdk.ZeroInt() |  | ||||||
| 	ukava := sdk.NewCoin(CosmosDenom, sdk.ZeroInt()) |  | ||||||
| 
 |  | ||||||
| 	if len(coins) == 0 { |  | ||||||
| 		return ukava, akava, nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := ValidateEvmCoins(coins); err != nil { |  | ||||||
| 		return ukava, akava, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// note: we should always have len(coins) == 1 here since coins cannot have dup denoms after we validate.
 |  | ||||||
| 	coin := coins[0] |  | ||||||
| 	remainingBalance := coin.Amount.Mod(ConversionMultiplier) |  | ||||||
| 	if remainingBalance.IsPositive() { |  | ||||||
| 		akava = remainingBalance |  | ||||||
| 	} |  | ||||||
| 	ukavaAmount := coin.Amount.Quo(ConversionMultiplier) |  | ||||||
| 	if ukavaAmount.IsPositive() { |  | ||||||
| 		ukava = sdk.NewCoin(CosmosDenom, ukavaAmount) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return ukava, akava, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ValidateEvmCoins validates the coins from evm is valid and is the EvmDenom (akava).
 |  | ||||||
| func ValidateEvmCoins(coins sdk.Coins) error { |  | ||||||
| 	if len(coins) == 0 { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// validate that coins are non-negative, sorted, and no dup denoms
 |  | ||||||
| 	if err := coins.Validate(); err != nil { |  | ||||||
| 		return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, coins.String()) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// validate that coin denom is akava
 |  | ||||||
| 	if len(coins) != 1 || coins[0].Denom != EvmDenom { |  | ||||||
| 		errMsg := fmt.Sprintf("invalid evm coin denom, only %s is supported", EvmDenom) |  | ||||||
| 		return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, errMsg) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @ -1,798 +0,0 @@ | |||||||
| package keeper_test |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"testing" |  | ||||||
| 	"time" |  | ||||||
| 
 |  | ||||||
| 	sdkmath "cosmossdk.io/math" |  | ||||||
| 	tmtime "github.com/cometbft/cometbft/types/time" |  | ||||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" |  | ||||||
| 	"github.com/stretchr/testify/suite" |  | ||||||
| 
 |  | ||||||
| 	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" |  | ||||||
| 	vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" |  | ||||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" |  | ||||||
| 
 |  | ||||||
| 	"github.com/kava-labs/kava/x/evmutil/keeper" |  | ||||||
| 	"github.com/kava-labs/kava/x/evmutil/testutil" |  | ||||||
| 	"github.com/kava-labs/kava/x/evmutil/types" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type evmBankKeeperTestSuite struct { |  | ||||||
| 	testutil.Suite |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) SetupTest() { |  | ||||||
| 	suite.Suite.SetupTest() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestGetBalance_ReturnsSpendable() { |  | ||||||
| 	startingCoins := sdk.NewCoins(sdk.NewInt64Coin("ukava", 10)) |  | ||||||
| 	startingAkava := sdkmath.NewInt(100) |  | ||||||
| 
 |  | ||||||
| 	now := tmtime.Now() |  | ||||||
| 	endTime := now.Add(24 * time.Hour) |  | ||||||
| 	bacc := authtypes.NewBaseAccountWithAddress(suite.Addrs[0]) |  | ||||||
| 	vacc := vesting.NewContinuousVestingAccount(bacc, startingCoins, now.Unix(), endTime.Unix()) |  | ||||||
| 	suite.AccountKeeper.SetAccount(suite.Ctx, vacc) |  | ||||||
| 
 |  | ||||||
| 	err := suite.App.FundAccount(suite.Ctx, suite.Addrs[0], startingCoins) |  | ||||||
| 	suite.Require().NoError(err) |  | ||||||
| 	err = suite.Keeper.SetBalance(suite.Ctx, suite.Addrs[0], startingAkava) |  | ||||||
| 	suite.Require().NoError(err) |  | ||||||
| 
 |  | ||||||
| 	coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "akava") |  | ||||||
| 	suite.Require().Equal(startingAkava, coin.Amount) |  | ||||||
| 
 |  | ||||||
| 	ctx := suite.Ctx.WithBlockTime(now.Add(12 * time.Hour)) |  | ||||||
| 	coin = suite.EvmBankKeeper.GetBalance(ctx, suite.Addrs[0], "akava") |  | ||||||
| 	suite.Require().Equal(sdkmath.NewIntFromUint64(5_000_000_000_100), coin.Amount) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestGetBalance_NotEvmDenom() { |  | ||||||
| 	suite.Require().Panics(func() { |  | ||||||
| 		suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "ukava") |  | ||||||
| 	}) |  | ||||||
| 	suite.Require().Panics(func() { |  | ||||||
| 		suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "busd") |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestGetBalance() { |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name           string |  | ||||||
| 		startingAmount sdk.Coins |  | ||||||
| 		expAmount      sdkmath.Int |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"ukava with akava", |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 100), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 10), |  | ||||||
| 			), |  | ||||||
| 			sdkmath.NewInt(10_000_000_000_100), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"just akava", |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 100), |  | ||||||
| 				sdk.NewInt64Coin("busd", 100), |  | ||||||
| 			), |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"just ukava", |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("ukava", 10), |  | ||||||
| 				sdk.NewInt64Coin("busd", 100), |  | ||||||
| 			), |  | ||||||
| 			sdkmath.NewInt(10_000_000_000_000), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"no ukava or akava", |  | ||||||
| 			sdk.NewCoins(), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"with avaka that is more than 1 ukava", |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 20_000_000_000_220), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 11), |  | ||||||
| 			), |  | ||||||
| 			sdkmath.NewInt(31_000_000_000_220), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 
 |  | ||||||
| 			suite.FundAccountWithKava(suite.Addrs[0], tt.startingAmount) |  | ||||||
| 			coin := suite.EvmBankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "akava") |  | ||||||
| 			suite.Require().Equal(tt.expAmount, coin.Amount) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestSendCoinsFromModuleToAccount() { |  | ||||||
| 	startingModuleCoins := sdk.NewCoins( |  | ||||||
| 		sdk.NewInt64Coin("akava", 200), |  | ||||||
| 		sdk.NewInt64Coin("ukava", 100), |  | ||||||
| 	) |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name           string |  | ||||||
| 		sendCoins      sdk.Coins |  | ||||||
| 		startingAccBal sdk.Coins |  | ||||||
| 		expAccBal      sdk.Coins |  | ||||||
| 		hasErr         bool |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"send more than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_000_000_000_010)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 10), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 12), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send less than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 122)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 122), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 0), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send an exact amount of ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 98_000_000_000_000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 0o0), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 98), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send no akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 0)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 0), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 0), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if sending other coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 500), sdk.NewInt64Coin("busd", 1000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough total akava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_001_000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough ukava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200_000_000_000_000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts receiver's akava to ukava if there's enough akava after the transfer", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 99_000_000_000_200)), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 999_999_999_900), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 1), |  | ||||||
| 			), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 100), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 101), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts all of receiver's akava to ukava even if somehow receiver has more than 1ukava of akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_000_000_000_100)), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 5_999_999_999_990), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 1), |  | ||||||
| 			), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 90), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 19), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"swap 1 ukava for akava if module account doesn't have enough akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 99_000_000_001_000)), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 200), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 1), |  | ||||||
| 			), |  | ||||||
| 			sdk.NewCoins( |  | ||||||
| 				sdk.NewInt64Coin("akava", 1200), |  | ||||||
| 				sdk.NewInt64Coin("ukava", 100), |  | ||||||
| 			), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 
 |  | ||||||
| 			suite.FundAccountWithKava(suite.Addrs[0], tt.startingAccBal) |  | ||||||
| 			suite.FundModuleAccountWithKava(evmtypes.ModuleName, startingModuleCoins) |  | ||||||
| 
 |  | ||||||
| 			// fund our module with some ukava to account for converting extra akava back to ukava
 |  | ||||||
| 			suite.FundModuleAccountWithKava(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin("ukava", 10))) |  | ||||||
| 
 |  | ||||||
| 			err := suite.EvmBankKeeper.SendCoinsFromModuleToAccount(suite.Ctx, evmtypes.ModuleName, suite.Addrs[0], tt.sendCoins) |  | ||||||
| 			if tt.hasErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 				return |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// check ukava
 |  | ||||||
| 			ukavaSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expAccBal.AmountOf("ukava").Int64(), ukavaSender.Amount.Int64()) |  | ||||||
| 
 |  | ||||||
| 			// check akava
 |  | ||||||
| 			actualAkava := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) |  | ||||||
| 			suite.Require().Equal(tt.expAccBal.AmountOf("akava").Int64(), actualAkava.Int64()) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestSendCoinsFromAccountToModule() { |  | ||||||
| 	startingAccCoins := sdk.NewCoins( |  | ||||||
| 		sdk.NewInt64Coin("akava", 200), |  | ||||||
| 		sdk.NewInt64Coin("ukava", 100), |  | ||||||
| 	) |  | ||||||
| 	startingModuleCoins := sdk.NewCoins( |  | ||||||
| 		sdk.NewInt64Coin("akava", 100_000_000_000), |  | ||||||
| 	) |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name           string |  | ||||||
| 		sendCoins      sdk.Coins |  | ||||||
| 		expSenderCoins sdk.Coins |  | ||||||
| 		expModuleCoins sdk.Coins |  | ||||||
| 		hasErr         bool |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"send more than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_000_000_000_010)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 190), sdk.NewInt64Coin("ukava", 88)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_010), sdk.NewInt64Coin("ukava", 12)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send less than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 122)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 78), sdk.NewInt64Coin("ukava", 100)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_122), sdk.NewInt64Coin("ukava", 0)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send an exact amount of ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 98_000_000_000_000)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200), sdk.NewInt64Coin("ukava", 2)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_000), sdk.NewInt64Coin("ukava", 98)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"send no akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 0)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200), sdk.NewInt64Coin("ukava", 100)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_000), sdk.NewInt64Coin("ukava", 0)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if sending other coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 500), sdk.NewInt64Coin("busd", 1000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if have dup coins", |  | ||||||
| 			sdk.Coins{ |  | ||||||
| 				sdk.NewInt64Coin("akava", 12_000_000_000_000), |  | ||||||
| 				sdk.NewInt64Coin("akava", 2_000_000_000_000), |  | ||||||
| 			}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough total akava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_001_000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough ukava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200_000_000_000_000)), |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			sdk.Coins{}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts 1 ukava to akava if not enough akava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 99_001_000_000_000)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 999_000_000_200), sdk.NewInt64Coin("ukava", 0)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 101_000_000_000), sdk.NewInt64Coin("ukava", 99)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts receiver's akava to ukava if there's enough akava after the transfer", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 5_900_000_000_200)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_000_000_000), sdk.NewInt64Coin("ukava", 94)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200), sdk.NewInt64Coin("ukava", 6)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 			suite.FundAccountWithKava(suite.Addrs[0], startingAccCoins) |  | ||||||
| 			suite.FundModuleAccountWithKava(evmtypes.ModuleName, startingModuleCoins) |  | ||||||
| 
 |  | ||||||
| 			err := suite.EvmBankKeeper.SendCoinsFromAccountToModule(suite.Ctx, suite.Addrs[0], evmtypes.ModuleName, tt.sendCoins) |  | ||||||
| 			if tt.hasErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 				return |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// check sender balance
 |  | ||||||
| 			ukavaSender := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expSenderCoins.AmountOf("ukava").Int64(), ukavaSender.Amount.Int64()) |  | ||||||
| 			actualAkava := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) |  | ||||||
| 			suite.Require().Equal(tt.expSenderCoins.AmountOf("akava").Int64(), actualAkava.Int64()) |  | ||||||
| 
 |  | ||||||
| 			// check module balance
 |  | ||||||
| 			moduleAddr := suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) |  | ||||||
| 			ukavaSender = suite.BankKeeper.GetBalance(suite.Ctx, moduleAddr, "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expModuleCoins.AmountOf("ukava").Int64(), ukavaSender.Amount.Int64()) |  | ||||||
| 			actualAkava = suite.Keeper.GetBalance(suite.Ctx, moduleAddr) |  | ||||||
| 			suite.Require().Equal(tt.expModuleCoins.AmountOf("akava").Int64(), actualAkava.Int64()) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestBurnCoins() { |  | ||||||
| 	startingUkava := sdkmath.NewInt(100) |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name       string |  | ||||||
| 		burnCoins  sdk.Coins |  | ||||||
| 		expUkava   sdkmath.Int |  | ||||||
| 		expAkava   sdkmath.Int |  | ||||||
| 		hasErr     bool |  | ||||||
| 		akavaStart sdkmath.Int |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"burn more than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_021_000_000_002)), |  | ||||||
| 			sdkmath.NewInt(88), |  | ||||||
| 			sdkmath.NewInt(100_000_000_000), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(121_000_000_002), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"burn less than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 122)), |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 			sdkmath.NewInt(878), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(1000), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"burn an exact amount of ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 98_000_000_000_000)), |  | ||||||
| 			sdkmath.NewInt(2), |  | ||||||
| 			sdkmath.NewInt(10), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(10), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"burn no akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 0)), |  | ||||||
| 			startingUkava, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			false, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if burning other coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 500), sdk.NewInt64Coin("busd", 1000)), |  | ||||||
| 			startingUkava, |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 			true, |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if have dup coins", |  | ||||||
| 			sdk.Coins{ |  | ||||||
| 				sdk.NewInt64Coin("akava", 12_000_000_000_000), |  | ||||||
| 				sdk.NewInt64Coin("akava", 2_000_000_000_000), |  | ||||||
| 			}, |  | ||||||
| 			startingUkava, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			true, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if burn amount is negative", |  | ||||||
| 			sdk.Coins{sdk.Coin{Denom: "akava", Amount: sdkmath.NewInt(-100)}}, |  | ||||||
| 			startingUkava, |  | ||||||
| 			sdkmath.NewInt(50), |  | ||||||
| 			true, |  | ||||||
| 			sdkmath.NewInt(50), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough akava to cover burn", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100_999_000_000_000)), |  | ||||||
| 			sdkmath.NewInt(0), |  | ||||||
| 			sdkmath.NewInt(99_000_000_000), |  | ||||||
| 			true, |  | ||||||
| 			sdkmath.NewInt(99_000_000_000), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if not enough ukava to cover burn", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 200_000_000_000_000)), |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			true, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts 1 ukava to akava if not enough akava to cover", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_021_000_000_002)), |  | ||||||
| 			sdkmath.NewInt(87), |  | ||||||
| 			sdkmath.NewInt(980_000_000_000), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(1_000_000_002), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 			startingCoins := sdk.NewCoins( |  | ||||||
| 				sdk.NewCoin("ukava", startingUkava), |  | ||||||
| 				sdk.NewCoin("akava", tt.akavaStart), |  | ||||||
| 			) |  | ||||||
| 			suite.FundModuleAccountWithKava(evmtypes.ModuleName, startingCoins) |  | ||||||
| 
 |  | ||||||
| 			err := suite.EvmBankKeeper.BurnCoins(suite.Ctx, evmtypes.ModuleName, tt.burnCoins) |  | ||||||
| 			if tt.hasErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 				return |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// check ukava
 |  | ||||||
| 			ukavaActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expUkava, ukavaActual.Amount) |  | ||||||
| 
 |  | ||||||
| 			// check akava
 |  | ||||||
| 			akavaActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr) |  | ||||||
| 			suite.Require().Equal(tt.expAkava, akavaActual) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestMintCoins() { |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name       string |  | ||||||
| 		mintCoins  sdk.Coins |  | ||||||
| 		ukava      sdkmath.Int |  | ||||||
| 		akava      sdkmath.Int |  | ||||||
| 		hasErr     bool |  | ||||||
| 		akavaStart sdkmath.Int |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"mint more than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_021_000_000_002)), |  | ||||||
| 			sdkmath.NewInt(12), |  | ||||||
| 			sdkmath.NewInt(21_000_000_002), |  | ||||||
| 			false, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"mint less than 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 901_000_000_001)), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			sdkmath.NewInt(901_000_000_001), |  | ||||||
| 			false, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"mint an exact amount of ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 123_000_000_000_000_000)), |  | ||||||
| 			sdkmath.NewInt(123_000), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			false, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"mint no akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 0)), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			false, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if minting other coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 500), sdk.NewInt64Coin("busd", 1000)), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 			true, |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if have dup coins", |  | ||||||
| 			sdk.Coins{ |  | ||||||
| 				sdk.NewInt64Coin("akava", 12_000_000_000_000), |  | ||||||
| 				sdk.NewInt64Coin("akava", 2_000_000_000_000), |  | ||||||
| 			}, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			true, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"errors if mint amount is negative", |  | ||||||
| 			sdk.Coins{sdk.Coin{Denom: "akava", Amount: sdkmath.NewInt(-100)}}, |  | ||||||
| 			sdk.ZeroInt(), |  | ||||||
| 			sdkmath.NewInt(50), |  | ||||||
| 			true, |  | ||||||
| 			sdkmath.NewInt(50), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"adds to existing akava balance", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 12_021_000_000_002)), |  | ||||||
| 			sdkmath.NewInt(12), |  | ||||||
| 			sdkmath.NewInt(21_000_000_102), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(100), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"convert akava balance to ukava if it exceeds 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 10_999_000_000_000)), |  | ||||||
| 			sdkmath.NewInt(12), |  | ||||||
| 			sdkmath.NewInt(1_200_000_001), |  | ||||||
| 			false, |  | ||||||
| 			sdkmath.NewInt(1_002_200_000_001), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 			suite.FundModuleAccountWithKava(types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin("ukava", 10))) |  | ||||||
| 			suite.FundModuleAccountWithKava(evmtypes.ModuleName, sdk.NewCoins(sdk.NewCoin("akava", tt.akavaStart))) |  | ||||||
| 
 |  | ||||||
| 			err := suite.EvmBankKeeper.MintCoins(suite.Ctx, evmtypes.ModuleName, tt.mintCoins) |  | ||||||
| 			if tt.hasErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 				return |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// check ukava
 |  | ||||||
| 			ukavaActual := suite.BankKeeper.GetBalance(suite.Ctx, suite.EvmModuleAddr, "ukava") |  | ||||||
| 			suite.Require().Equal(tt.ukava, ukavaActual.Amount) |  | ||||||
| 
 |  | ||||||
| 			// check akava
 |  | ||||||
| 			akavaActual := suite.Keeper.GetBalance(suite.Ctx, suite.EvmModuleAddr) |  | ||||||
| 			suite.Require().Equal(tt.akava, akavaActual) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestValidateEvmCoins() { |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name      string |  | ||||||
| 		coins     sdk.Coins |  | ||||||
| 		shouldErr bool |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"valid coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 500)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"dup coins", |  | ||||||
| 			sdk.Coins{sdk.NewInt64Coin("akava", 500), sdk.NewInt64Coin("akava", 500)}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"not evm coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 500)), |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"negative coins", |  | ||||||
| 			sdk.Coins{sdk.Coin{Denom: "akava", Amount: sdkmath.NewInt(-500)}}, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			err := keeper.ValidateEvmCoins(tt.coins) |  | ||||||
| 			if tt.shouldErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestConvertOneUkavaToAkavaIfNeeded() { |  | ||||||
| 	akavaNeeded := sdkmath.NewInt(200) |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name          string |  | ||||||
| 		startingCoins sdk.Coins |  | ||||||
| 		expectedCoins sdk.Coins |  | ||||||
| 		success       bool |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"not enough ukava for conversion", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts 1 ukava to akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 10), sdk.NewInt64Coin("akava", 100)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 9), sdk.NewInt64Coin("akava", 1_000_000_000_100)), |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"conversion not needed", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 10), sdk.NewInt64Coin("akava", 200)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 10), sdk.NewInt64Coin("akava", 200)), |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 
 |  | ||||||
| 			suite.FundAccountWithKava(suite.Addrs[0], tt.startingCoins) |  | ||||||
| 			err := suite.EvmBankKeeper.ConvertOneUkavaToAkavaIfNeeded(suite.Ctx, suite.Addrs[0], akavaNeeded) |  | ||||||
| 			moduleKava := suite.BankKeeper.GetBalance(suite.Ctx, suite.AccountKeeper.GetModuleAddress(types.ModuleName), "ukava") |  | ||||||
| 			if tt.success { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 				if tt.startingCoins.AmountOf("akava").LT(akavaNeeded) { |  | ||||||
| 					suite.Require().Equal(sdk.OneInt(), moduleKava.Amount) |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 				suite.Require().Equal(sdk.ZeroInt(), moduleKava.Amount) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			akava := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) |  | ||||||
| 			suite.Require().Equal(tt.expectedCoins.AmountOf("akava"), akava) |  | ||||||
| 			ukava := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expectedCoins.AmountOf("ukava"), ukava.Amount) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestConvertAkavaToUkava() { |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name          string |  | ||||||
| 		startingCoins sdk.Coins |  | ||||||
| 		expectedCoins sdk.Coins |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"not enough ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 100), sdk.NewInt64Coin("ukava", 0)), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts akava for 1 ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 10), sdk.NewInt64Coin("akava", 1_000_000_000_003)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 11), sdk.NewInt64Coin("akava", 3)), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"converts more than 1 ukava of akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 10), sdk.NewInt64Coin("akava", 8_000_000_000_123)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 18), sdk.NewInt64Coin("akava", 123)), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			suite.SetupTest() |  | ||||||
| 
 |  | ||||||
| 			err := suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, sdk.NewCoins(sdk.NewInt64Coin("ukava", 10))) |  | ||||||
| 			suite.Require().NoError(err) |  | ||||||
| 			suite.FundAccountWithKava(suite.Addrs[0], tt.startingCoins) |  | ||||||
| 			err = suite.EvmBankKeeper.ConvertAkavaToUkava(suite.Ctx, suite.Addrs[0]) |  | ||||||
| 			suite.Require().NoError(err) |  | ||||||
| 			akava := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]) |  | ||||||
| 			suite.Require().Equal(tt.expectedCoins.AmountOf("akava"), akava) |  | ||||||
| 			ukava := suite.BankKeeper.GetBalance(suite.Ctx, suite.Addrs[0], "ukava") |  | ||||||
| 			suite.Require().Equal(tt.expectedCoins.AmountOf("ukava"), ukava.Amount) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *evmBankKeeperTestSuite) TestSplitAkavaCoins() { |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name          string |  | ||||||
| 		coins         sdk.Coins |  | ||||||
| 		expectedCoins sdk.Coins |  | ||||||
| 		shouldErr     bool |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			"invalid coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 500)), |  | ||||||
| 			nil, |  | ||||||
| 			true, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"empty coins", |  | ||||||
| 			sdk.NewCoins(), |  | ||||||
| 			sdk.NewCoins(), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"ukava & akava coins", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 8_000_000_000_123)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 8), sdk.NewInt64Coin("akava", 123)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"only akava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 10_123)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 10_123)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"only ukava", |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("akava", 5_000_000_000_000)), |  | ||||||
| 			sdk.NewCoins(sdk.NewInt64Coin("ukava", 5)), |  | ||||||
| 			false, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		suite.Run(tt.name, func() { |  | ||||||
| 			ukava, akava, err := keeper.SplitAkavaCoins(tt.coins) |  | ||||||
| 			if tt.shouldErr { |  | ||||||
| 				suite.Require().Error(err) |  | ||||||
| 			} else { |  | ||||||
| 				suite.Require().NoError(err) |  | ||||||
| 				suite.Require().Equal(tt.expectedCoins.AmountOf("ukava"), ukava.Amount) |  | ||||||
| 				suite.Require().Equal(tt.expectedCoins.AmountOf("akava"), akava) |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestEvmBankKeeperTestSuite(t *testing.T) { |  | ||||||
| 	suite.Run(t, new(evmBankKeeperTestSuite)) |  | ||||||
| } |  | ||||||
| @ -11,8 +11,6 @@ import ( | |||||||
| 
 | 
 | ||||||
| // RegisterInvariants registers the swap module invariants
 | // RegisterInvariants registers the swap module invariants
 | ||||||
| func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) { | func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keeper) { | ||||||
| 	ir.RegisterRoute(types.ModuleName, "fully-backed", FullyBackedInvariant(bankK, k)) |  | ||||||
| 	ir.RegisterRoute(types.ModuleName, "small-balances", SmallBalancesInvariant(bankK, k)) |  | ||||||
| 	ir.RegisterRoute(types.ModuleName, "cosmos-coins-fully-backed", CosmosCoinsFullyBackedInvariant(bankK, k)) | 	ir.RegisterRoute(types.ModuleName, "cosmos-coins-fully-backed", CosmosCoinsFullyBackedInvariant(bankK, k)) | ||||||
| 	// Disable this invariant due to some issues with it requiring some staking params to be set in genesis.
 | 	// Disable this invariant due to some issues with it requiring some staking params to be set in genesis.
 | ||||||
| 	// ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k))
 | 	// ir.RegisterRoute(types.ModuleName, "backed-conversion-coins", BackedCoinsInvariant(bankK, k))
 | ||||||
| @ -21,57 +19,11 @@ func RegisterInvariants(ir sdk.InvariantRegistry, bankK types.BankKeeper, k Keep | |||||||
| // AllInvariants runs all invariants of the swap module
 | // AllInvariants runs all invariants of the swap module
 | ||||||
| func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant { | func AllInvariants(bankK types.BankKeeper, k Keeper) sdk.Invariant { | ||||||
| 	return func(ctx sdk.Context) (string, bool) { | 	return func(ctx sdk.Context) (string, bool) { | ||||||
| 		if res, stop := FullyBackedInvariant(bankK, k)(ctx); stop { |  | ||||||
| 			return res, stop |  | ||||||
| 		} |  | ||||||
| 		if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop { | 		if res, stop := BackedCoinsInvariant(bankK, k)(ctx); stop { | ||||||
| 			return res, stop | 			return res, stop | ||||||
| 		} | 		} | ||||||
| 		if res, stop := CosmosCoinsFullyBackedInvariant(bankK, k)(ctx); stop { |  | ||||||
| 			return res, stop |  | ||||||
| 		} |  | ||||||
| 		return SmallBalancesInvariant(bankK, k)(ctx) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // FullyBackedInvariant ensures all minor balances are backed by the coins in the module account.
 | 		return CosmosCoinsFullyBackedInvariant(bankK, k)(ctx) | ||||||
| //
 |  | ||||||
| // The module balance can be greater than the sum of all minor balances. This can happen in rare cases
 |  | ||||||
| // where the evm module burns tokens.
 |  | ||||||
| func FullyBackedInvariant(bankK types.BankKeeper, k Keeper) sdk.Invariant { |  | ||||||
| 	broken := false |  | ||||||
| 	message := sdk.FormatInvariant(types.ModuleName, "fully backed broken", "sum of minor balances greater than module account") |  | ||||||
| 
 |  | ||||||
| 	return func(ctx sdk.Context) (string, bool) { |  | ||||||
| 		totalMinorBalances := sdk.ZeroInt() |  | ||||||
| 		k.IterateAllAccounts(ctx, func(acc types.Account) bool { |  | ||||||
| 			totalMinorBalances = totalMinorBalances.Add(acc.Balance) |  | ||||||
| 			return false |  | ||||||
| 		}) |  | ||||||
| 
 |  | ||||||
| 		bankAddr := authtypes.NewModuleAddress(types.ModuleName) |  | ||||||
| 		bankBalance := bankK.GetBalance(ctx, bankAddr, CosmosDenom).Amount.Mul(ConversionMultiplier) |  | ||||||
| 
 |  | ||||||
| 		broken = totalMinorBalances.GT(bankBalance) |  | ||||||
| 
 |  | ||||||
| 		return message, broken |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SmallBalancesInvariant ensures all minor balances are less than the overflow amount, beyond this they should be converted to the major denom.
 |  | ||||||
| func SmallBalancesInvariant(_ types.BankKeeper, k Keeper) sdk.Invariant { |  | ||||||
| 	broken := false |  | ||||||
| 	message := sdk.FormatInvariant(types.ModuleName, "small balances broken", "minor balances not all less than overflow") |  | ||||||
| 
 |  | ||||||
| 	return func(ctx sdk.Context) (string, bool) { |  | ||||||
| 		k.IterateAllAccounts(ctx, func(account types.Account) bool { |  | ||||||
| 			if account.Balance.GTE(ConversionMultiplier) { |  | ||||||
| 				broken = true |  | ||||||
| 				return true |  | ||||||
| 			} |  | ||||||
| 			return false |  | ||||||
| 		}) |  | ||||||
| 		return message, broken |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ func (suite *invariantTestSuite) SetupValidState() { | |||||||
| 	for i := 0; i < 4; i++ { | 	for i := 0; i < 4; i++ { | ||||||
| 		suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount( | 		suite.Keeper.SetAccount(suite.Ctx, *types.NewAccount( | ||||||
| 			suite.Addrs[i], | 			suite.Addrs[i], | ||||||
| 			keeper.ConversionMultiplier.QuoRaw(2), | 			sdkmath.NewInt(10000000000), | ||||||
| 		)) | 		)) | ||||||
| 	} | 	} | ||||||
| 	suite.FundModuleAccountWithKava( | 	suite.FundModuleAccountWithKava( | ||||||
| @ -131,45 +131,6 @@ func (suite *invariantTestSuite) runInvariant(route string, invariant func(bankK | |||||||
| 	return dMessage, dBroken | 	return dMessage, dBroken | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *invariantTestSuite) TestFullyBackedInvariant() { |  | ||||||
| 	// default state is valid
 |  | ||||||
| 	_, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) |  | ||||||
| 	suite.Equal(false, broken) |  | ||||||
| 
 |  | ||||||
| 	suite.SetupValidState() |  | ||||||
| 	_, broken = suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) |  | ||||||
| 	suite.Equal(false, broken) |  | ||||||
| 
 |  | ||||||
| 	// break invariant by increasing total minor balances above module balance
 |  | ||||||
| 	suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], sdk.OneInt()) |  | ||||||
| 
 |  | ||||||
| 	message, broken := suite.runInvariant("fully-backed", keeper.FullyBackedInvariant) |  | ||||||
| 	suite.Equal("evmutil: fully backed broken invariant\nsum of minor balances greater than module account\n", message) |  | ||||||
| 	suite.Equal(true, broken) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (suite *invariantTestSuite) TestSmallBalances() { |  | ||||||
| 	// default state is valid
 |  | ||||||
| 	_, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) |  | ||||||
| 	suite.Equal(false, broken) |  | ||||||
| 
 |  | ||||||
| 	suite.SetupValidState() |  | ||||||
| 	_, broken = suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) |  | ||||||
| 	suite.Equal(false, broken) |  | ||||||
| 
 |  | ||||||
| 	// increase minor balance at least above conversion multiplier
 |  | ||||||
| 	suite.Keeper.AddBalance(suite.Ctx, suite.Addrs[0], keeper.ConversionMultiplier) |  | ||||||
| 	// add same number of ukava to avoid breaking other invariants
 |  | ||||||
| 	amt := sdk.NewCoins(sdk.NewInt64Coin(keeper.CosmosDenom, 1)) |  | ||||||
| 	suite.Require().NoError( |  | ||||||
| 		suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, amt), |  | ||||||
| 	) |  | ||||||
| 
 |  | ||||||
| 	message, broken := suite.runInvariant("small-balances", keeper.SmallBalancesInvariant) |  | ||||||
| 	suite.Equal("evmutil: small balances broken invariant\nminor balances not all less than overflow\n", message) |  | ||||||
| 	suite.Equal(true, broken) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // the cosmos-coins-fully-backed invariant depends on 1-to-1 mapping of module balance to erc20s
 | // the cosmos-coins-fully-backed invariant depends on 1-to-1 mapping of module balance to erc20s
 | ||||||
| // if coins can be sent directly to the module account, this assumption is broken.
 | // if coins can be sent directly to the module account, this assumption is broken.
 | ||||||
| // this test verifies that coins cannot be directly sent to the module account.
 | // this test verifies that coins cannot be directly sent to the module account.
 | ||||||
|  | |||||||
| @ -50,7 +50,6 @@ type Suite struct { | |||||||
| 	BankKeeper     bankkeeper.Keeper | 	BankKeeper     bankkeeper.Keeper | ||||||
| 	AccountKeeper  authkeeper.AccountKeeper | 	AccountKeeper  authkeeper.AccountKeeper | ||||||
| 	Keeper         keeper.Keeper | 	Keeper         keeper.Keeper | ||||||
| 	EvmBankKeeper  keeper.EvmBankKeeper |  | ||||||
| 	Addrs          []sdk.AccAddress | 	Addrs          []sdk.AccAddress | ||||||
| 	EvmModuleAddr  sdk.AccAddress | 	EvmModuleAddr  sdk.AccAddress | ||||||
| 	QueryClient    types.QueryClient | 	QueryClient    types.QueryClient | ||||||
| @ -68,7 +67,6 @@ func (suite *Suite) SetupTest() { | |||||||
| 	suite.BankKeeper = tApp.GetBankKeeper() | 	suite.BankKeeper = tApp.GetBankKeeper() | ||||||
| 	suite.AccountKeeper = tApp.GetAccountKeeper() | 	suite.AccountKeeper = tApp.GetAccountKeeper() | ||||||
| 	suite.Keeper = tApp.GetEvmutilKeeper() | 	suite.Keeper = tApp.GetEvmutilKeeper() | ||||||
| 	suite.EvmBankKeeper = keeper.NewEvmBankKeeper(tApp.GetEvmutilKeeper(), suite.BankKeeper, suite.AccountKeeper) |  | ||||||
| 	suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) | 	suite.EvmModuleAddr = suite.AccountKeeper.GetModuleAddress(evmtypes.ModuleName) | ||||||
| 
 | 
 | ||||||
| 	// test evm user keys that have no minting permissions
 | 	// test evm user keys that have no minting permissions
 | ||||||
|  | |||||||
| @ -19,7 +19,11 @@ type AccountKeeper interface { | |||||||
| 
 | 
 | ||||||
| // BankKeeper defines the expected bank keeper interface
 | // BankKeeper defines the expected bank keeper interface
 | ||||||
| type BankKeeper interface { | type BankKeeper interface { | ||||||
| 	evmtypes.BankKeeper | 	GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin | ||||||
|  | 	SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error | ||||||
|  | 	SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error | ||||||
|  | 	MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error | ||||||
|  | 	BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error | ||||||
| 
 | 
 | ||||||
| 	GetSupply(ctx sdk.Context, denom string) sdk.Coin | 	GetSupply(ctx sdk.Context, denom string) sdk.Coin | ||||||
| 	SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins | 	SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 drklee3
						drklee3