Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Genesis upgrade and add invariant cherry pick (backport #1081) #1082

Merged
merged 3 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ replace (
// branch: v0.22.0-osmo-v7, current tag: v0.22.0-osmo-v7.2.0
github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.22.0-osmo-v7.2
// Our cosmos-sdk branch is: https://github.com/osmosis-labs/cosmos-sdk v0.45.0x-osmo-v7
github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220309184504-1640058bad8a
github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220311195527-87988f9e28b1
// Use Osmosis fast iavl
github.com/cosmos/iavl => github.com/osmosis-labs/iavl v0.17.3-osmo-v5
// Use osmosis fork of ibc-go
Expand Down
12 changes: 2 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -777,16 +777,8 @@ github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnh
github.com/ory/dockertest/v3 v3.6.2/go.mod h1:EFLcVUOl8qCwp9NyDAcCDtq/QviLtYswW/VbWzUnTNE=
github.com/osmosis-labs/bech32-ibc v0.2.0-rc2 h1:7xy1pLtNiF2KaRSkolayZf4z3OfCJsO3eqBtEAXg2VA=
github.com/osmosis-labs/bech32-ibc v0.2.0-rc2/go.mod h1:0JCaioRNOVUiw7c3MngmKACnumaQ2sjPenXCnwxCttI=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220221115656-75545ea8cb2d h1:Y0JpKFb4n04ViTMUGm7SO4OobWKr6dBB/l3cvuBe6EY=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220221115656-75545ea8cb2d/go.mod h1:HsD/JxengDcevHFRA+wlWgeM78Og3ZwYM+cya3yOa7c=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220303025721-7f1c77addd36 h1:NXmRt2dx6rAA2Q3G8wBVxpkcNEQvJCztihxdmZy1cd4=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220303025721-7f1c77addd36/go.mod h1:UXp4GVQX3+u5iP1VQ7YZtGuLs0Fj5RBSSIi3xMYdUWI=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220309184504-1640058bad8a h1:xxsTTY8O+PHAQieff4t5PQPCd5Fum1qk8jajcZrKSjw=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220309184504-1640058bad8a/go.mod h1:7hy9bXGNkZVlq7MtejLafgPRuTnidBkyBnTEaMCj6Jc=
github.com/osmosis-labs/iavl v0.17.3-osmo-v3 h1:q2Qv3+DK52w5b68I96VApHI05jBu7HeQK/YDttKh/jY=
github.com/osmosis-labs/iavl v0.17.3-osmo-v3/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto=
github.com/osmosis-labs/iavl v0.17.3-osmo-v4 h1:U1HA2WEMAYVPjeJlfClH10ajv6O0C1C1jk/SQxDPwyM=
github.com/osmosis-labs/iavl v0.17.3-osmo-v4/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220311195527-87988f9e28b1 h1:cKcaMdiUZiZsQcQ2BL5Ta2OkhcWOri3HQe9lcoHypmA=
github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220311195527-87988f9e28b1/go.mod h1:7hy9bXGNkZVlq7MtejLafgPRuTnidBkyBnTEaMCj6Jc=
github.com/osmosis-labs/iavl v0.17.3-osmo-v5 h1:B6Saw2AK0StgfSSgi2rUc5B8MDa1vV1nGJUyYM7THus=
github.com/osmosis-labs/iavl v0.17.3-osmo-v5/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto=
github.com/osmosis-labs/ibc-go/v2 v2.0.2-osmo h1:XyYyDTjPIu7qX2nhQp9mboj7Pa9FEnjg1RXw73Ctv5U=
Expand Down
2 changes: 2 additions & 0 deletions proto/osmosis/superfluid/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ message GenesisState {
[ (gogoproto.nullable) = false ];
repeated SuperfluidIntermediaryAccount intermediary_accounts = 4
[ (gogoproto.nullable) = false ];
repeated LockIdIntermediaryAccountConnection intemediary_account_connections = 5
[ (gogoproto.nullable) = false ];
}
5 changes: 5 additions & 0 deletions proto/osmosis/superfluid/superfluid.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,8 @@ message SuperfluidDelegationRecord {
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"
];
}

message LockIdIntermediaryAccountConnection {
uint64 lock_id = 1;
string intermediary_account = 2;
}
2 changes: 2 additions & 0 deletions x/claim/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress,
}
func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, _ int64, _ sdk.Dec, _ sdk.Dec) {
}
func (h Hooks) AfterValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, infractionHeight int64, slashFactor sdk.Dec, effectiveSlashFactor sdk.Dec) {
}
func (h Hooks) BeforeSlashingUnbondingDelegation(ctx sdk.Context, unbondingDelegation stakingtypes.UnbondingDelegation,
infractionHeight int64, slashFactor sdk.Dec) {
}
Expand Down
23 changes: 21 additions & 2 deletions x/superfluid/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,31 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
for _, multiplierRecord := range genState.OsmoEquivalentMultipliers {
k.SetOsmoEquivalentMultiplier(ctx, multiplierRecord.EpochNumber, multiplierRecord.Denom, multiplierRecord.Multiplier)
}

