mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
1743cf5275
Fix reserve minting an extra coin when the recipient module both carries fractional over to integer balance AND remainder is insufficient. Adjusts fractional carry to simply send from reserve, instead of doing an additional mint. Add invariant to ensure reserve matches exactly with fractional balances + remainder, failing on both insufficient and excess funds.
130 lines
4.0 KiB
Go
130 lines
4.0 KiB
Go
package keeper_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/kava-labs/kava/x/precisebank/keeper"
|
|
"github.com/kava-labs/kava/x/precisebank/testutil"
|
|
"github.com/kava-labs/kava/x/precisebank/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)
|
|
}
|
|
})
|
|
}
|
|
}
|