0g-chain/x/precisebank/keeper/invariants_integration_test.go
2024-09-25 15:31:20 +00:00

130 lines
4.0 KiB
Go

package keeper_test
import (
"testing"
sdkmath "cosmossdk.io/math"
"github.com/0glabs/0g-chain/x/precisebank/keeper"
"github.com/0glabs/0g-chain/x/precisebank/testutil"
"github.com/0glabs/0g-chain/x/precisebank/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
)
type invariantsIntegrationTestSuite struct {
testutil.Suite
}
func (suite *invariantsIntegrationTestSuite) SetupTest() {
suite.Suite.SetupTest()
}
func TestInvariantsIntegrationTest(t *testing.T) {
suite.Run(t, new(invariantsIntegrationTestSuite))
}
func (suite *invariantsIntegrationTestSuite) FundReserve(amt sdkmath.Int) {
coins := sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, amt))
err := suite.BankKeeper.MintCoins(suite.Ctx, types.ModuleName, coins)
suite.Require().NoError(err)
}
func (suite *invariantsIntegrationTestSuite) TestReserveBackingFractionalInvariant() {
tests := []struct {
name string
setupFn func(ctx sdk.Context, k keeper.Keeper)
wantBroken bool
wantMsg string
}{
{
"valid - empty state",
func(_ sdk.Context, _ keeper.Keeper) {},
false,
"",
},
{
"valid - fractional balances, no remainder",
func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2))
// 1 integer backs same amount fractional
suite.FundReserve(sdk.NewInt(1))
},
false,
"",
},
{
"valid - fractional balances, with remainder",
func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetRemainderAmount(ctx, types.ConversionFactor().QuoRaw(2))
// 1 integer backs same amount fractional including remainder
suite.FundReserve(sdk.NewInt(1))
},
false,
"",
},
{
"invalid - no fractional balances, non-zero remainder",
func(ctx sdk.Context, k keeper.Keeper) {
k.SetRemainderAmount(ctx, types.ConversionFactor().QuoRaw(2))
},
true,
"precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 0 mismatches 500000000000 (fractional balances 0 + remainder 500000000000)\n\n",
},
{
"invalid - insufficient reserve backing",
func(ctx sdk.Context, k keeper.Keeper) {
amt := types.ConversionFactor().QuoRaw(2)
// 0.5 int coins x 4
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, amt)
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, amt)
k.SetFractionalBalance(ctx, sdk.AccAddress{3}, amt)
k.SetRemainderAmount(ctx, amt)
// Needs 2 to back 0.5 x 4
suite.FundReserve(sdk.NewInt(1))
},
true,
"precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 1000000000000 mismatches 2000000000000 (fractional balances 1500000000000 + remainder 500000000000)\n\n",
},
{
"invalid - excess reserve backing",
func(ctx sdk.Context, k keeper.Keeper) {
amt := types.ConversionFactor().QuoRaw(2)
// 0.5 int coins x 4
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, amt)
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, amt)
k.SetFractionalBalance(ctx, sdk.AccAddress{3}, amt)
k.SetRemainderAmount(ctx, amt)
// Needs 2 to back 0.5 x 4
suite.FundReserve(sdk.NewInt(3))
},
true,
"precisebank: module reserve backing total fractional balances invariant\nakava reserve balance 3000000000000 mismatches 2000000000000 (fractional balances 1500000000000 + remainder 500000000000)\n\n",
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
// Reset each time
suite.SetupTest()
tt.setupFn(suite.Ctx, suite.Keeper)
invariantFn := keeper.ReserveBacksFractionsInvariant(suite.Keeper)
msg, broken := invariantFn(suite.Ctx)
if tt.wantBroken {
suite.Require().True(broken, "invariant should be broken but is not")
suite.Require().Equal(tt.wantMsg, msg)
} else {
suite.Require().Falsef(broken, "invariant should not be broken but is: %s", msg)
}
})
}
}