for _, intermediaryAcc := range genState.IntermediaryAccounts {
k.SetIntermediaryAccount(ctx, intermediaryAcc)
}

// initialize lock id and intermediary connections
for _, connection := range genState.IntemediaryAccountConnections {
acc, err := sdk.AccAddressFromBech32(connection.IntermediaryAccount)
if err != nil {
panic(err)
}
intermediaryAcc := k.GetIntermediaryAccount(ctx, acc)
if intermediaryAcc.Denom == "" {
panic("connection to invalid intermediary account found")
}
k.SetLockIdIntermediaryAccountConnection(ctx, connection.LockId, intermediaryAcc)
}
}

// ExportGenesis returns the capability module's exported genesis.
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
return &types.GenesisState{
SuperfluidAssets: k.GetAllSuperfluidAssets(ctx),
OsmoEquivalentMultipliers: k.GetAllOsmoEquivalentMultipliers(ctx),
SuperfluidAssets: k.GetAllSuperfluidAssets(ctx),
OsmoEquivalentMultipliers: k.GetAllOsmoEquivalentMultipliers(ctx),
IntermediaryAccounts: k.GetAllIntermediaryAccounts(ctx),
IntemediaryAccountConnections: k.GetAllLockIdIntermediaryAccountConnections(ctx),
}
}
4 changes: 4 additions & 0 deletions x/superfluid/keeper/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func (suite *KeeperTestSuite) TestMoveSuperfluidDelegationRewardToGauges() {
// move intermediary account delegation rewards to gauges
suite.App.SuperfluidKeeper.MoveSuperfluidDelegationRewardToGauges(suite.Ctx)

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)

// check gauge balance
for _, gaugeCheck := range tc.gaugeChecks {
gaugeId := intermediaryAccs[gaugeCheck.intermediaryAccIndex].GaugeId
Expand Down
6 changes: 6 additions & 0 deletions x/superfluid/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,9 @@ func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, i
}
h.k.SlashLockupsForValidatorSlash(ctx, valAddr, infractionHeight, slashFactor)
}
func (h Hooks) AfterValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, infractionHeight int64, slashFactor sdk.Dec, effectiveSlashFactor sdk.Dec) {
// if slashFactor.IsZero() {
// return
// }
// h.k.RefreshIntermediaryDelegationAmounts(ctx)
}
16 changes: 16 additions & 0 deletions x/superfluid/keeper/intermediary_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ func (k Keeper) GetLockIdIntermediaryAccountConnection(ctx sdk.Context, lockId u
return prefixStore.Get(sdk.Uint64ToBigEndian(lockId))
}

func (k Keeper) GetAllLockIdIntermediaryAccountConnections(ctx sdk.Context) []types.LockIdIntermediaryAccountConnection {
store := ctx.KVStore(k.storeKey)
prefixStore := prefix.NewStore(store, types.KeyPrefixLockIntermediaryAccAddr)

iterator := prefixStore.Iterator(nil, nil)

connections := []types.LockIdIntermediaryAccountConnection{}
for ; iterator.Valid(); iterator.Next() {
connections = append(connections, types.LockIdIntermediaryAccountConnection{
LockId: sdk.BigEndianToUint64(iterator.Key()),
IntermediaryAccount: sdk.AccAddress(iterator.Value()).String(),
})
}
return connections
}

