mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 23:17:27 +00:00 
			
		
		
		
	 528be6350e
			
		
	
	
		528be6350e
		
			
		
	
	
	
	
		
			
			* add IterateAllDeployedCosmosCoinContracts method * refactor unpacking big int from erc20 query * add QueryERC20TotalSupply method * feat(evmutil): add CosmosCoinsFullyBackedInvariant * update changelog
		
			
				
	
	
		
			440 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			440 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package keeper_test
 | |
| 
 | |
| import (
 | |
| 	"testing"
 | |
| 
 | |
| 	sdkmath "cosmossdk.io/math"
 | |
| 	sdk "github.com/cosmos/cosmos-sdk/types"
 | |
| 	"github.com/stretchr/testify/suite"
 | |
| 
 | |
| 	"github.com/kava-labs/kava/x/evmutil/testutil"
 | |
| 	"github.com/kava-labs/kava/x/evmutil/types"
 | |
| )
 | |
| 
 | |
| type keeperTestSuite struct {
 | |
| 	testutil.Suite
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) SetupTest() {
 | |
| 	suite.Suite.SetupTest()
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestGetAllAccounts() {
 | |
| 	tests := []struct {
 | |
| 		name        string
 | |
| 		expAccounts []types.Account
 | |
| 	}{
 | |
| 		{
 | |
| 			"no accounts",
 | |
| 			[]types.Account{},
 | |
| 		},
 | |
| 		{
 | |
| 			"with accounts",
 | |
| 			[]types.Account{
 | |
| 				{Address: suite.Addrs[0], Balance: sdkmath.NewInt(100)},
 | |
| 				{Address: suite.Addrs[1], Balance: sdkmath.NewInt(200)},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			for _, account := range tt.expAccounts {
 | |
| 				suite.Keeper.SetBalance(suite.Ctx, account.Address, account.Balance)
 | |
| 			}
 | |
| 
 | |
| 			accounts := suite.Suite.Keeper.GetAllAccounts(suite.Ctx)
 | |
| 			if len(tt.expAccounts) == 0 {
 | |
| 				suite.Require().Len(tt.expAccounts, 0)
 | |
| 			} else {
 | |
| 				suite.Require().Equal(tt.expAccounts, accounts)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestSetAccount_ZeroBalance() {
 | |
| 	existingAccount := types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdkmath.NewInt(100),
 | |
| 	}
 | |
| 	err := suite.Keeper.SetAccount(suite.Ctx, existingAccount)
 | |
| 	suite.Require().NoError(err)
 | |
| 	err = suite.Keeper.SetAccount(suite.Ctx, types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdk.ZeroInt(),
 | |
| 	})
 | |
| 	suite.Require().NoError(err)
 | |
| 	bal := suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0])
 | |
| 	suite.Require().Equal(sdk.ZeroInt(), bal)
 | |
| 	expAcct := suite.Keeper.GetAccount(suite.Ctx, suite.Addrs[0])
 | |
| 	suite.Require().Nil(expAcct)
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestSetAccount() {
 | |
| 	existingAccount := types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdkmath.NewInt(100),
 | |
| 	}
 | |
| 	tests := []struct {
 | |
| 		name    string
 | |
| 		account types.Account
 | |
| 		success bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"invalid address",
 | |
| 			types.Account{Address: nil, Balance: sdkmath.NewInt(100)},
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"invalid balance",
 | |
| 			types.Account{Address: suite.Addrs[0], Balance: sdkmath.NewInt(-100)},
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"empty account",
 | |
| 			types.Account{},
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"valid account",
 | |
| 			types.Account{Address: suite.Addrs[1], Balance: sdkmath.NewInt(100)},
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"replaces account",
 | |
| 			types.Account{Address: suite.Addrs[0], Balance: sdkmath.NewInt(50)},
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			err := suite.Keeper.SetAccount(suite.Ctx, existingAccount)
 | |
| 			suite.Require().NoError(err)
 | |
| 			err = suite.Keeper.SetAccount(suite.Ctx, tt.account)
 | |
| 			if tt.success {
 | |
| 				suite.Require().NoError(err)
 | |
| 				expAcct := suite.Keeper.GetAccount(suite.Ctx, tt.account.Address)
 | |
| 				suite.Require().Equal(tt.account, *expAcct)
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 				suite.Require().Nil(suite.Keeper.GetAccount(suite.Ctx, suite.Addrs[1]))
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestSendBalance() {
 | |
| 	startingSenderBal := sdkmath.NewInt(100)
 | |
| 	startingRecipientBal := sdkmath.NewInt(50)
 | |
| 	tests := []struct {
 | |
| 		name            string
 | |
| 		amt             sdkmath.Int
 | |
| 		expSenderBal    sdkmath.Int
 | |
| 		expRecipientBal sdkmath.Int
 | |
| 		success         bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"fails when sending negative amount",
 | |
| 			sdkmath.NewInt(-5),
 | |
| 			sdk.ZeroInt(),
 | |
| 			sdk.ZeroInt(),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"send zero amount",
 | |
| 			sdk.ZeroInt(),
 | |
| 			startingSenderBal,
 | |
| 			startingRecipientBal,
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"fails when sender does not have enough balance",
 | |
| 			sdkmath.NewInt(101),
 | |
| 			sdk.ZeroInt(),
 | |
| 			sdk.ZeroInt(),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"send valid amount",
 | |
| 			sdkmath.NewInt(80),
 | |
| 			sdkmath.NewInt(20),
 | |
| 			sdkmath.NewInt(130),
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			err := suite.Keeper.SetBalance(suite.Ctx, suite.Addrs[0], startingSenderBal)
 | |
| 			suite.Require().NoError(err)
 | |
| 			err = suite.Keeper.SetBalance(suite.Ctx, suite.Addrs[1], startingRecipientBal)
 | |
| 			suite.Require().NoError(err)
 | |
| 
 | |
| 			err = suite.Keeper.SendBalance(suite.Ctx, suite.Addrs[0], suite.Addrs[1], tt.amt)
 | |
| 			if tt.success {
 | |
| 				suite.Require().NoError(err)
 | |
| 				suite.Require().Equal(tt.expSenderBal, suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[0]))
 | |
| 				suite.Require().Equal(tt.expRecipientBal, suite.Keeper.GetBalance(suite.Ctx, suite.Addrs[1]))
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestSetBalance() {
 | |
| 	existingAccount := types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdkmath.NewInt(100),
 | |
| 	}
 | |
| 	tests := []struct {
 | |
| 		name    string
 | |
| 		address sdk.AccAddress
 | |
| 		balance sdkmath.Int
 | |
| 		success bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"invalid balance",
 | |
| 			suite.Addrs[0],
 | |
| 			sdkmath.NewInt(-100),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"set new account balance",
 | |
| 			suite.Addrs[1],
 | |
| 			sdkmath.NewInt(100),
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"replace account balance",
 | |
| 			suite.Addrs[0],
 | |
| 			sdkmath.NewInt(50),
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"invalid address",
 | |
| 			nil,
 | |
| 			sdkmath.NewInt(100),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"zero balance",
 | |
| 			suite.Addrs[0],
 | |
| 			sdk.ZeroInt(),
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			err := suite.Keeper.SetAccount(suite.Ctx, existingAccount)
 | |
| 			suite.Require().NoError(err)
 | |
| 			err = suite.Keeper.SetBalance(suite.Ctx, tt.address, tt.balance)
 | |
| 			if tt.success {
 | |
| 				suite.Require().NoError(err)
 | |
| 				expBal := suite.Keeper.GetBalance(suite.Ctx, tt.address)
 | |
| 				suite.Require().Equal(expBal, tt.balance)
 | |
| 
 | |
| 				if tt.balance.IsZero() {
 | |
| 					account := suite.Keeper.GetAccount(suite.Ctx, tt.address)
 | |
| 					suite.Require().Nil(account)
 | |
| 				}
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 				expBal := suite.Keeper.GetBalance(suite.Ctx, existingAccount.Address)
 | |
| 				suite.Require().Equal(expBal, existingAccount.Balance)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestRemoveBalance() {
 | |
| 	existingAccount := types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdkmath.NewInt(100),
 | |
| 	}
 | |
| 	tests := []struct {
 | |
| 		name    string
 | |
| 		amt     sdkmath.Int
 | |
| 		expBal  sdkmath.Int
 | |
| 		success bool
 | |
| 	}{
 | |
| 		{
 | |
| 			"fails if amount is negative",
 | |
| 			sdkmath.NewInt(-10),
 | |
| 			sdk.ZeroInt(),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"remove zero amount",
 | |
| 			sdk.ZeroInt(),
 | |
| 			existingAccount.Balance,
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"not enough balance",
 | |
| 			sdkmath.NewInt(101),
 | |
| 			sdk.ZeroInt(),
 | |
| 			false,
 | |
| 		},
 | |
| 		{
 | |
| 			"remove full balance",
 | |
| 			sdkmath.NewInt(100),
 | |
| 			sdk.ZeroInt(),
 | |
| 			true,
 | |
| 		},
 | |
| 		{
 | |
| 			"remove some balance",
 | |
| 			sdkmath.NewInt(10),
 | |
| 			sdkmath.NewInt(90),
 | |
| 			true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			err := suite.Keeper.SetAccount(suite.Ctx, existingAccount)
 | |
| 			suite.Require().NoError(err)
 | |
| 			err = suite.Keeper.RemoveBalance(suite.Ctx, existingAccount.Address, tt.amt)
 | |
| 			if tt.success {
 | |
| 				suite.Require().NoError(err)
 | |
| 				expBal := suite.Keeper.GetBalance(suite.Ctx, existingAccount.Address)
 | |
| 				suite.Require().Equal(expBal, tt.expBal)
 | |
| 			} else {
 | |
| 				suite.Require().Error(err)
 | |
| 				expBal := suite.Keeper.GetBalance(suite.Ctx, existingAccount.Address)
 | |
| 				suite.Require().Equal(expBal, existingAccount.Balance)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestGetBalance() {
 | |
| 	existingAccount := types.Account{
 | |
| 		Address: suite.Addrs[0],
 | |
| 		Balance: sdkmath.NewInt(100),
 | |
| 	}
 | |
| 	tests := []struct {
 | |
| 		name   string
 | |
| 		addr   sdk.AccAddress
 | |
| 		expBal sdkmath.Int
 | |
| 	}{
 | |
| 		{
 | |
| 			"returns 0 balance if account does not exist",
 | |
| 			suite.Addrs[1],
 | |
| 			sdk.ZeroInt(),
 | |
| 		},
 | |
| 		{
 | |
| 			"returns account balance",
 | |
| 			suite.Addrs[0],
 | |
| 			sdkmath.NewInt(100),
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		suite.Run(tt.name, func() {
 | |
| 			suite.SetupTest()
 | |
| 
 | |
| 			err := suite.Keeper.SetAccount(suite.Ctx, existingAccount)
 | |
| 			suite.Require().NoError(err)
 | |
| 			balance := suite.Keeper.GetBalance(suite.Ctx, tt.addr)
 | |
| 			suite.Require().Equal(tt.expBal, balance)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestDeployedCosmosCoinContractStoreState() {
 | |
| 	suite.Run("returns nil for nonexistent denom", func() {
 | |
| 		suite.SetupTest()
 | |
| 		addr, found := suite.Keeper.GetDeployedCosmosCoinContract(suite.Ctx, "undeployed-denom")
 | |
| 		suite.False(found)
 | |
| 		suite.Equal(addr, types.InternalEVMAddress{})
 | |
| 	})
 | |
| 
 | |
| 	suite.Run("handles setting & getting a contract address", func() {
 | |
| 		suite.SetupTest()
 | |
| 		denom := "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2"
 | |
| 		address := testutil.RandomInternalEVMAddress()
 | |
| 
 | |
| 		err := suite.Keeper.SetDeployedCosmosCoinContract(suite.Ctx, denom, address)
 | |
| 		suite.NoError(err)
 | |
| 
 | |
| 		stored, found := suite.Keeper.GetDeployedCosmosCoinContract(suite.Ctx, denom)
 | |
| 		suite.True(found)
 | |
| 		suite.Equal(address, stored)
 | |
| 	})
 | |
| 
 | |
| 	suite.Run("fails when setting an invalid denom", func() {
 | |
| 		suite.SetupTest()
 | |
| 		invalidDenom := ""
 | |
| 		err := suite.Keeper.SetDeployedCosmosCoinContract(suite.Ctx, invalidDenom, testutil.RandomInternalEVMAddress())
 | |
| 		suite.ErrorContains(err, "invalid cosmos denom")
 | |
| 	})
 | |
| 
 | |
| 	suite.Run("fails when setting 0 address", func() {
 | |
| 		suite.SetupTest()
 | |
| 		invalidAddr := types.InternalEVMAddress{}
 | |
| 		err := suite.Keeper.SetDeployedCosmosCoinContract(suite.Ctx, "denom", invalidAddr)
 | |
| 		suite.ErrorContains(err, "attempting to register empty contract address")
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (suite *keeperTestSuite) TestIterateAllDeployedCosmosCoinContracts() {
 | |
| 	suite.SetupTest()
 | |
| 	address := testutil.RandomInternalEVMAddress()
 | |
| 	denoms := []string{}
 | |
| 	register := func(denom string) {
 | |
| 		addr := testutil.RandomInternalEVMAddress()
 | |
| 		if denom == "waldo" {
 | |
| 			addr = address
 | |
| 		}
 | |
| 		err := suite.Keeper.SetDeployedCosmosCoinContract(suite.Ctx, denom, addr)
 | |
| 		suite.NoError(err)
 | |
| 		denoms = append(denoms, denom)
 | |
| 	}
 | |
| 
 | |
| 	// register some contracts
 | |
| 	register("magic")
 | |
| 	register("popcorn")
 | |
| 	register("waldo")
 | |
| 	register("zzz")
 | |
| 	register("ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2")
 | |
| 
 | |
| 	suite.Run("stops when told", func() {
 | |
| 		// test out stopping the iteration
 | |
| 		// NOTE: don't actually look for a single contract this way. the keys are deterministic by denom.
 | |
| 		var contract types.DeployedCosmosCoinContract
 | |
| 		suite.Keeper.IterateAllDeployedCosmosCoinContracts(suite.Ctx, func(c types.DeployedCosmosCoinContract) bool {
 | |
| 			contract = c
 | |
| 			return c.CosmosDenom == "waldo"
 | |
| 		})
 | |
| 		suite.Equal(types.NewDeployedCosmosCoinContract("waldo", address), contract)
 | |
| 	})
 | |
| 
 | |
| 	suite.Run("iterates all contracts", func() {
 | |
| 		foundDenoms := make([]string, 0, len(denoms))
 | |
| 		suite.Keeper.IterateAllDeployedCosmosCoinContracts(suite.Ctx, func(c types.DeployedCosmosCoinContract) bool {
 | |
| 			foundDenoms = append(foundDenoms, c.CosmosDenom)
 | |
| 			return false
 | |
| 		})
 | |
| 		suite.Len(foundDenoms, len(denoms))
 | |
| 		suite.ElementsMatch(denoms, foundDenoms)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestKeeperTestSuite(t *testing.T) {
 | |
| 	suite.Run(t, new(keeperTestSuite))
 | |
| }
 |