2024-05-10 16:30:28 +00:00
|
|
|
package precisebank_test
|
|
|
|
|
|
|
|
import (
|
2024-05-15 21:07:24 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
|
2024-09-25 15:31:20 +00:00
|
|
|
"github.com/0glabs/0g-chain/x/precisebank"
|
|
|
|
"github.com/0glabs/0g-chain/x/precisebank/keeper"
|
|
|
|
"github.com/0glabs/0g-chain/x/precisebank/testutil"
|
|
|
|
"github.com/0glabs/0g-chain/x/precisebank/types"
|
2024-05-15 21:07:24 +00:00
|
|
|
"github.com/stretchr/testify/suite"
|
2024-05-10 16:30:28 +00:00
|
|
|
)
|
|
|
|
|
2024-05-15 21:07:24 +00:00
|
|
|
type GenesisTestSuite struct {
|
2024-05-10 16:30:28 +00:00
|
|
|
testutil.Suite
|
|
|
|
}
|
|
|
|
|
2024-05-15 21:07:24 +00:00
|
|
|
func TestGenesisTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(GenesisTestSuite))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (suite *GenesisTestSuite) TestInitGenesis() {
|
2024-05-10 16:30:28 +00:00
|
|
|
tests := []struct {
|
|
|
|
name string
|
2024-05-15 21:07:24 +00:00
|
|
|
setupFn func()
|
2024-05-10 16:30:28 +00:00
|
|
|
genesisState *types.GenesisState
|
|
|
|
panicMsg string
|
|
|
|
}{
|
|
|
|
{
|
2024-05-15 21:07:24 +00:00
|
|
|
"valid - default genesisState",
|
|
|
|
func() {},
|
2024-05-10 16:30:28 +00:00
|
|
|
types.DefaultGenesisState(),
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
{
|
2024-05-15 21:07:24 +00:00
|
|
|
"valid - empty genesisState",
|
|
|
|
func() {},
|
2024-05-10 16:30:28 +00:00
|
|
|
&types.GenesisState{},
|
2024-05-15 21:07:24 +00:00
|
|
|
"failed to validate precisebank genesis state: nil remainder amount",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid - module balance matches non-zero amount",
|
|
|
|
func() {
|
|
|
|
// Set module account balance to expected amount
|
|
|
|
err := suite.BankKeeper.MintCoins(
|
|
|
|
suite.Ctx,
|
|
|
|
types.ModuleName,
|
|
|
|
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(2))),
|
|
|
|
)
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
},
|
|
|
|
types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
},
|
|
|
|
// 2 leftover from 0.999... + 0.999...
|
|
|
|
sdkmath.NewInt(2),
|
|
|
|
),
|
2024-05-10 16:30:28 +00:00
|
|
|
"",
|
|
|
|
},
|
|
|
|
{
|
2024-05-15 21:07:24 +00:00
|
|
|
// Other GenesisState.Validate() tests are in types/genesis_test.go
|
|
|
|
"invalid genesisState - GenesisState.Validate() is called",
|
|
|
|
func() {},
|
|
|
|
types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)),
|
|
|
|
},
|
|
|
|
sdkmath.ZeroInt(),
|
|
|
|
),
|
|
|
|
"failed to validate precisebank genesis state: invalid balances: duplicate address kava1qy0xn7za",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid - module balance insufficient",
|
|
|
|
func() {},
|
|
|
|
types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
},
|
|
|
|
// 2 leftover from 0.999... + 0.999...
|
|
|
|
sdkmath.NewInt(2),
|
|
|
|
),
|
|
|
|
"module account balance does not match sum of fractional balances and remainder, balance is 0ukava but expected 2000000000000akava (2ukava)",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid - module balance excessive",
|
|
|
|
func() {
|
|
|
|
// Set module account balance to greater than expected amount
|
|
|
|
err := suite.BankKeeper.MintCoins(
|
|
|
|
suite.Ctx,
|
|
|
|
types.ModuleName,
|
|
|
|
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(100))),
|
|
|
|
)
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
},
|
|
|
|
types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
|
|
|
|
},
|
|
|
|
sdkmath.NewInt(2),
|
|
|
|
),
|
|
|
|
"module account balance does not match sum of fractional balances and remainder, balance is 100ukava but expected 2000000000000akava (2ukava)",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sets module account",
|
|
|
|
func() {
|
|
|
|
// Delete the module account first to ensure it's created here
|
|
|
|
moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
|
|
|
|
suite.AccountKeeper.RemoveAccount(suite.Ctx, moduleAcc)
|
|
|
|
|
|
|
|
// Ensure module account is deleted in state.
|
|
|
|
// GetModuleAccount() will always return non-nil and does not
|
|
|
|
// necessarily equate to the account being stored in the account store.
|
|
|
|
suite.Require().Nil(suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress()))
|
|
|
|
},
|
|
|
|
types.DefaultGenesisState(),
|
2024-05-10 16:30:28 +00:00
|
|
|
"",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
suite.Run(tc.name, func() {
|
2024-05-15 21:07:24 +00:00
|
|
|
suite.SetupTest()
|
|
|
|
tc.setupFn()
|
|
|
|
|
|
|
|
if tc.panicMsg != "" {
|
|
|
|
suite.Require().PanicsWithValue(
|
|
|
|
tc.panicMsg,
|
|
|
|
func() {
|
|
|
|
precisebank.InitGenesis(
|
|
|
|
suite.Ctx,
|
|
|
|
suite.Keeper,
|
|
|
|
suite.AccountKeeper,
|
|
|
|
suite.BankKeeper,
|
|
|
|
tc.genesisState,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
)
|
2024-05-10 16:30:28 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
suite.Require().NotPanics(func() {
|
2024-05-15 21:07:24 +00:00
|
|
|
precisebank.InitGenesis(
|
|
|
|
suite.Ctx,
|
|
|
|
suite.Keeper,
|
|
|
|
suite.AccountKeeper,
|
|
|
|
suite.BankKeeper,
|
|
|
|
tc.genesisState,
|
|
|
|
)
|
2024-05-10 16:30:28 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// Ensure module account is created
|
|
|
|
moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
|
2024-05-15 21:07:24 +00:00
|
|
|
suite.NotNil(moduleAcc)
|
|
|
|
suite.NotNil(
|
|
|
|
suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress()),
|
|
|
|
"module account should be created & stored in account store",
|
|
|
|
)
|
2024-05-10 16:30:28 +00:00
|
|
|
|
2024-05-20 16:50:31 +00:00
|
|
|
// Verify balances are set in state, get full list of balances in
|
|
|
|
// state to ensure they are set AND no extra balances are set
|
|
|
|
var bals []types.FractionalBalance
|
|
|
|
suite.Keeper.IterateFractionalBalances(suite.Ctx, func(addr sdk.AccAddress, bal sdkmath.Int) bool {
|
|
|
|
bals = append(bals, types.NewFractionalBalance(addr.String(), bal))
|
2024-05-10 16:30:28 +00:00
|
|
|
|
2024-05-20 16:50:31 +00:00
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
|
|
|
suite.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state")
|
2024-05-15 21:07:24 +00:00
|
|
|
|
2024-05-20 16:50:31 +00:00
|
|
|
remainder := suite.Keeper.GetRemainderAmount(suite.Ctx)
|
|
|
|
suite.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state")
|
2024-05-15 21:07:24 +00:00
|
|
|
|
2024-05-20 16:50:31 +00:00
|
|
|
// Additional verification of state via invariants
|
|
|
|
invariantFn := keeper.AllInvariants(suite.Keeper)
|
|
|
|
msg, broken := invariantFn(suite.Ctx)
|
|
|
|
suite.Require().False(broken, "invariants should not be broken after InitGenesis")
|
|
|
|
suite.Require().Empty(msg, "invariants should not return a message after InitGenesis")
|
2024-05-10 16:30:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-20 16:50:31 +00:00
|
|
|
func (suite *GenesisTestSuite) TestExportGenesis() {
|
|
|
|
// ExportGenesis(InitGenesis(genesisState)) == genesisState
|
|
|
|
// Must also be valid.
|
|
|
|
|
2024-05-10 16:30:28 +00:00
|
|
|
tests := []struct {
|
2024-05-20 16:50:31 +00:00
|
|
|
name string
|
|
|
|
initGenesisState func() *types.GenesisState
|
2024-05-10 16:30:28 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
"InitGenesis(DefaultGenesisState)",
|
2024-05-20 16:50:31 +00:00
|
|
|
func() *types.GenesisState {
|
|
|
|
return types.DefaultGenesisState()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"balances, no remainder",
|
|
|
|
func() *types.GenesisState {
|
|
|
|
err := suite.BankKeeper.MintCoins(
|
2024-05-10 16:30:28 +00:00
|
|
|
suite.Ctx,
|
2024-05-20 16:50:31 +00:00
|
|
|
types.ModuleName,
|
|
|
|
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))),
|
|
|
|
)
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
return types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2)),
|
|
|
|
},
|
|
|
|
sdkmath.ZeroInt(),
|
2024-05-10 16:30:28 +00:00
|
|
|
)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-20 16:50:31 +00:00
|
|
|
"balances, remainder",
|
|
|
|
func() *types.GenesisState {
|
|
|
|
err := suite.BankKeeper.MintCoins(
|
|
|
|
suite.Ctx,
|
|
|
|
types.ModuleName,
|
|
|
|
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))),
|
|
|
|
)
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
return types.NewGenesisState(
|
|
|
|
types.FractionalBalances{
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)),
|
|
|
|
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2).SubRaw(1)),
|
|
|
|
},
|
|
|
|
sdkmath.OneInt(),
|
|
|
|
)
|
|
|
|
},
|
2024-05-10 16:30:28 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
suite.Run(tc.name, func() {
|
2024-05-20 16:50:31 +00:00
|
|
|
// Reset state
|
|
|
|
suite.SetupTest()
|
|
|
|
|
|
|
|
initGs := tc.initGenesisState()
|
|
|
|
|
2024-05-10 16:30:28 +00:00
|
|
|
suite.Require().NotPanics(func() {
|
|
|
|
precisebank.InitGenesis(
|
|
|
|
suite.Ctx,
|
|
|
|
suite.Keeper,
|
|
|
|
suite.AccountKeeper,
|
2024-05-15 21:07:24 +00:00
|
|
|
suite.BankKeeper,
|
2024-05-20 16:50:31 +00:00
|
|
|
initGs,
|
2024-05-10 16:30:28 +00:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
genesisState := precisebank.ExportGenesis(suite.Ctx, suite.Keeper)
|
|
|
|
suite.Require().NoError(genesisState.Validate(), "exported genesis state should be valid")
|
|
|
|
|
|
|
|
suite.Require().Equal(
|
2024-05-20 16:50:31 +00:00
|
|
|
initGs,
|
2024-05-10 16:30:28 +00:00
|
|
|
genesisState,
|
|
|
|
"exported genesis state should equal initial genesis state",
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|