// Returns Superfluid Intermediate Account and a bool if found / not found
func (k Keeper) GetIntermediaryAccountFromLockId(ctx sdk.Context, lockId uint64) (types.SuperfluidIntermediaryAccount, bool) {
addr := k.GetLockIdIntermediaryAccountConnection(ctx, lockId)
Expand Down
5 changes: 5 additions & 0 deletions x/superfluid/keeper/intermediary_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,15 @@ func (suite *KeeperTestSuite) TestLockIdIntermediaryAccountConnection() {
addr = suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, 1)
suite.Require().Equal(addr.String(), acc.GetAccAddress().String())

// check get all
conns := suite.App.SuperfluidKeeper.GetAllLockIdIntermediaryAccountConnections(suite.Ctx)
suite.Require().Len(conns, 1)

// delete account
suite.App.SuperfluidKeeper.DeleteLockIdIntermediaryAccountConnection(suite.Ctx, 1)

// get account
addr = suite.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(suite.Ctx, 1)
suite.Require().Equal(addr.String(), "")

}
79 changes: 79 additions & 0 deletions x/superfluid/keeper/invariants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package keeper

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/osmosis-labs/osmosis/v7/x/superfluid/types"
)

const totalSuperfluidDelegationInvariantName = "total-superfluid-delegation-invariant-name"

// RegisterInvariants registers all governance invariants
func RegisterInvariants(ir sdk.InvariantRegistry, keeper Keeper) {
ir.RegisterRoute(types.ModuleName, totalSuperfluidDelegationInvariantName, TotalSuperfluidDelegationInvariant(keeper))
}

// AllInvariants runs all invariants of the gamm module
func AllInvariants(keeper Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
return TotalSuperfluidDelegationInvariant(keeper)(ctx)
}
}

// TotalSuperfluidDelegationInvariant checks the sum of intermediary account delegation is same as sum of individual lockup delegation
func TotalSuperfluidDelegationInvariant(keeper Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
accs := keeper.GetAllIntermediaryAccounts(ctx)
totalSuperfluidDelegationTokens := sdk.ZeroDec()

// Compute the total amount delegated from all intermediary accounts
for _, acc := range accs {
valAddr, err := sdk.ValAddressFromBech32(acc.ValAddr)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, totalSuperfluidDelegationInvariantName,
"\tinvalid validator address exists"), true
}
validator, found := keeper.sk.GetValidator(ctx, valAddr)
if !found {
return sdk.FormatInvariant(types.ModuleName, totalSuperfluidDelegationInvariantName,
"\tvalidator does not exists for specified validator address on intermediary account"), true
}
delegation, found := keeper.sk.GetDelegation(ctx, acc.GetAccAddress(), valAddr)
if found {
tokens := validator.TokensFromShares(delegation.Shares)
totalSuperfluidDelegationTokens = totalSuperfluidDelegationTokens.Add(tokens)
}
}

// Compute the total delegation amount expected
// from every lockID intermediary account connections
totalExpectedSuperfluidAmount := sdk.ZeroInt()
connections := keeper.GetAllLockIdIntermediaryAccountConnections(ctx)
for _, connection := range connections {
lockId := connection.LockId
lock, err := keeper.lk.GetLockByID(ctx, lockId)
if err != nil || lock == nil {
return sdk.FormatInvariant(types.ModuleName, totalSuperfluidDelegationInvariantName,
"\tinvalid superfluid lock id exists with no actual lockup"), true
}
if len(lock.Coins) != 1 {
return sdk.FormatInvariant(types.ModuleName, totalSuperfluidDelegationInvariantName,
"\tonly single coin lockup is eligible for superfluid staking"), true
}
amount := keeper.GetSuperfluidOSMOTokens(ctx, lock.Coins[0].Denom, lock.Coins[0].Amount)
totalExpectedSuperfluidAmount = totalExpectedSuperfluidAmount.Add(amount)
}

if !totalExpectedSuperfluidAmount.Equal(totalSuperfluidDelegationTokens.TruncateInt()) {
return sdk.FormatInvariant(types.ModuleName,
totalSuperfluidDelegationInvariantName,
fmt.Sprintf("\ttotal superfluid intermediary account delegation amount does not match total sum of lockup delegations: %s != %s\n", totalExpectedSuperfluidAmount.String(), totalSuperfluidDelegationTokens.String())),
true
}

return sdk.FormatInvariant(types.ModuleName, totalSuperfluidDelegationInvariantName,
"\ttotal superfluid intermediary account delegation amount matches total sum of lockup delegations\n"), false
}
}
73 changes: 41 additions & 32 deletions x/superfluid/keeper/slash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
lockuptypes "github.com/osmosis-labs/osmosis/v7/x/lockup/types"
"github.com/osmosis-labs/osmosis/v7/x/superfluid/keeper"
)

func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() {
Expand All @@ -15,38 +16,38 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() {
slashedValIndexes []int64
expSlashedLockIndexes []int64
}{
{
"with single validator and single superfluid delegation",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
1,
[]superfluidDelegation{{0, 0, 0, 1000000}},
[]int64{0},
[]int64{0},
},
{
"with single validator and multiple superfluid delegations",
[]stakingtypes.BondStatus{stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}},
[]int64{0},
[]int64{0, 1},
},
{
"with multiple validators and multiple superfluid delegations with single validator slash",
[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
[]int64{0},
[]int64{0},
},
{
"with multiple validators and multiple superfluid delegations with two validators slash",
[]stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
2,
[]superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
[]int64{0, 1},
[]int64{0, 1},
},
// {
// "with single validator and single superfluid delegation",
// []stakingtypes.BondStatus{stakingtypes.Bonded},
// 1,
// []superfluidDelegation{{0, 0, "gamm/pool/1", 1000000}},
// []int64{0},
// []int64{0},
// },
// {
// "with single validator and multiple superfluid delegations",
// []stakingtypes.BondStatus{stakingtypes.Bonded},
// 2,
// []superfluidDelegation{{0, 0, 0, 1000000}, {1, 0, 0, 1000000}},
// []int64{0},
// []int64{0, 1},
// },
// {
// "with multiple validators and multiple superfluid delegations with single validator slash",
// []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
// 2,
// []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
// []int64{0},
// []int64{0},
// },
// {
// "with multiple validators and multiple superfluid delegations with two validators slash",
// []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded},
// 2,
// []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}},
// []int64{0, 1},
// []int64{0, 1},
// },
}

for _, tc := range testCases {
Expand Down Expand Up @@ -89,6 +90,10 @@ func (suite *KeeperTestSuite) TestBeforeValidatorSlashed() {
// Note: this calls BeforeValidatorSlashed hook
}

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)

// check lock changes after validator & lockups slashing
for _, lockIndex := range tc.expSlashedLockIndexes {
gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, locks[lockIndex].ID)
Expand Down Expand Up @@ -169,6 +174,10 @@ func (suite *KeeperTestSuite) TestSlashLockupsForUnbondingDelegationSlash() {
slashFactor)
}

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)

// check check unbonding lockup changes
for _, lockId := range tc.superUnbondingLockIds {
gotLock, err := suite.App.LockupKeeper.GetLockByID(suite.Ctx, lockId)
Expand Down
11 changes: 11 additions & 0 deletions x/superfluid/keeper/stake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ func (suite *KeeperTestSuite) TestSuperfluidDelegate() {
suite.Require().Equal(tc.expInterDelegation[index], delegation.Shares)
}

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)

// try delegating twice with same lockup
for _, lock := range locks {
err := suite.App.SuperfluidKeeper.SuperfluidDelegate(suite.Ctx, lock.Owner, lock.ID, valAddrs[0].String())
Expand Down Expand Up @@ -385,6 +389,10 @@ func (suite *KeeperTestSuite) TestSuperfluidUndelegate() {
suite.Require().Equal(synthLock.EndTime, suite.Ctx.BlockTime().Add(unbondingDuration))
}

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)

// check remaining intermediary account delegation
for index, expDelegation := range tc.expInterDelegation {
acc := intermediaryAccs[index]
Expand Down Expand Up @@ -499,6 +507,9 @@ func (suite *KeeperTestSuite) TestSuperfluidUnbondLock() {
suite.Require().Equal(denoms[0], balances[0].Denom)
suite.Require().Equal(sdk.NewInt(1000000), balances[0].Amount)

// check invariant is fine
reason, broken := keeper.AllInvariants(*suite.App.SuperfluidKeeper)(suite.Ctx)
suite.Require().False(broken, reason)
}
}

Expand Down
4 changes: 3 additions & 1 deletion x/superfluid/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
}

// RegisterInvariants registers the capability module's invariants.
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
// keeper.RegisterInvariants(ir, am.keeper)
}

// InitGenesis performs the capability module's genesis initialization It returns
// no validator updates.
Expand Down
Loading