From d0ca709c87c7304f9170a1250e5ec1004a46be6c Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Mon, 17 Jul 2023 20:51:42 +0200 Subject: [PATCH 01/12] rename to --- x/superfluid/keeper/concentrated_liquidity.go | 2 +- x/superfluid/keeper/migrate.go | 2 +- x/superfluid/keeper/stake.go | 4 ++-- x/superfluid/keeper/stake_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x/superfluid/keeper/concentrated_liquidity.go b/x/superfluid/keeper/concentrated_liquidity.go index 56454d75bf7..fb1a80c7943 100644 --- a/x/superfluid/keeper/concentrated_liquidity.go +++ b/x/superfluid/keeper/concentrated_liquidity.go @@ -76,7 +76,7 @@ func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, se // Superfluid undelegate the superfluid delegated position. // This deletes the connection between the lock and the intermediate account, deletes the synthetic lock, and burns the synthetic osmo. - intermediateAccount, err := k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), lockId) + intermediateAccount, err := k.ForceSuperfluidUndelegate(ctx, sender.String(), lockId) if err != nil { return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err } diff --git a/x/superfluid/keeper/migrate.go b/x/superfluid/keeper/migrate.go index 47257b4bfa6..ffa5f3cd928 100644 --- a/x/superfluid/keeper/migrate.go +++ b/x/superfluid/keeper/migrate.go @@ -108,7 +108,7 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, // Note that lock's id is the same as the originalLockId since all shares are being migrated // and old lock is deleted gammLockToMigrate = preMigrationLock - intermediateAccount, err = k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), originalLockId) + intermediateAccount, err = k.ForceSuperfluidUndelegate(ctx, sender.String(), originalLockId) if err != nil { return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err } diff --git a/x/superfluid/keeper/stake.go b/x/superfluid/keeper/stake.go index bd40b110a77..a6c9cbc24e0 100644 --- a/x/superfluid/keeper/stake.go +++ b/x/superfluid/keeper/stake.go @@ -300,11 +300,11 @@ func (k Keeper) SuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint return k.createSyntheticLockup(ctx, lockID, intermediaryAcc, unlockingStatus) } -// SuperfluidUndelegateToConcentratedPosition starts undelegating superfluid delegated position for the given lock. It behaves similarly to SuperfluidUndelegate, +// ForceSuperfluidUndelegate starts undelegating superfluid delegated position for the given lock. It behaves similarly to SuperfluidUndelegate, // however it does not create a new synthetic lockup representing the unstaking side. This is because after the time this function is called, we might // want to perform more operations prior to creating a lock. Once the actual lock is created, the synthetic lockup representing the unstaking side // should eventually be created as well. Use this function with caution to avoid accidentally missing synthetic lock creation. -func (k Keeper) SuperfluidUndelegateToConcentratedPosition(ctx sdk.Context, sender string, gammLockID uint64) (types.SuperfluidIntermediaryAccount, error) { +func (k Keeper) ForceSuperfluidUndelegate(ctx sdk.Context, sender string, gammLockID uint64) (types.SuperfluidIntermediaryAccount, error) { return k.undelegateCommon(ctx, sender, gammLockID) } diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go index 9060cca2163..8cb7722fc2e 100644 --- a/x/superfluid/keeper/stake_test.go +++ b/x/superfluid/keeper/stake_test.go @@ -529,7 +529,7 @@ func (s *KeeperTestSuite) TestSuperfluidUndelegateToConcentratedPosition() { presupplyWithOffset := s.App.BankKeeper.GetSupplyWithOffset(s.Ctx, bondDenom) // superfluid undelegate - _, err = s.App.SuperfluidKeeper.SuperfluidUndelegateToConcentratedPosition(s.Ctx, lock.Owner, lockId) + _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, lock.Owner, lockId) if tc.expSuperUnbondingErr[index] { s.Require().Error(err) continue @@ -584,7 +584,7 @@ func (s *KeeperTestSuite) TestSuperfluidUndelegateToConcentratedPosition() { lock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) s.Require().NoError(err) - _, err = s.App.SuperfluidKeeper.SuperfluidUndelegateToConcentratedPosition(s.Ctx, lock.Owner, lockId) + _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, lock.Owner, lockId) s.Require().Error(err) } }) From f200e62c23be74a905b986c810b11ae1fb3a1381 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Mon, 17 Jul 2023 21:08:46 +0200 Subject: [PATCH 02/12] add force_superfluid_undelegate_allowed_addresses params --- proto/osmosis/superfluid/params.proto | 6 ++ x/superfluid/types/params.pb.go | 97 ++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/proto/osmosis/superfluid/params.proto b/proto/osmosis/superfluid/params.proto index a52e8b3928f..c2f7a2c66c0 100644 --- a/proto/osmosis/superfluid/params.proto +++ b/proto/osmosis/superfluid/params.proto @@ -17,4 +17,10 @@ message Params { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + + // force_superfluid_undelegate_allowed_addresses is a list of addresses that + // are allowed to force undelegate superfluid staking positions. + repeated string force_superfluid_undelegate_allowed_addresses = 2 + [ (gogoproto.moretags) = + "yaml:\"force_superfluid_undelegate_allowed_addresses\"" ]; } diff --git a/x/superfluid/types/params.pb.go b/x/superfluid/types/params.pb.go index fd84298b725..f3b4998dce4 100644 --- a/x/superfluid/types/params.pb.go +++ b/x/superfluid/types/params.pb.go @@ -32,6 +32,9 @@ type Params struct { // to counter-balance the staked amount on chain's exposure to various asset // volatilities, and have base staking be 'resistant' to volatility. MinimumRiskFactor github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=minimum_risk_factor,json=minimumRiskFactor,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"minimum_risk_factor" yaml:"minimum_risk_factor"` + // force_superfluid_undelegate_allowed_addresses is a list of addresses that + // are allowed to force undelegate superfluid staking positions. + ForceSuperfluidUndelegateAllowedAddresses []string `protobuf:"bytes,2,rep,name=force_superfluid_undelegate_allowed_addresses,json=forceSuperfluidUndelegateAllowedAddresses,proto3" json:"force_superfluid_undelegate_allowed_addresses,omitempty" yaml:"force_superfluid_undelegate_allowed_addresses"` } func (m *Params) Reset() { *m = Params{} } @@ -67,6 +70,13 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo +func (m *Params) GetForceSuperfluidUndelegateAllowedAddresses() []string { + if m != nil { + return m.ForceSuperfluidUndelegateAllowedAddresses + } + return nil +} + func init() { proto.RegisterType((*Params)(nil), "osmosis.superfluid.Params") } @@ -74,24 +84,28 @@ func init() { func init() { proto.RegisterFile("osmosis/superfluid/params.proto", fileDescriptor_0985261dfaf2a82e) } var fileDescriptor_0985261dfaf2a82e = []byte{ - // 260 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0x2f, 0xce, 0xcd, - 0x2f, 0xce, 0x2c, 0xd6, 0x2f, 0x2e, 0x2d, 0x48, 0x2d, 0x4a, 0xcb, 0x29, 0xcd, 0x4c, 0xd1, 0x2f, - 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x82, 0x2a, 0xd0, - 0x43, 0x28, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x4b, 0xeb, 0x83, 0x58, 0x10, 0x95, 0x52, - 0x72, 0xe9, 0xf9, 0xf9, 0xe9, 0x39, 0xa9, 0xfa, 0x60, 0x5e, 0x52, 0x69, 0x9a, 0x7e, 0x4a, 0x69, - 0x51, 0x62, 0x49, 0x66, 0x7e, 0x1e, 0x44, 0x5e, 0xa9, 0x8d, 0x91, 0x8b, 0x2d, 0x00, 0x6c, 0xb4, - 0x50, 0x0d, 0x97, 0x70, 0x6e, 0x66, 0x5e, 0x66, 0x6e, 0x69, 0x6e, 0x7c, 0x51, 0x66, 0x71, 0x76, - 0x7c, 0x5a, 0x62, 0x72, 0x49, 0x7e, 0x91, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xcf, 0x89, - 0x7b, 0xf2, 0x0c, 0xb7, 0xee, 0xc9, 0xab, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, - 0xe7, 0xea, 0x27, 0x83, 0x5d, 0x01, 0xa5, 0x74, 0x8b, 0x53, 0xb2, 0xf5, 0x4b, 0x2a, 0x0b, 0x52, - 0x8b, 0xf5, 0x5c, 0x52, 0x93, 0x3f, 0xdd, 0x93, 0x97, 0xaa, 0x4c, 0xcc, 0xcd, 0xb1, 0x52, 0xc2, - 0x62, 0xa4, 0x52, 0x90, 0x20, 0x54, 0x34, 0x28, 0xb3, 0x38, 0xdb, 0x0d, 0x2c, 0xe6, 0x14, 0x70, - 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, - 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x66, 0x48, 0x56, 0x42, 0xfd, 0xad, - 0x9b, 0x93, 0x98, 0x54, 0x0c, 0xe3, 0xe8, 0x97, 0x19, 0x9a, 0xe9, 0x57, 0x20, 0x87, 0x15, 0xd8, - 0x19, 0x49, 0x6c, 0x60, 0x1f, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xab, 0x2e, 0x8a, 0xb5, - 0x4e, 0x01, 0x00, 0x00, + // 334 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xbd, 0x4e, 0xc3, 0x30, + 0x14, 0x85, 0x93, 0x22, 0x55, 0x6a, 0x36, 0x02, 0x43, 0xd5, 0xc1, 0xa9, 0x32, 0xa0, 0x32, 0x34, + 0x16, 0x02, 0x55, 0x88, 0xad, 0x15, 0x62, 0x62, 0xa8, 0x8a, 0x58, 0x58, 0x22, 0x27, 0x76, 0x82, + 0x55, 0xbb, 0x8e, 0xec, 0x18, 0xa8, 0xc4, 0x43, 0x30, 0xb3, 0xf2, 0x32, 0x1d, 0x3b, 0x22, 0x86, + 0x08, 0x35, 0x6f, 0xd0, 0x27, 0x40, 0x38, 0xe9, 0xcf, 0xc0, 0xc2, 0x64, 0xdf, 0x7b, 0x3f, 0x1f, + 0xdb, 0xe7, 0x38, 0x9e, 0x50, 0x5c, 0x28, 0xaa, 0xa0, 0xd2, 0x19, 0x91, 0x09, 0xd3, 0x14, 0xc3, + 0x0c, 0x49, 0xc4, 0x55, 0x90, 0x49, 0x91, 0x0b, 0xd7, 0xad, 0x81, 0x60, 0x07, 0x74, 0x8e, 0x53, + 0x91, 0x0a, 0x33, 0x86, 0xbf, 0xbb, 0x8a, 0xec, 0x80, 0x54, 0x88, 0x94, 0x11, 0x68, 0xaa, 0x48, + 0x27, 0x10, 0x6b, 0x89, 0x72, 0x2a, 0x66, 0xd5, 0xdc, 0xff, 0x68, 0x38, 0xcd, 0xb1, 0x91, 0x76, + 0x5f, 0x9d, 0x23, 0x4e, 0x67, 0x94, 0x6b, 0x1e, 0x4a, 0xaa, 0xa6, 0x61, 0x82, 0xe2, 0x5c, 0xc8, + 0xb6, 0xdd, 0xb5, 0x7b, 0xad, 0xd1, 0xed, 0xa2, 0xf0, 0xac, 0xaf, 0xc2, 0x3b, 0x49, 0x69, 0xfe, + 0xa8, 0xa3, 0x20, 0x16, 0x1c, 0xc6, 0xe6, 0x15, 0xf5, 0xd2, 0x57, 0x78, 0x0a, 0xf3, 0x79, 0x46, + 0x54, 0x70, 0x4d, 0xe2, 0x75, 0xe1, 0x75, 0xe6, 0x88, 0xb3, 0x2b, 0xff, 0x0f, 0x49, 0x7f, 0x72, + 0x58, 0x77, 0x27, 0x54, 0x4d, 0x6f, 0x4c, 0xcf, 0x7d, 0xb7, 0x9d, 0x7e, 0x22, 0x64, 0x4c, 0xc2, + 0xdd, 0x9f, 0x42, 0x3d, 0xc3, 0x84, 0x91, 0x14, 0xe5, 0x24, 0x44, 0x8c, 0x89, 0x67, 0x82, 0x43, + 0x84, 0xb1, 0x24, 0x4a, 0x11, 0xd5, 0x6e, 0x74, 0x0f, 0x7a, 0xad, 0xd1, 0xe5, 0xba, 0xf0, 0x2e, + 0xaa, 0xab, 0xfe, 0x75, 0xdc, 0x9f, 0x9c, 0x1a, 0xfe, 0x6e, 0x8b, 0xdf, 0x6f, 0xe9, 0x61, 0x05, + 0x0f, 0x37, 0xec, 0x68, 0xbc, 0x58, 0x01, 0x7b, 0xb9, 0x02, 0xf6, 0xf7, 0x0a, 0xd8, 0x6f, 0x25, + 0xb0, 0x96, 0x25, 0xb0, 0x3e, 0x4b, 0x60, 0x3d, 0x0c, 0xf6, 0xfc, 0xa8, 0x43, 0xe9, 0x33, 0x14, + 0xa9, 0x4d, 0x01, 0x9f, 0xce, 0x06, 0xf0, 0x65, 0x3f, 0x48, 0xe3, 0x51, 0xd4, 0x34, 0xf6, 0x9f, + 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x97, 0x71, 0xea, 0xeb, 0x01, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -114,6 +128,15 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ForceSuperfluidUndelegateAllowedAddresses) > 0 { + for iNdEx := len(m.ForceSuperfluidUndelegateAllowedAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ForceSuperfluidUndelegateAllowedAddresses[iNdEx]) + copy(dAtA[i:], m.ForceSuperfluidUndelegateAllowedAddresses[iNdEx]) + i = encodeVarintParams(dAtA, i, uint64(len(m.ForceSuperfluidUndelegateAllowedAddresses[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } { size := m.MinimumRiskFactor.Size() i -= size @@ -146,6 +169,12 @@ func (m *Params) Size() (n int) { _ = l l = m.MinimumRiskFactor.Size() n += 1 + l + sovParams(uint64(l)) + if len(m.ForceSuperfluidUndelegateAllowedAddresses) > 0 { + for _, s := range m.ForceSuperfluidUndelegateAllowedAddresses { + l = len(s) + n += 1 + l + sovParams(uint64(l)) + } + } return n } @@ -218,6 +247,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForceSuperfluidUndelegateAllowedAddresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForceSuperfluidUndelegateAllowedAddresses = append(m.ForceSuperfluidUndelegateAllowedAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) From 0b9e3d189a2167edad3052bbcbcbec1f60ddb817 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Mon, 17 Jul 2023 22:22:53 +0200 Subject: [PATCH 03/12] update params def --- x/superfluid/types/params.go | 37 +++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/x/superfluid/types/params.go b/x/superfluid/types/params.go index a7969803de7..17c71ada439 100644 --- a/x/superfluid/types/params.go +++ b/x/superfluid/types/params.go @@ -10,8 +10,9 @@ import ( // Parameter store keys. var ( - KeyMinimumRiskFactor = []byte("MinimumRiskFactor") - defaultMinimumRiskFactor = sdk.NewDecWithPrec(5, 1) // 50% + KeyMinimumRiskFactor = []byte("MinimumRiskFactor") + KeyForceSuperfluidUndelegateAllowedAddresses = []byte("ForceSuperfluidUndelegateAllowedAddresses") + defaultMinimumRiskFactor = sdk.NewDecWithPrec(5, 1) // 50% ) // ParamTable for minting module. @@ -19,21 +20,31 @@ func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) } -func NewParams(minimumRiskFactor sdk.Dec) Params { +func NewParams(minimumRiskFactor sdk.Dec, forceSuperfluidUndelegateAllowedAddresses []string) Params { return Params{ - MinimumRiskFactor: minimumRiskFactor, + MinimumRiskFactor: minimumRiskFactor, + ForceSuperfluidUndelegateAllowedAddresses: forceSuperfluidUndelegateAllowedAddresses, } } // default minting module parameters. func DefaultParams() Params { return Params{ - MinimumRiskFactor: defaultMinimumRiskFactor, // 5% + MinimumRiskFactor: defaultMinimumRiskFactor, // 5% + ForceSuperfluidUndelegateAllowedAddresses: []string{}, } } // validate params. func (p Params) Validate() error { + if err := ValidateMinimumRiskFactor(p.MinimumRiskFactor); err != nil { + return err + } + + if err := ValidateAddresses(p.ForceSuperfluidUndelegateAllowedAddresses); err != nil { + return err + } + return nil } @@ -41,6 +52,7 @@ func (p Params) Validate() error { func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyMinimumRiskFactor, &p.MinimumRiskFactor, ValidateMinimumRiskFactor), + paramtypes.NewParamSetPair(KeyForceSuperfluidUndelegateAllowedAddresses, &p.ForceSuperfluidUndelegateAllowedAddresses, ValidateAddresses), } } @@ -69,3 +81,18 @@ func ValidateUnbondingDuration(i interface{}) error { return nil } + +func ValidateAddresses(i interface{}) error { + addresses, ok := i.([]string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + for _, address := range addresses { + _, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + } + + return nil +} From c8c235273adc67ea443f8e0f3d66d9bef0ed4461 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Mon, 17 Jul 2023 23:07:28 +0200 Subject: [PATCH 04/12] implement force undelegate --- proto/osmosis/superfluid/tx.proto | 12 + x/superfluid/keeper/internal/events/emit.go | 17 + x/superfluid/keeper/msg_server.go | 34 ++ x/superfluid/keeper/stake.go | 4 +- x/superfluid/types/events.go | 1 + x/superfluid/types/msgs.go | 33 ++ x/superfluid/types/tx.pb.go | 561 ++++++++++++++++---- 7 files changed, 561 insertions(+), 101 deletions(-) diff --git a/proto/osmosis/superfluid/tx.proto b/proto/osmosis/superfluid/tx.proto index 41149d7f065..a58613b3061 100644 --- a/proto/osmosis/superfluid/tx.proto +++ b/proto/osmosis/superfluid/tx.proto @@ -20,6 +20,9 @@ service Msg { rpc SuperfluidUndelegate(MsgSuperfluidUndelegate) returns (MsgSuperfluidUndelegateResponse); + rpc ForceSuperfluidUndelegate(MsgForceSuperfluidUndelegate) + returns (MsgForceSuperfluidUndelegateResponse); + // Execute superfluid redelegation for a lockup // rpc SuperfluidRedelegate(MsgSuperfluidRedelegate) returns // (MsgSuperfluidRedelegateResponse); @@ -71,6 +74,15 @@ message MsgSuperfluidUndelegate { } message MsgSuperfluidUndelegateResponse {} +message MsgForceSuperfluidUndelegate { + option (amino.name) = "osmosis/force-superfluid-undelegate"; + + string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; + uint64 lock_id = 2; +} + +message MsgForceSuperfluidUndelegateResponse {} + message MsgSuperfluidUnbondLock { option (amino.name) = "osmosis/superfluid-unbond-lock"; diff --git a/x/superfluid/keeper/internal/events/emit.go b/x/superfluid/keeper/internal/events/emit.go index ee8913e8f32..496384d810a 100644 --- a/x/superfluid/keeper/internal/events/emit.go +++ b/x/superfluid/keeper/internal/events/emit.go @@ -116,6 +116,23 @@ func newSuperfluidUndelegateEvent(lockId uint64) sdk.Event { ) } +func EmitForceSuperfluidUndelegateEvent(ctx sdk.Context, lockId uint64) { + if ctx.EventManager() == nil { + return + } + + ctx.EventManager().EmitEvents(sdk.Events{ + newForceSuperfluidUndelegateEvent(lockId), + }) +} + +func newForceSuperfluidUndelegateEvent(lockId uint64) sdk.Event { + return sdk.NewEvent( + types.TypeEvtForceSuperfluidUndelegate, + sdk.NewAttribute(types.AttributeLockId, fmt.Sprintf("%d", lockId)), + ) +} + func EmitSuperfluidUnbondLockEvent(ctx sdk.Context, lockId uint64) { if ctx.EventManager() == nil { return diff --git a/x/superfluid/keeper/msg_server.go b/x/superfluid/keeper/msg_server.go index 19d94ddabc3..ab98774eeb9 100644 --- a/x/superfluid/keeper/msg_server.go +++ b/x/superfluid/keeper/msg_server.go @@ -3,6 +3,7 @@ package keeper import ( "context" "encoding/json" + "fmt" "strconv" "time" @@ -13,6 +14,9 @@ import ( "github.com/osmosis-labs/osmosis/v16/x/superfluid/keeper/internal/events" "github.com/osmosis-labs/osmosis/v16/x/superfluid/types" + + errorsmod "cosmossdk.io/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) type msgServer struct { @@ -66,6 +70,36 @@ func (server msgServer) SuperfluidUndelegate(goCtx context.Context, msg *types.M return &types.MsgSuperfluidUndelegateResponse{}, err } +// ForceSuperfluidUndelegate is a method to force undelegate superfluid staked asset. +// This method is only allowed to be called whitelisted addresses. +func (server msgServer) ForceSuperfluidUndelegate(goCtx context.Context, msg *types.MsgForceSuperfluidUndelegate) (*types.MsgForceSuperfluidUndelegateResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // check if the sender is allowed to force undelegate + forceUndelegateAllowedAddresses := server.keeper.GetParams(ctx).ForceSuperfluidUndelegateAllowedAddresses + isSenderAllowed := false + for _, addr := range forceUndelegateAllowedAddresses { + if addr == msg.Sender { + isSenderAllowed = true + break + } + } + + // return error if the sender is not allowed to force undelegate + if !isSenderAllowed { + return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("msg sender (%s) is not allowed to force undeledate superfluid staking position", msg.Sender)) + } + + // perform force undelegate + _, err := server.keeper.ForceSuperfluidUndelegate(ctx, msg.Sender, msg.LockId) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + + events.EmitForceSuperfluidUndelegateEvent(ctx, msg.LockId) + return &types.MsgForceSuperfluidUndelegateResponse{}, nil +} + // SuperfluidRedelegate is a method to redelegate superfluid staked asset into a different validator. // Currently this feature is not supported. // func (server msgServer) SuperfluidRedelegate(goCtx context.Context, msg *types.MsgSuperfluidRedelegate) (*types.MsgSuperfluidRedelegateResponse, error) { diff --git a/x/superfluid/keeper/stake.go b/x/superfluid/keeper/stake.go index a6c9cbc24e0..ed4a2b81477 100644 --- a/x/superfluid/keeper/stake.go +++ b/x/superfluid/keeper/stake.go @@ -304,8 +304,8 @@ func (k Keeper) SuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint // however it does not create a new synthetic lockup representing the unstaking side. This is because after the time this function is called, we might // want to perform more operations prior to creating a lock. Once the actual lock is created, the synthetic lockup representing the unstaking side // should eventually be created as well. Use this function with caution to avoid accidentally missing synthetic lock creation. -func (k Keeper) ForceSuperfluidUndelegate(ctx sdk.Context, sender string, gammLockID uint64) (types.SuperfluidIntermediaryAccount, error) { - return k.undelegateCommon(ctx, sender, gammLockID) +func (k Keeper) ForceSuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint64) (types.SuperfluidIntermediaryAccount, error) { + return k.undelegateCommon(ctx, sender, lockID) } // partialUndelegateCommon acts similarly to undelegateCommon, but undelegates a partial amount of the lock's delegation rather than the full amount. The amount diff --git a/x/superfluid/types/events.go b/x/superfluid/types/events.go index de0594e5ea8..e9ebb08069e 100644 --- a/x/superfluid/types/events.go +++ b/x/superfluid/types/events.go @@ -9,6 +9,7 @@ const ( TypeEvtSuperfluidUndelegate = "superfluid_undelegate" TypeEvtSuperfluidUnbondLock = "superfluid_unbond_lock" TypeEvtSuperfluidUndelegateAndUnbondLock = "superfluid_undelegate_and_unbond_lock" + TypeEvtForceSuperfluidUndelegate = "force_superfluid_undelegate" TypeEvtAddToConcentratedLiquiditySuperfluidPosition = "add_to_concentrated_liquidity_superfluid_position" TypeEvtUnpoolId = "unpool_pool_id" diff --git a/x/superfluid/types/msgs.go b/x/superfluid/types/msgs.go index b752105464d..5de45cb7eb1 100644 --- a/x/superfluid/types/msgs.go +++ b/x/superfluid/types/msgs.go @@ -16,6 +16,7 @@ const ( TypeMsgSuperfluidRedelegate = "superfluid_redelegate" TypeMsgSuperfluidUnbondLock = "superfluid_unbond_underlying_lock" TypeMsgSuperfluidUndeledgateAndUnbondLock = "superfluid_undelegate_and_unbond_lock" + TypeMsgForceSuperfluidUndelegate = "force_superfluid_undelegate" TypeMsgLockAndSuperfluidDelegate = "lock_and_superfluid_delegate" TypeMsgUnPoolWhitelistedPool = "unpool_whitelisted_pool" TypeMsgUnlockAndMigrateShares = "unlock_and_migrate_shares" @@ -89,6 +90,38 @@ func (m MsgSuperfluidUndelegate) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{sender} } +var _ sdk.Msg = &MsgForceSuperfluidUndelegate{} + +// NewMsgForceSuperfluidUndelegate creates a message to do force superfluid undelegation. +func NewMsgForceSuperfluidUndelegate(sender sdk.AccAddress, lockId uint64) *MsgForceSuperfluidUndelegate { + return &MsgForceSuperfluidUndelegate{ + Sender: sender.String(), + LockId: lockId, + } +} + +func (m MsgForceSuperfluidUndelegate) Route() string { return RouterKey } +func (m MsgForceSuperfluidUndelegate) Type() string { return TypeMsgForceSuperfluidUndelegate } + +func (m MsgForceSuperfluidUndelegate) ValidateBasic() error { + if m.Sender == "" { + return fmt.Errorf("sender should not be an empty address") + } + if m.LockId == 0 { + return fmt.Errorf("lock id should be positive: %d < 0", m.LockId) + } + return nil +} + +func (m MsgForceSuperfluidUndelegate) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +func (m MsgForceSuperfluidUndelegate) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(m.Sender) + return []sdk.AccAddress{sender} +} + // var _ sdk.Msg = &MsgSuperfluidRedelegate{} // // NewMsgSuperfluidRedelegate creates a message to do superfluid redelegation diff --git a/x/superfluid/types/tx.pb.go b/x/superfluid/types/tx.pb.go index 7532c22f46e..a2dcf6547c9 100644 --- a/x/superfluid/types/tx.pb.go +++ b/x/superfluid/types/tx.pb.go @@ -219,6 +219,94 @@ func (m *MsgSuperfluidUndelegateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgSuperfluidUndelegateResponse proto.InternalMessageInfo +type MsgForceSuperfluidUndelegate struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + LockId uint64 `protobuf:"varint,2,opt,name=lock_id,json=lockId,proto3" json:"lock_id,omitempty"` +} + +func (m *MsgForceSuperfluidUndelegate) Reset() { *m = MsgForceSuperfluidUndelegate{} } +func (m *MsgForceSuperfluidUndelegate) String() string { return proto.CompactTextString(m) } +func (*MsgForceSuperfluidUndelegate) ProtoMessage() {} +func (*MsgForceSuperfluidUndelegate) Descriptor() ([]byte, []int) { + return fileDescriptor_55b645f187d22814, []int{4} +} +func (m *MsgForceSuperfluidUndelegate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgForceSuperfluidUndelegate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgForceSuperfluidUndelegate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgForceSuperfluidUndelegate) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgForceSuperfluidUndelegate.Merge(m, src) +} +func (m *MsgForceSuperfluidUndelegate) XXX_Size() int { + return m.Size() +} +func (m *MsgForceSuperfluidUndelegate) XXX_DiscardUnknown() { + xxx_messageInfo_MsgForceSuperfluidUndelegate.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgForceSuperfluidUndelegate proto.InternalMessageInfo + +func (m *MsgForceSuperfluidUndelegate) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgForceSuperfluidUndelegate) GetLockId() uint64 { + if m != nil { + return m.LockId + } + return 0 +} + +type MsgForceSuperfluidUndelegateResponse struct { +} + +func (m *MsgForceSuperfluidUndelegateResponse) Reset() { *m = MsgForceSuperfluidUndelegateResponse{} } +func (m *MsgForceSuperfluidUndelegateResponse) String() string { return proto.CompactTextString(m) } +func (*MsgForceSuperfluidUndelegateResponse) ProtoMessage() {} +func (*MsgForceSuperfluidUndelegateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_55b645f187d22814, []int{5} +} +func (m *MsgForceSuperfluidUndelegateResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgForceSuperfluidUndelegateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgForceSuperfluidUndelegateResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgForceSuperfluidUndelegateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgForceSuperfluidUndelegateResponse.Merge(m, src) +} +func (m *MsgForceSuperfluidUndelegateResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgForceSuperfluidUndelegateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgForceSuperfluidUndelegateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgForceSuperfluidUndelegateResponse proto.InternalMessageInfo + type MsgSuperfluidUnbondLock struct { Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` LockId uint64 `protobuf:"varint,2,opt,name=lock_id,json=lockId,proto3" json:"lock_id,omitempty"` @@ -228,7 +316,7 @@ func (m *MsgSuperfluidUnbondLock) Reset() { *m = MsgSuperfluidUnbondLock func (m *MsgSuperfluidUnbondLock) String() string { return proto.CompactTextString(m) } func (*MsgSuperfluidUnbondLock) ProtoMessage() {} func (*MsgSuperfluidUnbondLock) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{4} + return fileDescriptor_55b645f187d22814, []int{6} } func (m *MsgSuperfluidUnbondLock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -278,7 +366,7 @@ func (m *MsgSuperfluidUnbondLockResponse) Reset() { *m = MsgSuperfluidUn func (m *MsgSuperfluidUnbondLockResponse) String() string { return proto.CompactTextString(m) } func (*MsgSuperfluidUnbondLockResponse) ProtoMessage() {} func (*MsgSuperfluidUnbondLockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{5} + return fileDescriptor_55b645f187d22814, []int{7} } func (m *MsgSuperfluidUnbondLockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -318,7 +406,7 @@ func (m *MsgSuperfluidUndelegateAndUnbondLock) Reset() { *m = MsgSuperfl func (m *MsgSuperfluidUndelegateAndUnbondLock) String() string { return proto.CompactTextString(m) } func (*MsgSuperfluidUndelegateAndUnbondLock) ProtoMessage() {} func (*MsgSuperfluidUndelegateAndUnbondLock) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{6} + return fileDescriptor_55b645f187d22814, []int{8} } func (m *MsgSuperfluidUndelegateAndUnbondLock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -383,7 +471,7 @@ func (m *MsgSuperfluidUndelegateAndUnbondLockResponse) String() string { } func (*MsgSuperfluidUndelegateAndUnbondLockResponse) ProtoMessage() {} func (*MsgSuperfluidUndelegateAndUnbondLockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{7} + return fileDescriptor_55b645f187d22814, []int{9} } func (m *MsgSuperfluidUndelegateAndUnbondLockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -432,7 +520,7 @@ func (m *MsgLockAndSuperfluidDelegate) Reset() { *m = MsgLockAndSuperflu func (m *MsgLockAndSuperfluidDelegate) String() string { return proto.CompactTextString(m) } func (*MsgLockAndSuperfluidDelegate) ProtoMessage() {} func (*MsgLockAndSuperfluidDelegate) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{8} + return fileDescriptor_55b645f187d22814, []int{10} } func (m *MsgLockAndSuperfluidDelegate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -490,7 +578,7 @@ func (m *MsgLockAndSuperfluidDelegateResponse) Reset() { *m = MsgLockAnd func (m *MsgLockAndSuperfluidDelegateResponse) String() string { return proto.CompactTextString(m) } func (*MsgLockAndSuperfluidDelegateResponse) ProtoMessage() {} func (*MsgLockAndSuperfluidDelegateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{9} + return fileDescriptor_55b645f187d22814, []int{11} } func (m *MsgLockAndSuperfluidDelegateResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -543,7 +631,7 @@ func (m *MsgCreateFullRangePositionAndSuperfluidDelegate) String() string { } func (*MsgCreateFullRangePositionAndSuperfluidDelegate) ProtoMessage() {} func (*MsgCreateFullRangePositionAndSuperfluidDelegate) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{10} + return fileDescriptor_55b645f187d22814, []int{12} } func (m *MsgCreateFullRangePositionAndSuperfluidDelegate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -613,7 +701,7 @@ func (m *MsgCreateFullRangePositionAndSuperfluidDelegateResponse) String() strin } func (*MsgCreateFullRangePositionAndSuperfluidDelegateResponse) ProtoMessage() {} func (*MsgCreateFullRangePositionAndSuperfluidDelegateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{11} + return fileDescriptor_55b645f187d22814, []int{13} } func (m *MsgCreateFullRangePositionAndSuperfluidDelegateResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -673,7 +761,7 @@ func (m *MsgUnPoolWhitelistedPool) Reset() { *m = MsgUnPoolWhitelistedPo func (m *MsgUnPoolWhitelistedPool) String() string { return proto.CompactTextString(m) } func (*MsgUnPoolWhitelistedPool) ProtoMessage() {} func (*MsgUnPoolWhitelistedPool) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{12} + return fileDescriptor_55b645f187d22814, []int{14} } func (m *MsgUnPoolWhitelistedPool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -724,7 +812,7 @@ func (m *MsgUnPoolWhitelistedPoolResponse) Reset() { *m = MsgUnPoolWhite func (m *MsgUnPoolWhitelistedPoolResponse) String() string { return proto.CompactTextString(m) } func (*MsgUnPoolWhitelistedPoolResponse) ProtoMessage() {} func (*MsgUnPoolWhitelistedPoolResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{13} + return fileDescriptor_55b645f187d22814, []int{15} } func (m *MsgUnPoolWhitelistedPoolResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -778,7 +866,7 @@ func (m *MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition) String() stri } func (*MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition) ProtoMessage() {} func (*MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{14} + return fileDescriptor_55b645f187d22814, []int{16} } func (m *MsgUnlockAndMigrateSharesToFullRangeConcentratedPosition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -850,7 +938,7 @@ func (m *MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse) Strin } func (*MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse) ProtoMessage() {} func (*MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{15} + return fileDescriptor_55b645f187d22814, []int{17} } func (m *MsgUnlockAndMigrateSharesToFullRangeConcentratedPositionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -902,7 +990,7 @@ func (m *MsgAddToConcentratedLiquiditySuperfluidPosition) String() string { } func (*MsgAddToConcentratedLiquiditySuperfluidPosition) ProtoMessage() {} func (*MsgAddToConcentratedLiquiditySuperfluidPosition) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{16} + return fileDescriptor_55b645f187d22814, []int{18} } func (m *MsgAddToConcentratedLiquiditySuperfluidPosition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -978,7 +1066,7 @@ func (m *MsgAddToConcentratedLiquiditySuperfluidPositionResponse) String() strin } func (*MsgAddToConcentratedLiquiditySuperfluidPositionResponse) ProtoMessage() {} func (*MsgAddToConcentratedLiquiditySuperfluidPositionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_55b645f187d22814, []int{17} + return fileDescriptor_55b645f187d22814, []int{19} } func (m *MsgAddToConcentratedLiquiditySuperfluidPositionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1026,6 +1114,8 @@ func init() { proto.RegisterType((*MsgSuperfluidDelegateResponse)(nil), "osmosis.superfluid.MsgSuperfluidDelegateResponse") proto.RegisterType((*MsgSuperfluidUndelegate)(nil), "osmosis.superfluid.MsgSuperfluidUndelegate") proto.RegisterType((*MsgSuperfluidUndelegateResponse)(nil), "osmosis.superfluid.MsgSuperfluidUndelegateResponse") + proto.RegisterType((*MsgForceSuperfluidUndelegate)(nil), "osmosis.superfluid.MsgForceSuperfluidUndelegate") + proto.RegisterType((*MsgForceSuperfluidUndelegateResponse)(nil), "osmosis.superfluid.MsgForceSuperfluidUndelegateResponse") proto.RegisterType((*MsgSuperfluidUnbondLock)(nil), "osmosis.superfluid.MsgSuperfluidUnbondLock") proto.RegisterType((*MsgSuperfluidUnbondLockResponse)(nil), "osmosis.superfluid.MsgSuperfluidUnbondLockResponse") proto.RegisterType((*MsgSuperfluidUndelegateAndUnbondLock)(nil), "osmosis.superfluid.MsgSuperfluidUndelegateAndUnbondLock") @@ -1045,91 +1135,94 @@ func init() { func init() { proto.RegisterFile("osmosis/superfluid/tx.proto", fileDescriptor_55b645f187d22814) } var fileDescriptor_55b645f187d22814 = []byte{ - // 1343 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcf, 0x73, 0xd3, 0xc6, - 0x17, 0x8f, 0xec, 0x90, 0xc0, 0x86, 0x00, 0xd1, 0x97, 0x1f, 0xc6, 0x5f, 0xb0, 0xcc, 0x42, 0x69, - 0xf8, 0x61, 0x29, 0x86, 0x16, 0x98, 0x9c, 0x88, 0xe3, 0xa1, 0x63, 0x1a, 0x4f, 0x19, 0x11, 0xa6, - 0x33, 0x5c, 0x3c, 0xb2, 0x77, 0x23, 0xd4, 0xc8, 0x5a, 0xa3, 0x95, 0x92, 0x30, 0x3d, 0xb5, 0x3d, - 0x74, 0x86, 0x13, 0xc7, 0xde, 0x7a, 0x6e, 0x0f, 0x1d, 0xfe, 0x84, 0x1e, 0x7a, 0x60, 0x7a, 0xe2, - 0xd8, 0x69, 0x67, 0x42, 0x87, 0x1c, 0x7a, 0xcf, 0xb1, 0xa7, 0xce, 0x4a, 0xab, 0xb5, 0x9c, 0x48, - 0x38, 0x32, 0xee, 0xa1, 0x97, 0x44, 0xbb, 0xfb, 0x7e, 0x7c, 0xde, 0xdb, 0xf7, 0x79, 0xbb, 0x6b, - 0xf0, 0x7f, 0x42, 0xbb, 0x84, 0x5a, 0x54, 0xa3, 0x7e, 0x0f, 0xbb, 0x6b, 0xb6, 0x6f, 0x21, 0xcd, - 0xdb, 0x52, 0x7b, 0x2e, 0xf1, 0x88, 0x2c, 0xf3, 0x45, 0xb5, 0xbf, 0x58, 0x3c, 0x69, 0x12, 0x93, - 0x04, 0xcb, 0x1a, 0xfb, 0x0a, 0x25, 0x8b, 0x73, 0x46, 0xd7, 0x72, 0x88, 0x16, 0xfc, 0xe5, 0x53, - 0x25, 0x93, 0x10, 0xd3, 0xc6, 0x5a, 0x30, 0x6a, 0xfb, 0x6b, 0x1a, 0xf2, 0x5d, 0xc3, 0xb3, 0x88, - 0x13, 0xad, 0x77, 0x02, 0xeb, 0x5a, 0xdb, 0xa0, 0x58, 0xdb, 0xa8, 0xb6, 0xb1, 0x67, 0x54, 0xb5, - 0x0e, 0xb1, 0xa2, 0x75, 0x65, 0xaf, 0xbe, 0x67, 0x75, 0x31, 0xf5, 0x8c, 0x6e, 0x8f, 0x0b, 0x5c, - 0x4c, 0x80, 0xde, 0xff, 0x0c, 0x85, 0xe0, 0x77, 0x12, 0x38, 0xd5, 0xa4, 0xe6, 0x43, 0x31, 0x5f, - 0xc7, 0x36, 0x36, 0x0d, 0x0f, 0xcb, 0x57, 0xc0, 0x14, 0xc5, 0x0e, 0xc2, 0x6e, 0x41, 0x2a, 0x4b, - 0xf3, 0x47, 0x6a, 0x73, 0xbb, 0xdb, 0xca, 0xec, 0x33, 0xa3, 0x6b, 0x2f, 0xc2, 0x70, 0x1e, 0xea, - 0x5c, 0x40, 0x3e, 0x03, 0xa6, 0x6d, 0xd2, 0x59, 0x6f, 0x59, 0xa8, 0x90, 0x2b, 0x4b, 0xf3, 0x93, - 0xfa, 0x14, 0x1b, 0x36, 0x90, 0x7c, 0x16, 0x1c, 0xde, 0x30, 0xec, 0x96, 0x81, 0x90, 0x5b, 0xc8, - 0x33, 0x2b, 0xfa, 0xf4, 0x86, 0x61, 0x2f, 0x21, 0xe4, 0x2e, 0x96, 0x9f, 0xff, 0xf5, 0xf2, 0x6a, - 0x42, 0x76, 0x2b, 0x88, 0x03, 0x80, 0x0a, 0x38, 0x9f, 0x88, 0x4c, 0xc7, 0xb4, 0x47, 0x1c, 0x8a, - 0xe1, 0x57, 0x12, 0x38, 0x33, 0x20, 0xf1, 0xc8, 0x41, 0x63, 0x44, 0xbf, 0x08, 0x19, 0xc4, 0xf3, - 0x09, 0x10, 0x7d, 0xe1, 0x07, 0x5e, 0x00, 0x4a, 0x0a, 0x04, 0x01, 0xf3, 0xeb, 0xfd, 0x30, 0xdb, - 0xc4, 0x41, 0x2b, 0xa4, 0xb3, 0x3e, 0x16, 0x98, 0x17, 0x19, 0xcc, 0x52, 0x22, 0x4c, 0xe6, 0xa7, - 0xc2, 0xc4, 0x12, 0x70, 0x46, 0x18, 0x04, 0xce, 0x9f, 0x24, 0x70, 0x29, 0x25, 0x96, 0x25, 0x67, - 0xcc, 0xa0, 0xe5, 0x1a, 0x98, 0x64, 0xb5, 0x1c, 0x54, 0xc5, 0xcc, 0x8d, 0xb3, 0x6a, 0x58, 0xec, - 0x2a, 0x2b, 0x76, 0x95, 0x17, 0xbb, 0xba, 0x4c, 0x2c, 0xa7, 0xf6, 0xbf, 0x57, 0xdb, 0xca, 0xc4, - 0xee, 0xb6, 0x32, 0x13, 0x3a, 0x60, 0x4a, 0x50, 0x0f, 0x74, 0xe1, 0x27, 0xe0, 0xfa, 0x41, 0xf0, - 0x46, 0x01, 0xc6, 0xc1, 0x48, 0x71, 0x30, 0x70, 0x57, 0x02, 0xe7, 0x9a, 0xd4, 0x64, 0xc2, 0x4b, - 0x0e, 0x7a, 0x3f, 0x2e, 0x18, 0xe0, 0x10, 0x03, 0x47, 0x0b, 0xb9, 0x72, 0xfe, 0xdd, 0x91, 0x2d, - 0xb0, 0xc8, 0x7e, 0x7c, 0xa3, 0xcc, 0x9b, 0x96, 0xf7, 0xc4, 0x6f, 0xab, 0x1d, 0xd2, 0xd5, 0x38, - 0xe7, 0xc3, 0x7f, 0x15, 0x8a, 0xd6, 0x35, 0xef, 0x59, 0x0f, 0xd3, 0x40, 0x81, 0xea, 0xa1, 0xe5, - 0x77, 0xb1, 0xea, 0x0a, 0xab, 0x85, 0x4b, 0x51, 0x2d, 0xb0, 0xf0, 0x2a, 0x86, 0x83, 0x2a, 0x49, - 0xf4, 0xba, 0x15, 0xec, 0x76, 0x6a, 0xcc, 0x22, 0x6b, 0xc7, 0x40, 0xae, 0x51, 0xe7, 0x09, 0xcb, - 0x35, 0xea, 0xf0, 0x65, 0x0e, 0x68, 0x4d, 0x6a, 0x2e, 0xbb, 0xd8, 0xf0, 0xf0, 0x3d, 0xdf, 0xb6, - 0x75, 0xc3, 0x31, 0xf1, 0x03, 0x42, 0x2d, 0xd6, 0xbc, 0xfe, 0xdb, 0xf9, 0x93, 0xaf, 0x81, 0xe9, - 0x1e, 0x21, 0x36, 0x2b, 0x91, 0x49, 0x16, 0x71, 0x4d, 0xde, 0xdd, 0x56, 0x8e, 0x85, 0x48, 0xf9, - 0x02, 0xd4, 0xa7, 0xd8, 0x57, 0x03, 0x2d, 0x7e, 0xc8, 0x92, 0x0d, 0xa3, 0x64, 0xaf, 0xf9, 0xb6, - 0x5d, 0x71, 0x59, 0x2e, 0xc2, 0x94, 0xaf, 0xf5, 0x53, 0xfd, 0x14, 0xdc, 0xce, 0x98, 0x31, 0x91, - 0xfd, 0xd3, 0x20, 0x2c, 0xd2, 0xfa, 0x40, 0xc9, 0xd6, 0xe5, 0x12, 0x00, 0x3d, 0x6e, 0xa0, 0x51, - 0xe7, 0xdc, 0x8a, 0xcd, 0xb0, 0xbe, 0x5e, 0x68, 0x52, 0xf3, 0x91, 0xf3, 0x80, 0x10, 0xfb, 0xf3, - 0x27, 0x96, 0x87, 0x6d, 0x8b, 0x7a, 0x18, 0xb1, 0x61, 0x96, 0xed, 0x88, 0x25, 0x24, 0x37, 0x34, - 0x21, 0x97, 0x58, 0x42, 0x94, 0x28, 0x21, 0xbe, 0xc3, 0xa6, 0x2b, 0x9b, 0x7d, 0xe7, 0x15, 0x36, - 0x01, 0xef, 0x83, 0x72, 0x1a, 0x32, 0x11, 0xf6, 0x65, 0x70, 0x1c, 0x6f, 0x59, 0x1e, 0x46, 0x2d, - 0xce, 0x58, 0x5a, 0x90, 0xca, 0xf9, 0xf9, 0x49, 0x7d, 0x36, 0x9c, 0x5e, 0x09, 0x88, 0x4b, 0xe1, - 0x0f, 0x79, 0x70, 0x27, 0x30, 0x66, 0x87, 0x75, 0xdc, 0xb4, 0x4c, 0xd7, 0xf0, 0xf0, 0xc3, 0x27, - 0x86, 0x8b, 0xe9, 0x2a, 0x11, 0xc9, 0x5e, 0x26, 0x4e, 0x07, 0x3b, 0x1e, 0x5b, 0x43, 0x51, 0xe2, - 0x33, 0xa6, 0x21, 0xde, 0xc7, 0xf2, 0xf1, 0x34, 0xf0, 0x05, 0x28, 0x7a, 0x9b, 0x09, 0xe6, 0x68, - 0x00, 0xa0, 0xe5, 0x91, 0x56, 0x37, 0x44, 0x34, 0xbc, 0xd1, 0x95, 0x79, 0xa3, 0x2b, 0x70, 0x04, - 0x7b, 0x2d, 0x40, 0xfd, 0x38, 0xe5, 0x61, 0xf1, 0x28, 0xe5, 0xe7, 0x12, 0x38, 0xe6, 0x91, 0x75, - 0xec, 0xb4, 0x88, 0xef, 0xb5, 0xba, 0x8c, 0x35, 0x93, 0xc3, 0x58, 0xd3, 0xe0, 0x6e, 0x4e, 0x85, - 0x6e, 0x06, 0xd5, 0x61, 0x26, 0x3a, 0x1d, 0x0d, 0x94, 0x3f, 0xf3, 0xbd, 0xa6, 0xe5, 0xd0, 0x45, - 0x85, 0x6d, 0x7e, 0xb1, 0xbf, 0xf9, 0xa2, 0xf9, 0x44, 0xf8, 0x7f, 0xcd, 0x83, 0xbb, 0xa3, 0xee, - 0x95, 0x28, 0x8c, 0xc7, 0x60, 0xda, 0xe8, 0x12, 0xdf, 0xf1, 0x16, 0xf8, 0xa6, 0xdd, 0x65, 0xf1, - 0xfc, 0xbe, 0xad, 0x5c, 0x3e, 0x00, 0xec, 0x86, 0xe3, 0xf5, 0xb7, 0x8d, 0x9b, 0x81, 0x7a, 0x64, - 0xb0, 0x6f, 0xbb, 0x1a, 0x6c, 0xf2, 0x7b, 0xdb, 0xae, 0x0a, 0xdb, 0x55, 0x79, 0x13, 0xcc, 0xd9, - 0xd6, 0x53, 0xdf, 0x42, 0x96, 0xf7, 0xac, 0xd5, 0x09, 0x3a, 0x01, 0x0a, 0x9b, 0x4f, 0xed, 0x7e, - 0x06, 0x2f, 0x75, 0xdc, 0xe9, 0x97, 0xc8, 0x3e, 0x83, 0x50, 0x3f, 0x21, 0xe6, 0xc2, 0x6e, 0x83, - 0xe4, 0x47, 0xe0, 0xc8, 0x17, 0xc4, 0x72, 0x5a, 0xec, 0x76, 0x18, 0xf4, 0xb4, 0x99, 0x1b, 0x45, - 0x35, 0xbc, 0x3a, 0xaa, 0xd1, 0xd5, 0x51, 0x5d, 0x8d, 0xae, 0x8e, 0xb5, 0x73, 0xbc, 0x3c, 0x4e, - 0x84, 0x2e, 0x84, 0x2a, 0x7c, 0xf1, 0x46, 0x91, 0xf4, 0xc3, 0x6c, 0xcc, 0x84, 0xe1, 0x37, 0xf9, - 0xe0, 0x14, 0x58, 0x42, 0x68, 0x95, 0xc4, 0x37, 0x6c, 0x25, 0xf2, 0xdf, 0xef, 0x69, 0x82, 0x6f, - 0xb7, 0xc1, 0x4c, 0xd4, 0xa1, 0xc4, 0x19, 0x5c, 0x3b, 0xbd, 0xbb, 0xad, 0xc8, 0x51, 0x3f, 0x11, - 0x8b, 0x30, 0xd6, 0xcc, 0x50, 0x8c, 0xa8, 0xb9, 0x61, 0x44, 0x6d, 0x45, 0x8c, 0x40, 0x98, 0x5a, - 0x2e, 0x46, 0x0b, 0xc3, 0x89, 0x77, 0x3e, 0x89, 0x11, 0x91, 0x3a, 0xd4, 0x67, 0x83, 0x89, 0x3a, - 0x1f, 0xef, 0x73, 0x50, 0xe5, 0x49, 0x1d, 0xd1, 0x41, 0x75, 0x8f, 0x83, 0xea, 0xe2, 0x55, 0xc6, - 0xa3, 0x0f, 0x22, 0x1e, 0x19, 0x08, 0x55, 0x3c, 0x52, 0xe9, 0xd8, 0xf1, 0x33, 0x3c, 0x4a, 0x0d, - 0xfc, 0x25, 0x1f, 0x9c, 0x2c, 0x59, 0x76, 0x41, 0x30, 0x69, 0xe4, 0xdd, 0x88, 0x51, 0x30, 0xf7, - 0x2f, 0x52, 0x30, 0x3f, 0x6e, 0x0a, 0xae, 0x83, 0x59, 0x07, 0x6f, 0xb6, 0x04, 0x43, 0x0a, 0x87, - 0x02, 0x0f, 0xf7, 0x32, 0xd3, 0xef, 0x64, 0xe8, 0x61, 0xc0, 0x18, 0xd4, 0x8f, 0x3a, 0x78, 0x53, - 0xe4, 0x3d, 0x7e, 0x60, 0xec, 0xbb, 0x48, 0xec, 0x3d, 0x30, 0x6e, 0xfc, 0x0d, 0x40, 0xbe, 0x49, - 0x4d, 0xd9, 0x05, 0x72, 0xd2, 0xe5, 0x49, 0xdd, 0xff, 0xcc, 0x54, 0x13, 0x5f, 0x46, 0xc5, 0xea, - 0x81, 0x45, 0x45, 0x19, 0x6c, 0x81, 0x93, 0x89, 0x0f, 0xa8, 0x6b, 0x43, 0x4d, 0xf5, 0x85, 0x8b, - 0x37, 0x33, 0x08, 0xa7, 0x79, 0x16, 0xcf, 0x8b, 0x83, 0x78, 0x8e, 0x84, 0x0f, 0xe4, 0x79, 0xdf, - 0x43, 0xe0, 0x7b, 0x09, 0x5c, 0x18, 0xfe, 0xcc, 0xb9, 0x93, 0x21, 0xa8, 0x01, 0xcd, 0xe2, 0xdd, - 0x51, 0x35, 0x05, 0xc2, 0x6f, 0x25, 0x70, 0x36, 0xfd, 0x39, 0xb2, 0x90, 0x62, 0x3f, 0x55, 0xa3, - 0x78, 0x27, 0xab, 0x86, 0x40, 0xf2, 0xb3, 0x04, 0xae, 0x67, 0xba, 0xeb, 0x2f, 0xa7, 0xb8, 0xca, - 0x62, 0xa4, 0xf8, 0xe9, 0x18, 0x8c, 0x88, 0x10, 0xbe, 0x04, 0xa7, 0x92, 0xef, 0xc1, 0xd7, 0x53, - 0xbc, 0x24, 0x4a, 0x17, 0x3f, 0xca, 0x22, 0x2d, 0x9c, 0xff, 0x21, 0x81, 0x8f, 0x47, 0xbb, 0x9e, - 0xae, 0xa4, 0xfa, 0x1b, 0xc1, 0x5a, 0x71, 0x75, 0x9c, 0xd6, 0x06, 0xaa, 0x23, 0xd3, 0x1d, 0x20, - 0xad, 0x3a, 0xb2, 0x18, 0x49, 0xad, 0x8e, 0x51, 0xce, 0xc1, 0xda, 0x83, 0x57, 0x6f, 0x4b, 0xd2, - 0xeb, 0xb7, 0x25, 0xe9, 0xcf, 0xb7, 0x25, 0xe9, 0xc5, 0x4e, 0x69, 0xe2, 0xf5, 0x4e, 0x69, 0xe2, - 0xb7, 0x9d, 0xd2, 0xc4, 0xe3, 0x5b, 0xb1, 0x13, 0x81, 0x3b, 0xac, 0xd8, 0x46, 0x9b, 0x46, 0x03, - 0x6d, 0xa3, 0x7a, 0x4b, 0xdb, 0x1a, 0xf8, 0x65, 0x90, 0x9d, 0x12, 0xed, 0xa9, 0xe0, 0x5e, 0x75, - 0xf3, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xce, 0x7c, 0x80, 0xa0, 0x3c, 0x14, 0x00, 0x00, + // 1385 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcb, 0x73, 0xd3, 0xc6, + 0x1f, 0x8f, 0xec, 0x90, 0xc0, 0x86, 0x00, 0xd1, 0x8f, 0x87, 0xf1, 0x0f, 0x2c, 0xb3, 0x50, 0x1a, + 0x1e, 0x96, 0x62, 0x68, 0x81, 0xc9, 0x89, 0x38, 0x1e, 0x3a, 0xa6, 0xf1, 0x94, 0x11, 0x61, 0x3a, + 0xc3, 0xc5, 0x23, 0x7b, 0x37, 0x42, 0x8d, 0xac, 0x35, 0x5a, 0x29, 0x09, 0xd3, 0x53, 0x1f, 0x33, + 0x9d, 0x61, 0x7a, 0xe0, 0xd8, 0x5b, 0xcf, 0xed, 0xa1, 0xc3, 0x9f, 0xd0, 0x43, 0x0f, 0x4c, 0x4f, + 0x1c, 0x3b, 0xed, 0x4c, 0xe8, 0xc0, 0xa1, 0xf7, 0xfc, 0x05, 0x9d, 0x95, 0x56, 0x6b, 0x39, 0x91, + 0x70, 0x64, 0xcc, 0xa1, 0x17, 0xb0, 0x76, 0xbf, 0x8f, 0xcf, 0xf7, 0xf3, 0x7d, 0xec, 0x6e, 0xc0, + 0xff, 0x09, 0xed, 0x12, 0x6a, 0x51, 0x8d, 0xfa, 0x3d, 0xec, 0xae, 0xd9, 0xbe, 0x85, 0x34, 0x6f, + 0x4b, 0xed, 0xb9, 0xc4, 0x23, 0xb2, 0xcc, 0x37, 0xd5, 0xfe, 0x66, 0xf1, 0xb8, 0x49, 0x4c, 0x12, + 0x6c, 0x6b, 0xec, 0x57, 0x28, 0x59, 0x9c, 0x33, 0xba, 0x96, 0x43, 0xb4, 0xe0, 0x5f, 0xbe, 0x54, + 0x32, 0x09, 0x31, 0x6d, 0xac, 0x05, 0x5f, 0x6d, 0x7f, 0x4d, 0x43, 0xbe, 0x6b, 0x78, 0x16, 0x71, + 0xa2, 0xfd, 0x4e, 0x60, 0x5d, 0x6b, 0x1b, 0x14, 0x6b, 0x1b, 0xd5, 0x36, 0xf6, 0x8c, 0xaa, 0xd6, + 0x21, 0x56, 0xb4, 0xaf, 0xec, 0xd6, 0xf7, 0xac, 0x2e, 0xa6, 0x9e, 0xd1, 0xed, 0x71, 0x81, 0xf3, + 0x09, 0xd0, 0xfb, 0x3f, 0x43, 0x21, 0xf8, 0x83, 0x04, 0x4e, 0x34, 0xa9, 0x79, 0x5f, 0xac, 0xd7, + 0xb1, 0x8d, 0x4d, 0xc3, 0xc3, 0xf2, 0x25, 0x30, 0x45, 0xb1, 0x83, 0xb0, 0x5b, 0x90, 0xca, 0xd2, + 0xfc, 0xa1, 0xda, 0xdc, 0xce, 0xb6, 0x32, 0xfb, 0xc4, 0xe8, 0xda, 0x8b, 0x30, 0x5c, 0x87, 0x3a, + 0x17, 0x90, 0x4f, 0x81, 0x69, 0x9b, 0x74, 0xd6, 0x5b, 0x16, 0x2a, 0xe4, 0xca, 0xd2, 0xfc, 0xa4, + 0x3e, 0xc5, 0x3e, 0x1b, 0x48, 0x3e, 0x0d, 0x0e, 0x6e, 0x18, 0x76, 0xcb, 0x40, 0xc8, 0x2d, 0xe4, + 0x99, 0x15, 0x7d, 0x7a, 0xc3, 0xb0, 0x97, 0x10, 0x72, 0x17, 0xcb, 0x4f, 0xff, 0x79, 0x7e, 0x39, + 0x81, 0xdd, 0x0a, 0xe2, 0x00, 0xa0, 0x02, 0xce, 0x26, 0x22, 0xd3, 0x31, 0xed, 0x11, 0x87, 0x62, + 0xf8, 0x95, 0x04, 0x4e, 0x0d, 0x48, 0x3c, 0x70, 0xd0, 0x18, 0xd1, 0x2f, 0x42, 0x06, 0xf1, 0x6c, + 0x02, 0x44, 0x5f, 0xf8, 0x81, 0xe7, 0x80, 0x92, 0x02, 0x41, 0xc0, 0xfc, 0x5e, 0x02, 0x67, 0x9a, + 0xd4, 0xbc, 0x43, 0xdc, 0x0e, 0x7e, 0x6f, 0x58, 0xe7, 0x19, 0x56, 0x91, 0xf1, 0x35, 0xe6, 0xab, + 0x92, 0x8c, 0xf8, 0x22, 0xb8, 0xf0, 0x36, 0x34, 0x02, 0xf6, 0xd7, 0x7b, 0xd9, 0x6d, 0x13, 0x07, + 0xad, 0x90, 0xce, 0xfa, 0x58, 0x10, 0x9f, 0x67, 0x88, 0x4b, 0x89, 0xec, 0x32, 0x3f, 0x15, 0x26, + 0x96, 0x40, 0x6f, 0x84, 0x41, 0xe0, 0xfc, 0x45, 0x0a, 0x02, 0x4a, 0x8a, 0x65, 0xc9, 0x19, 0x33, + 0x68, 0xb9, 0x06, 0x26, 0x59, 0x0b, 0x06, 0xc5, 0x3c, 0x73, 0xed, 0xb4, 0x1a, 0xf6, 0xa8, 0xca, + 0x7a, 0x54, 0xe5, 0x3d, 0xaa, 0x2e, 0x13, 0xcb, 0xa9, 0xfd, 0xef, 0xc5, 0xb6, 0x32, 0xb1, 0xb3, + 0xad, 0xcc, 0x84, 0x0e, 0x98, 0x12, 0xd4, 0x03, 0x5d, 0xf8, 0x09, 0xb8, 0xba, 0x1f, 0xbc, 0x51, + 0x80, 0x71, 0x30, 0x52, 0x1c, 0x0c, 0xdc, 0x09, 0x0b, 0x8b, 0x09, 0x2f, 0x39, 0xe8, 0xdd, 0x5a, + 0xd8, 0x00, 0x07, 0x18, 0x38, 0x5a, 0xc8, 0x95, 0xf3, 0x6f, 0x8f, 0x6c, 0x81, 0x45, 0xf6, 0xf3, + 0x2b, 0x65, 0xde, 0xb4, 0xbc, 0x47, 0x7e, 0x5b, 0xed, 0x90, 0xae, 0xc6, 0x47, 0x55, 0xf8, 0x5f, + 0x85, 0xa2, 0x75, 0xcd, 0x7b, 0xd2, 0xc3, 0x34, 0x50, 0xa0, 0x7a, 0x68, 0xf9, 0x6d, 0xc3, 0xe0, + 0x12, 0xab, 0x85, 0x0b, 0x51, 0x2d, 0xb0, 0xf0, 0x2a, 0x86, 0x83, 0x2a, 0x49, 0x53, 0xe1, 0x46, + 0x90, 0xed, 0xd4, 0x98, 0x05, 0x6b, 0x47, 0x40, 0xae, 0x51, 0xe7, 0x84, 0xe5, 0x1a, 0x75, 0xf8, + 0x3c, 0x07, 0xb4, 0x26, 0x35, 0x97, 0x5d, 0x6c, 0x78, 0xf8, 0x8e, 0x6f, 0xdb, 0xba, 0xe1, 0x98, + 0xf8, 0x1e, 0xa1, 0x16, 0x9b, 0xb9, 0xff, 0x6d, 0xfe, 0xe4, 0x2b, 0x60, 0xba, 0x47, 0x88, 0xcd, + 0x4a, 0x64, 0x92, 0x45, 0x5c, 0x93, 0x77, 0xb6, 0x95, 0x23, 0x21, 0x52, 0xbe, 0x01, 0xf5, 0x29, + 0xf6, 0xab, 0x81, 0x16, 0x3f, 0x64, 0x64, 0x43, 0x31, 0x2a, 0x7c, 0xdb, 0xae, 0xb8, 0x8c, 0x8b, + 0x90, 0xf2, 0xb5, 0x3e, 0xd5, 0x8f, 0xc1, 0xcd, 0x8c, 0x8c, 0x09, 0xf6, 0x4f, 0x82, 0xb0, 0x48, + 0xeb, 0x03, 0x25, 0x5b, 0x97, 0x4b, 0x00, 0xf4, 0xb8, 0x81, 0x46, 0x9d, 0xf7, 0x56, 0x6c, 0x85, + 0x1d, 0x47, 0x85, 0x26, 0x35, 0x1f, 0x38, 0xf7, 0x08, 0xb1, 0x3f, 0x7f, 0x64, 0x79, 0xd8, 0xb6, + 0xa8, 0x87, 0x11, 0xfb, 0xcc, 0x92, 0x8e, 0x18, 0x21, 0xb9, 0xa1, 0x84, 0x5c, 0x60, 0x84, 0x28, + 0x11, 0x21, 0xbe, 0xc3, 0x96, 0x2b, 0x9b, 0x7d, 0xe7, 0x15, 0xb6, 0x00, 0xef, 0x82, 0x72, 0x1a, + 0x32, 0x11, 0xf6, 0x45, 0x70, 0x14, 0x6f, 0x59, 0x1e, 0x46, 0x2d, 0xde, 0xb1, 0xb4, 0x20, 0x95, + 0xf3, 0xf3, 0x93, 0xfa, 0x6c, 0xb8, 0xbc, 0x12, 0x34, 0x2e, 0x85, 0x3f, 0xe5, 0xc1, 0xad, 0xc0, + 0x98, 0x1d, 0xd6, 0x71, 0xd3, 0x32, 0x5d, 0xc3, 0xc3, 0xf7, 0x1f, 0x19, 0x2e, 0xa6, 0xab, 0x44, + 0x90, 0xbd, 0x4c, 0x9c, 0x0e, 0x76, 0x3c, 0xb6, 0x87, 0x22, 0xe2, 0x33, 0xd2, 0x10, 0x9f, 0x63, + 0xf9, 0x38, 0x0d, 0x7c, 0x03, 0x8a, 0xd9, 0x66, 0x82, 0x39, 0x1a, 0x00, 0x68, 0x79, 0xa4, 0xd5, + 0x0d, 0x11, 0x0d, 0x1f, 0x74, 0x65, 0x3e, 0xe8, 0x0a, 0x1c, 0xc1, 0x6e, 0x0b, 0x50, 0x3f, 0x4a, + 0x79, 0x58, 0x3c, 0x4a, 0xf9, 0xa9, 0x04, 0x8e, 0x78, 0x64, 0x1d, 0x3b, 0x2d, 0xe2, 0x7b, 0xad, + 0x2e, 0xeb, 0x9a, 0xc9, 0x61, 0x5d, 0xd3, 0xe0, 0x6e, 0x4e, 0x84, 0x6e, 0x06, 0xd5, 0x61, 0xa6, + 0x76, 0x3a, 0x1c, 0x28, 0x7f, 0xe6, 0x7b, 0x4d, 0xcb, 0xa1, 0x8b, 0x0a, 0x4b, 0x7e, 0xb1, 0x9f, + 0x7c, 0x31, 0x7c, 0x22, 0xfc, 0xbf, 0xe7, 0xc1, 0xed, 0x51, 0x73, 0x25, 0x0a, 0xe3, 0x21, 0x98, + 0x36, 0xba, 0xc4, 0x77, 0xbc, 0x05, 0x9e, 0xb4, 0xdb, 0x2c, 0x9e, 0x3f, 0xb7, 0x95, 0x8b, 0xfb, + 0x80, 0xdd, 0x70, 0xbc, 0x7e, 0xda, 0xb8, 0x19, 0xa8, 0x47, 0x06, 0xfb, 0xb6, 0xab, 0x41, 0x92, + 0xdf, 0xd9, 0x76, 0x55, 0xd8, 0xae, 0xca, 0x9b, 0x60, 0xce, 0xb6, 0x1e, 0xfb, 0x16, 0xb2, 0xbc, + 0x27, 0xad, 0x4e, 0x30, 0x09, 0x50, 0x38, 0x7c, 0x6a, 0x77, 0x33, 0x78, 0xa9, 0xe3, 0x4e, 0xbf, + 0x44, 0xf6, 0x18, 0x84, 0xfa, 0x31, 0xb1, 0x16, 0x4e, 0x1b, 0x24, 0x3f, 0x00, 0x87, 0xbe, 0x20, + 0x96, 0xd3, 0x62, 0x97, 0xda, 0x60, 0xa6, 0xcd, 0x5c, 0x2b, 0xaa, 0xe1, 0x8d, 0x57, 0x8d, 0x6e, + 0xbc, 0xea, 0x6a, 0x74, 0xe3, 0xad, 0x9d, 0xe1, 0xe5, 0x71, 0x2c, 0x74, 0x21, 0x54, 0xe1, 0xb3, + 0x57, 0x8a, 0xa4, 0x1f, 0x64, 0xdf, 0x4c, 0x18, 0x7e, 0x93, 0x0f, 0x4e, 0x81, 0x25, 0x84, 0x56, + 0x49, 0x3c, 0x61, 0x2b, 0x91, 0xff, 0xfe, 0x4c, 0x13, 0xfd, 0x76, 0x13, 0xcc, 0x44, 0x13, 0x4a, + 0x9c, 0xc1, 0xb5, 0x93, 0x3b, 0xdb, 0x8a, 0x1c, 0xcd, 0x13, 0xb1, 0x09, 0x63, 0xc3, 0x0c, 0xc5, + 0x1a, 0x35, 0x37, 0xac, 0x51, 0x5b, 0x51, 0x47, 0x20, 0x4c, 0x2d, 0x17, 0xa3, 0x85, 0xe1, 0x8d, + 0x77, 0x36, 0xa9, 0x23, 0x22, 0x75, 0xa8, 0xcf, 0x06, 0x0b, 0x75, 0xfe, 0xbd, 0xc7, 0x41, 0x95, + 0x93, 0x3a, 0xa2, 0x83, 0xea, 0x2e, 0x07, 0xd5, 0xc5, 0xcb, 0xac, 0x8f, 0x3e, 0x88, 0xfa, 0xc8, + 0x40, 0xa8, 0xe2, 0x91, 0x4a, 0xc7, 0x8e, 0x9f, 0xe1, 0x11, 0x35, 0xf0, 0xb7, 0x7c, 0x70, 0xb2, + 0x64, 0xc9, 0x82, 0xe8, 0xa4, 0x91, 0xb3, 0x11, 0x6b, 0xc1, 0xdc, 0x7b, 0x6c, 0xc1, 0xfc, 0xb8, + 0x5b, 0x70, 0x1d, 0xcc, 0x3a, 0x78, 0xb3, 0x25, 0x3a, 0xa4, 0x70, 0x20, 0xf0, 0x70, 0x27, 0x73, + 0xfb, 0x1d, 0x0f, 0x3d, 0x0c, 0x18, 0x83, 0xfa, 0x61, 0x07, 0x6f, 0x0a, 0xde, 0xe3, 0x07, 0xc6, + 0x9e, 0x8b, 0xc4, 0xee, 0x03, 0xe3, 0xda, 0xb7, 0x87, 0x41, 0xbe, 0x49, 0x4d, 0xd9, 0x05, 0x72, + 0xd2, 0xe5, 0x49, 0xdd, 0xfb, 0x3a, 0x56, 0x13, 0x1f, 0x74, 0xc5, 0xea, 0xbe, 0x45, 0x45, 0x19, + 0x6c, 0x81, 0xe3, 0x89, 0x6f, 0xa9, 0x2b, 0x43, 0x4d, 0xf5, 0x85, 0x8b, 0xd7, 0x33, 0x08, 0x0b, + 0xcf, 0xdf, 0x49, 0xe0, 0x74, 0xfa, 0x5b, 0x6e, 0x21, 0xc5, 0x64, 0xaa, 0x46, 0xf1, 0x56, 0x56, + 0x8d, 0x34, 0x0e, 0xc4, 0x43, 0x67, 0x3f, 0x1c, 0x44, 0xc2, 0xfb, 0xe2, 0x60, 0xcf, 0x93, 0xe4, + 0x47, 0x09, 0x9c, 0x1b, 0xfe, 0xe0, 0xba, 0x95, 0x81, 0xde, 0x01, 0xcd, 0xe2, 0xed, 0x51, 0x35, + 0x07, 0xb2, 0x94, 0xfe, 0x30, 0x4a, 0xcb, 0x52, 0xaa, 0x46, 0x6a, 0x96, 0x86, 0x3f, 0x44, 0x7e, + 0x95, 0xc0, 0xd5, 0x4c, 0xaf, 0x8e, 0xe5, 0x14, 0x57, 0x59, 0x8c, 0x14, 0x3f, 0x1d, 0x83, 0x11, + 0x11, 0xc2, 0x97, 0xe0, 0x44, 0xf2, 0x8d, 0xfc, 0x6a, 0x8a, 0x97, 0x44, 0xe9, 0xe2, 0x47, 0x59, + 0xa4, 0x85, 0xf3, 0xbf, 0x24, 0xf0, 0xf1, 0x68, 0x17, 0xe5, 0x95, 0x54, 0x7f, 0x23, 0x58, 0x2b, + 0xae, 0x8e, 0xd3, 0xda, 0x40, 0x75, 0x64, 0xba, 0x8d, 0xa4, 0x55, 0x47, 0x16, 0x23, 0xa9, 0xd5, + 0x31, 0xca, 0x89, 0x5c, 0xbb, 0xf7, 0xe2, 0x75, 0x49, 0x7a, 0xf9, 0xba, 0x24, 0xfd, 0xfd, 0xba, + 0x24, 0x3d, 0x7b, 0x53, 0x9a, 0x78, 0xf9, 0xa6, 0x34, 0xf1, 0xc7, 0x9b, 0xd2, 0xc4, 0xc3, 0x1b, + 0xb1, 0xb3, 0x89, 0x3b, 0xac, 0xd8, 0x46, 0x9b, 0x46, 0x1f, 0xda, 0x46, 0xf5, 0x86, 0xb6, 0x35, + 0xf0, 0xa7, 0x55, 0x76, 0x5e, 0xb5, 0xa7, 0x82, 0x1b, 0xde, 0xf5, 0x7f, 0x03, 0x00, 0x00, 0xff, + 0xff, 0x2d, 0x36, 0x7f, 0x6c, 0x7d, 0x15, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1148,6 +1241,7 @@ type MsgClient interface { SuperfluidDelegate(ctx context.Context, in *MsgSuperfluidDelegate, opts ...grpc.CallOption) (*MsgSuperfluidDelegateResponse, error) // Execute superfluid undelegation for a lockup SuperfluidUndelegate(ctx context.Context, in *MsgSuperfluidUndelegate, opts ...grpc.CallOption) (*MsgSuperfluidUndelegateResponse, error) + ForceSuperfluidUndelegate(ctx context.Context, in *MsgForceSuperfluidUndelegate, opts ...grpc.CallOption) (*MsgForceSuperfluidUndelegateResponse, error) // For a given lock that is being superfluidly undelegated, // also unbond the underlying lock. SuperfluidUnbondLock(ctx context.Context, in *MsgSuperfluidUnbondLock, opts ...grpc.CallOption) (*MsgSuperfluidUnbondLockResponse, error) @@ -1187,6 +1281,15 @@ func (c *msgClient) SuperfluidUndelegate(ctx context.Context, in *MsgSuperfluidU return out, nil } +func (c *msgClient) ForceSuperfluidUndelegate(ctx context.Context, in *MsgForceSuperfluidUndelegate, opts ...grpc.CallOption) (*MsgForceSuperfluidUndelegateResponse, error) { + out := new(MsgForceSuperfluidUndelegateResponse) + err := c.cc.Invoke(ctx, "/osmosis.superfluid.Msg/ForceSuperfluidUndelegate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *msgClient) SuperfluidUnbondLock(ctx context.Context, in *MsgSuperfluidUnbondLock, opts ...grpc.CallOption) (*MsgSuperfluidUnbondLockResponse, error) { out := new(MsgSuperfluidUnbondLockResponse) err := c.cc.Invoke(ctx, "/osmosis.superfluid.Msg/SuperfluidUnbondLock", in, out, opts...) @@ -1256,6 +1359,7 @@ type MsgServer interface { SuperfluidDelegate(context.Context, *MsgSuperfluidDelegate) (*MsgSuperfluidDelegateResponse, error) // Execute superfluid undelegation for a lockup SuperfluidUndelegate(context.Context, *MsgSuperfluidUndelegate) (*MsgSuperfluidUndelegateResponse, error) + ForceSuperfluidUndelegate(context.Context, *MsgForceSuperfluidUndelegate) (*MsgForceSuperfluidUndelegateResponse, error) // For a given lock that is being superfluidly undelegated, // also unbond the underlying lock. SuperfluidUnbondLock(context.Context, *MsgSuperfluidUnbondLock) (*MsgSuperfluidUnbondLockResponse, error) @@ -1279,6 +1383,9 @@ func (*UnimplementedMsgServer) SuperfluidDelegate(ctx context.Context, req *MsgS func (*UnimplementedMsgServer) SuperfluidUndelegate(ctx context.Context, req *MsgSuperfluidUndelegate) (*MsgSuperfluidUndelegateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SuperfluidUndelegate not implemented") } +func (*UnimplementedMsgServer) ForceSuperfluidUndelegate(ctx context.Context, req *MsgForceSuperfluidUndelegate) (*MsgForceSuperfluidUndelegateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ForceSuperfluidUndelegate not implemented") +} func (*UnimplementedMsgServer) SuperfluidUnbondLock(ctx context.Context, req *MsgSuperfluidUnbondLock) (*MsgSuperfluidUnbondLockResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SuperfluidUnbondLock not implemented") } @@ -1341,6 +1448,24 @@ func _Msg_SuperfluidUndelegate_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Msg_ForceSuperfluidUndelegate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgForceSuperfluidUndelegate) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ForceSuperfluidUndelegate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.superfluid.Msg/ForceSuperfluidUndelegate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ForceSuperfluidUndelegate(ctx, req.(*MsgForceSuperfluidUndelegate)) + } + return interceptor(ctx, in, info, handler) +} + func _Msg_SuperfluidUnbondLock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(MsgSuperfluidUnbondLock) if err := dec(in); err != nil { @@ -1479,6 +1604,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "SuperfluidUndelegate", Handler: _Msg_SuperfluidUndelegate_Handler, }, + { + MethodName: "ForceSuperfluidUndelegate", + Handler: _Msg_ForceSuperfluidUndelegate_Handler, + }, { MethodName: "SuperfluidUnbondLock", Handler: _Msg_SuperfluidUnbondLock_Handler, @@ -1635,6 +1764,64 @@ func (m *MsgSuperfluidUndelegateResponse) MarshalToSizedBuffer(dAtA []byte) (int return len(dAtA) - i, nil } +func (m *MsgForceSuperfluidUndelegate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgForceSuperfluidUndelegate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgForceSuperfluidUndelegate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LockId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.LockId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgForceSuperfluidUndelegateResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgForceSuperfluidUndelegateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgForceSuperfluidUndelegateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *MsgSuperfluidUnbondLock) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2313,6 +2500,31 @@ func (m *MsgSuperfluidUndelegateResponse) Size() (n int) { return n } +func (m *MsgForceSuperfluidUndelegate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.LockId != 0 { + n += 1 + sovTx(uint64(m.LockId)) + } + return n +} + +func (m *MsgForceSuperfluidUndelegateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func (m *MsgSuperfluidUnbondLock) Size() (n int) { if m == nil { return 0 @@ -2898,6 +3110,157 @@ func (m *MsgSuperfluidUndelegateResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgForceSuperfluidUndelegate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgForceSuperfluidUndelegate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgForceSuperfluidUndelegate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LockId", wireType) + } + m.LockId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LockId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgForceSuperfluidUndelegateResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgForceSuperfluidUndelegateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgForceSuperfluidUndelegateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MsgSuperfluidUnbondLock) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 From 8e06c4e5a53dc5d3cceb289b403fd473a8164d95 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Wed, 19 Jul 2023 21:49:27 +0200 Subject: [PATCH 05/12] Revert "rename to" This reverts commit d0ca709c87c7304f9170a1250e5ec1004a46be6c. --- x/superfluid/keeper/concentrated_liquidity.go | 2 +- x/superfluid/keeper/migrate.go | 2 +- x/superfluid/keeper/stake.go | 6 +++--- x/superfluid/keeper/stake_test.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x/superfluid/keeper/concentrated_liquidity.go b/x/superfluid/keeper/concentrated_liquidity.go index fb1a80c7943..56454d75bf7 100644 --- a/x/superfluid/keeper/concentrated_liquidity.go +++ b/x/superfluid/keeper/concentrated_liquidity.go @@ -76,7 +76,7 @@ func (k Keeper) addToConcentratedLiquiditySuperfluidPosition(ctx sdk.Context, se // Superfluid undelegate the superfluid delegated position. // This deletes the connection between the lock and the intermediate account, deletes the synthetic lock, and burns the synthetic osmo. - intermediateAccount, err := k.ForceSuperfluidUndelegate(ctx, sender.String(), lockId) + intermediateAccount, err := k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), lockId) if err != nil { return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, err } diff --git a/x/superfluid/keeper/migrate.go b/x/superfluid/keeper/migrate.go index ffa5f3cd928..47257b4bfa6 100644 --- a/x/superfluid/keeper/migrate.go +++ b/x/superfluid/keeper/migrate.go @@ -108,7 +108,7 @@ func (k Keeper) migrateSuperfluidBondedBalancerToConcentrated(ctx sdk.Context, // Note that lock's id is the same as the originalLockId since all shares are being migrated // and old lock is deleted gammLockToMigrate = preMigrationLock - intermediateAccount, err = k.ForceSuperfluidUndelegate(ctx, sender.String(), originalLockId) + intermediateAccount, err = k.SuperfluidUndelegateToConcentratedPosition(ctx, sender.String(), originalLockId) if err != nil { return 0, sdk.Int{}, sdk.Int{}, sdk.Dec{}, 0, 0, 0, err } diff --git a/x/superfluid/keeper/stake.go b/x/superfluid/keeper/stake.go index ed4a2b81477..bd40b110a77 100644 --- a/x/superfluid/keeper/stake.go +++ b/x/superfluid/keeper/stake.go @@ -300,12 +300,12 @@ func (k Keeper) SuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint return k.createSyntheticLockup(ctx, lockID, intermediaryAcc, unlockingStatus) } -// ForceSuperfluidUndelegate starts undelegating superfluid delegated position for the given lock. It behaves similarly to SuperfluidUndelegate, +// SuperfluidUndelegateToConcentratedPosition starts undelegating superfluid delegated position for the given lock. It behaves similarly to SuperfluidUndelegate, // however it does not create a new synthetic lockup representing the unstaking side. This is because after the time this function is called, we might // want to perform more operations prior to creating a lock. Once the actual lock is created, the synthetic lockup representing the unstaking side // should eventually be created as well. Use this function with caution to avoid accidentally missing synthetic lock creation. -func (k Keeper) ForceSuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint64) (types.SuperfluidIntermediaryAccount, error) { - return k.undelegateCommon(ctx, sender, lockID) +func (k Keeper) SuperfluidUndelegateToConcentratedPosition(ctx sdk.Context, sender string, gammLockID uint64) (types.SuperfluidIntermediaryAccount, error) { + return k.undelegateCommon(ctx, sender, gammLockID) } // partialUndelegateCommon acts similarly to undelegateCommon, but undelegates a partial amount of the lock's delegation rather than the full amount. The amount diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go index 8cb7722fc2e..9060cca2163 100644 --- a/x/superfluid/keeper/stake_test.go +++ b/x/superfluid/keeper/stake_test.go @@ -529,7 +529,7 @@ func (s *KeeperTestSuite) TestSuperfluidUndelegateToConcentratedPosition() { presupplyWithOffset := s.App.BankKeeper.GetSupplyWithOffset(s.Ctx, bondDenom) // superfluid undelegate - _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, lock.Owner, lockId) + _, err = s.App.SuperfluidKeeper.SuperfluidUndelegateToConcentratedPosition(s.Ctx, lock.Owner, lockId) if tc.expSuperUnbondingErr[index] { s.Require().Error(err) continue @@ -584,7 +584,7 @@ func (s *KeeperTestSuite) TestSuperfluidUndelegateToConcentratedPosition() { lock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) s.Require().NoError(err) - _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, lock.Owner, lockId) + _, err = s.App.SuperfluidKeeper.SuperfluidUndelegateToConcentratedPosition(s.Ctx, lock.Owner, lockId) s.Require().Error(err) } }) From f137cce71b20eedecf801cfb5da265bd4fe513a2 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Wed, 19 Jul 2023 22:20:18 +0200 Subject: [PATCH 06/12] implement force undelegate and test --- x/superfluid/keeper/msg_server.go | 1 + x/superfluid/keeper/msg_server_test.go | 103 +++++++++++++++++++++++++ x/superfluid/keeper/stake.go | 27 +++++-- 3 files changed, 126 insertions(+), 5 deletions(-) diff --git a/x/superfluid/keeper/msg_server.go b/x/superfluid/keeper/msg_server.go index ab98774eeb9..32b8ad41f69 100644 --- a/x/superfluid/keeper/msg_server.go +++ b/x/superfluid/keeper/msg_server.go @@ -72,6 +72,7 @@ func (server msgServer) SuperfluidUndelegate(goCtx context.Context, msg *types.M // ForceSuperfluidUndelegate is a method to force undelegate superfluid staked asset. // This method is only allowed to be called whitelisted addresses. +// With whitelisted addresses, we can force undelegate superfluid staked asset without being a lock owner. func (server msgServer) ForceSuperfluidUndelegate(goCtx context.Context, msg *types.MsgForceSuperfluidUndelegate) (*types.MsgForceSuperfluidUndelegateResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) diff --git a/x/superfluid/keeper/msg_server_test.go b/x/superfluid/keeper/msg_server_test.go index 4817dc1f691..901c9334e4e 100644 --- a/x/superfluid/keeper/msg_server_test.go +++ b/x/superfluid/keeper/msg_server_test.go @@ -3,6 +3,7 @@ package keeper_test import ( "time" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -135,6 +136,108 @@ func (s *KeeperTestSuite) TestMsgSuperfluidUndelegate() { } } +func (s *KeeperTestSuite) TestMsgForceSuperfluidUndelegate() { + + forceSuperfluidUndelegateAllowedAddresses := []string{ + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + } + + type param struct { + lockOwner sdk.AccAddress + undelegator sdk.AccAddress + duration time.Duration + } + + tests := []struct { + name string + param param + expectPass bool + }{ + { + name: "unknown undelegator", + param: param{ + lockOwner: sdk.AccAddress([]byte("addr1---------------")), // setup wallet + undelegator: sdk.AccAddress([]byte("addr2---------------")), + duration: time.Hour * 504, + }, + expectPass: false, + }, + { + name: "allowed undelegator 0", + param: param{ + lockOwner: sdk.AccAddress([]byte("addr1---------------")), // setup wallet + undelegator: sdk.MustAccAddressFromBech32(forceSuperfluidUndelegateAllowedAddresses[0]), + duration: time.Hour * 504, + }, + expectPass: true, + }, + { + name: "allowed undelegator 1", + param: param{ + lockOwner: sdk.AccAddress([]byte("addr1---------------")), // setup wallet + undelegator: sdk.MustAccAddressFromBech32(forceSuperfluidUndelegateAllowedAddresses[0]), + duration: time.Hour * 504, + }, + expectPass: true, + }, + { + name: "allowed undelegator 2", + param: param{ + lockOwner: sdk.AccAddress([]byte("addr1---------------")), // setup wallet + undelegator: sdk.MustAccAddressFromBech32(forceSuperfluidUndelegateAllowedAddresses[0]), + duration: time.Hour * 504, + }, + expectPass: true, + }, + } + + for _, test := range tests { + s.Run(test.name, func() { + s.SetupTest() + + // set params with allowed addresses + params := s.App.SuperfluidKeeper.GetParams(s.Ctx) + s.App.SuperfluidKeeper.SetParams(s.Ctx, types.Params{ + MinimumRiskFactor: params.MinimumRiskFactor, + ForceSuperfluidUndelegateAllowedAddresses: forceSuperfluidUndelegateAllowedAddresses, + }) + + params = s.App.SuperfluidKeeper.GetParams(s.Ctx) + + lockupMsgServer := lockupkeeper.NewMsgServerImpl(s.App.LockupKeeper) + c := sdk.WrapSDKContext(s.Ctx) + + denoms, _ := s.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + + coinsToLock := sdk.NewCoins(sdk.NewCoin(denoms[0], sdk.NewInt(20))) + + s.FundAcc(test.param.lockOwner, coinsToLock) + resp, err := lockupMsgServer.LockTokens(c, lockuptypes.NewMsgLockTokens(test.param.lockOwner, test.param.duration, coinsToLock)) + s.Require().NoError(err) + + valAddrs := s.SetupValidators([]stakingtypes.BondStatus{stakingtypes.Bonded}) + + msgServer := keeper.NewMsgServerImpl(s.App.SuperfluidKeeper) + + // delegate + _, err = msgServer.SuperfluidDelegate(c, types.NewMsgSuperfluidDelegate(test.param.lockOwner, resp.ID, valAddrs[0])) + s.Require().NoError(err) + + // force undelegate + _, err = msgServer.ForceSuperfluidUndelegate(c, types.NewMsgForceSuperfluidUndelegate(test.param.undelegator, resp.ID)) + + if test.expectPass { + s.Require().NoError(err) + s.AssertEventEmitted(s.Ctx, types.TypeEvtForceSuperfluidUndelegate, 1) + } else { + s.Require().Error(err) + } + }) + } +} + func (s *KeeperTestSuite) TestMsgCreateFullRangePositionAndSuperfluidDelegate() { defaultSender := s.TestAccs[0] type param struct { diff --git a/x/superfluid/keeper/stake.go b/x/superfluid/keeper/stake.go index bd40b110a77..8b7eb8f5c22 100644 --- a/x/superfluid/keeper/stake.go +++ b/x/superfluid/keeper/stake.go @@ -132,6 +132,16 @@ func (k Keeper) validateLockForSF(ctx sdk.Context, lock *lockuptypes.PeriodLock, if lock.Owner != sender { return lockuptypes.ErrNotLockOwner } + + err := k.validateLockForSFWithoutCheckingOwner(ctx, lock) + if err != nil { + return err + } + return nil +} + +// basic validation for locks to be eligible for superfluid delegation. This includes checking +func (k Keeper) validateLockForSFWithoutCheckingOwner(ctx sdk.Context, lock *lockuptypes.PeriodLock) error { if lock.Coins.Len() != 1 { return types.ErrMultipleCoinsLockupNotSupported } @@ -242,20 +252,27 @@ func (k Keeper) SuperfluidDelegate(ctx sdk.Context, sender string, lockID uint64 return k.mintOsmoTokensAndDelegate(ctx, amount, acc) } +func (k Keeper) ForceSuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint64) (types.SuperfluidIntermediaryAccount, error) { + validateHasSingleCoin := func(ctx sdk.Context, lock *lockuptypes.PeriodLock, _ string) error { + return k.validateLockForSFWithoutCheckingOwner(ctx, lock) + } + return k.undelegateCommon(ctx, sender, lockID, validateHasSingleCoin) +} + // undelegateCommon is a helper function for SuperfluidUndelegate and superfluidUndelegateToConcentratedPosition. // It performs the following tasks: -// - checks that the lock is valid for superfluid staking +// - checks that the lock is valid with provided validation function // - gets the intermediary account associated with the lock id // - deletes the connection between the lock id and the intermediary account // - deletes the synthetic lockup associated with the lock id // - undelegates the superfluid staking position associated with the lock id and burns the underlying osmo tokens // - returns the intermediary account -func (k Keeper) undelegateCommon(ctx sdk.Context, sender string, lockID uint64) (types.SuperfluidIntermediaryAccount, error) { +func (k Keeper) undelegateCommon(ctx sdk.Context, sender string, lockID uint64, validate func(sdk.Context, *lockuptypes.PeriodLock, string) error) (types.SuperfluidIntermediaryAccount, error) { lock, err := k.lk.GetLockByID(ctx, lockID) if err != nil { return types.SuperfluidIntermediaryAccount{}, err } - err = k.validateLockForSF(ctx, lock, sender) + err = validate(ctx, lock, sender) if err != nil { return types.SuperfluidIntermediaryAccount{}, err } @@ -292,7 +309,7 @@ func (k Keeper) undelegateCommon(ctx sdk.Context, sender string, lockID uint64) // where it is burnt. Note that this method does not include unbonding the lock // itself. func (k Keeper) SuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint64) error { - intermediaryAcc, err := k.undelegateCommon(ctx, sender, lockID) + intermediaryAcc, err := k.undelegateCommon(ctx, sender, lockID, k.validateLockForSF) if err != nil { return err } @@ -305,7 +322,7 @@ func (k Keeper) SuperfluidUndelegate(ctx sdk.Context, sender string, lockID uint // want to perform more operations prior to creating a lock. Once the actual lock is created, the synthetic lockup representing the unstaking side // should eventually be created as well. Use this function with caution to avoid accidentally missing synthetic lock creation. func (k Keeper) SuperfluidUndelegateToConcentratedPosition(ctx sdk.Context, sender string, gammLockID uint64) (types.SuperfluidIntermediaryAccount, error) { - return k.undelegateCommon(ctx, sender, gammLockID) + return k.undelegateCommon(ctx, sender, gammLockID, k.validateLockForSF) } // partialUndelegateCommon acts similarly to undelegateCommon, but undelegates a partial amount of the lock's delegation rather than the full amount. The amount From 3e59a7a669eba6c3a0e7542553e89b028a6d3db8 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Wed, 19 Jul 2023 22:32:00 +0200 Subject: [PATCH 07/12] add test for force undelegate --- x/superfluid/keeper/stake_test.go | 165 ++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go index 9060cca2163..9df4d9f86ec 100644 --- a/x/superfluid/keeper/stake_test.go +++ b/x/superfluid/keeper/stake_test.go @@ -591,6 +591,171 @@ func (s *KeeperTestSuite) TestSuperfluidUndelegateToConcentratedPosition() { } } +func (s *KeeperTestSuite) TestForceSuperfluidUndelegate() { + testCases := []struct { + name string + validatorStats []stakingtypes.BondStatus + superDelegations []superfluidDelegation + superUnbondingLockIds []uint64 + expSuperUnbondingErr []bool + // expected amount of delegation to intermediary account + expInterDelegation []sdk.Dec + }{ + { + "with single validator and single superfluid delegation and single undelegation", + []stakingtypes.BondStatus{stakingtypes.Bonded}, + []superfluidDelegation{{0, 0, 0, 1000000}}, + []uint64{1}, + []bool{false}, + []sdk.Dec{sdk.ZeroDec()}, + }, + { + "with single validator and additional superfluid delegations and single undelegation", + []stakingtypes.BondStatus{stakingtypes.Bonded}, + []superfluidDelegation{{0, 0, 0, 1000000}, {0, 0, 0, 1000000}}, + []uint64{1}, + []bool{false}, + []sdk.Dec{sdk.ZeroDec()}, + }, + { + "with multiple validators and multiple superfluid delegations and multiple undelegations", + []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Bonded}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, + []uint64{1, 2}, + []bool{false, false}, + []sdk.Dec{sdk.ZeroDec()}, + }, + { + "add unbonding validator", + []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonding}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, + []uint64{1, 2}, + []bool{false, false}, + []sdk.Dec{sdk.ZeroDec()}, + }, + { + "add unbonded validator", + []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded}, + []superfluidDelegation{{0, 0, 0, 1000000}, {1, 1, 0, 1000000}}, + []uint64{1, 2}, + []bool{false, false}, + []sdk.Dec{sdk.ZeroDec()}, + }, + { + "undelegating not available lock id", + []stakingtypes.BondStatus{stakingtypes.Bonded}, + []superfluidDelegation{{0, 0, 0, 1000000}}, + []uint64{2}, + []bool{true}, + []sdk.Dec{}, + }, + { + "try undelegating twice for same lock id", + []stakingtypes.BondStatus{stakingtypes.Bonded}, + []superfluidDelegation{{0, 0, 0, 1000000}}, + []uint64{1, 1}, + []bool{false, true}, + []sdk.Dec{sdk.ZeroDec()}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + s.SetupTest() + + notLockOwner := "osmo1notlockowner" + + bondDenom := s.App.StakingKeeper.GetParams(s.Ctx).BondDenom + + // setup validators + valAddrs := s.SetupValidators(tc.validatorStats) + + denoms, _ := s.SetupGammPoolsAndSuperfluidAssets([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + + // setup superfluid delegations + _, intermediaryAccs, _ := s.setupSuperfluidDelegations(valAddrs, tc.superDelegations, denoms) + s.checkIntermediaryAccountDelegations(intermediaryAccs) + + for index, lockId := range tc.superUnbondingLockIds { + // get intermediary account + accAddr := s.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(s.Ctx, lockId) + intermediaryAcc := s.App.SuperfluidKeeper.GetIntermediaryAccount(s.Ctx, accAddr) + valAddr := intermediaryAcc.ValAddr + + lock, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) + if err != nil { + lock = &lockuptypes.PeriodLock{} + } + + // get pre-superfluid delgations osmo supply and supplyWithOffset + presupply := s.App.BankKeeper.GetSupply(s.Ctx, bondDenom) + presupplyWithOffset := s.App.BankKeeper.GetSupplyWithOffset(s.Ctx, bondDenom) + + // superfluid undelegate works eventhough sender is not the lock owner + + _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, notLockOwner, lockId) + if tc.expSuperUnbondingErr[index] { + s.Require().Error(err) + continue + } + s.Require().NoError(err) + + // ensure post-superfluid delegations osmo supplywithoffset is the same while supply is not + postsupply := s.App.BankKeeper.GetSupply(s.Ctx, bondDenom) + postsupplyWithOffset := s.App.BankKeeper.GetSupplyWithOffset(s.Ctx, bondDenom) + s.Require().False(postsupply.IsEqual(presupply), "presupply: %s postsupply: %s", presupply, postsupply) + s.Require().True(postsupplyWithOffset.IsEqual(presupplyWithOffset)) + + // check lockId and intermediary account connection deletion + addr := s.App.SuperfluidKeeper.GetLockIdIntermediaryAccountConnection(s.Ctx, lockId) + s.Require().Equal(addr.String(), "") + + // check bonding synthetic lockup deletion + _, err = s.App.LockupKeeper.GetSyntheticLockup(s.Ctx, lockId, keeper.StakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) + s.Require().Error(err) + + // check unbonding synthetic lockup creation + // since this is the concentrated liquidity path, no new synthetic lockup should be created + synthLock, err := s.App.LockupKeeper.GetSyntheticLockup(s.Ctx, lockId, keeper.UnstakingSyntheticDenom(lock.Coins[0].Denom, valAddr)) + s.Require().Error(err) + s.Require().Nil(synthLock) + } + + // check invariant is fine + reason, broken := keeper.AllInvariants(*s.App.SuperfluidKeeper)(s.Ctx) + s.Require().False(broken, reason) + + // check remaining intermediary account delegation + for index, expDelegation := range tc.expInterDelegation { + acc := intermediaryAccs[index] + valAddr, err := sdk.ValAddressFromBech32(acc.ValAddr) + s.Require().NoError(err) + delegation, found := s.App.StakingKeeper.GetDelegation(s.Ctx, acc.GetAccAddress(), valAddr) + if expDelegation.IsZero() { + s.Require().False(found, "expected no delegation, found delegation w/ %d shares", delegation.Shares) + } else { + s.Require().True(found) + s.Require().Equal(expDelegation, delegation.Shares) + } + } + + // try undelegating twice + for index, lockId := range tc.superUnbondingLockIds { + if tc.expSuperUnbondingErr[index] { + continue + } + + _, err := s.App.LockupKeeper.GetLockByID(s.Ctx, lockId) + s.Require().NoError(err) + + _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, notLockOwner, lockId) + s.Require().Error(err) + } + }) + } +} + // TestSuperfluidUnbondLock tests the following. // 1. test SuperfluidUnbondLock does not work before undelegation // 2. test SuperfluidUnbondLock makes underlying lock start unlocking From dad054ec1b463ac20adab0b6d592ffa8208df31d Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Wed, 19 Jul 2023 22:45:11 +0200 Subject: [PATCH 08/12] ensure authz deser for new msg --- x/superfluid/keeper/stake_test.go | 1 - x/superfluid/types/codec.go | 2 ++ x/superfluid/types/msg_test.go | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/x/superfluid/keeper/stake_test.go b/x/superfluid/keeper/stake_test.go index 9df4d9f86ec..6aea0840d09 100644 --- a/x/superfluid/keeper/stake_test.go +++ b/x/superfluid/keeper/stake_test.go @@ -693,7 +693,6 @@ func (s *KeeperTestSuite) TestForceSuperfluidUndelegate() { presupplyWithOffset := s.App.BankKeeper.GetSupplyWithOffset(s.Ctx, bondDenom) // superfluid undelegate works eventhough sender is not the lock owner - _, err = s.App.SuperfluidKeeper.ForceSuperfluidUndelegate(s.Ctx, notLockOwner, lockId) if tc.expSuperUnbondingErr[index] { s.Require().Error(err) diff --git a/x/superfluid/types/codec.go b/x/superfluid/types/codec.go index aff8c223d21..46ea91aedb0 100644 --- a/x/superfluid/types/codec.go +++ b/x/superfluid/types/codec.go @@ -12,6 +12,7 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgSuperfluidDelegate{}, "osmosis/superfluid-delegate", nil) cdc.RegisterConcrete(&MsgSuperfluidUndelegate{}, "osmosis/superfluid-undelegate", nil) + cdc.RegisterConcrete(&MsgForceSuperfluidUndelegate{}, "osmosis/force-superfluid-undelegate", nil) cdc.RegisterConcrete(&MsgLockAndSuperfluidDelegate{}, "osmosis/lock-and-superfluid-delegate", nil) cdc.RegisterConcrete(&MsgSuperfluidUnbondLock{}, "osmosis/superfluid-unbond-lock", nil) cdc.RegisterConcrete(&MsgSuperfluidUndelegateAndUnbondLock{}, "osmosis/sf-undelegate-and-unbond-lock", nil) @@ -29,6 +30,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { (*sdk.Msg)(nil), &MsgSuperfluidDelegate{}, &MsgSuperfluidUndelegate{}, + &MsgForceSuperfluidUndelegate{}, &MsgLockAndSuperfluidDelegate{}, &MsgSuperfluidUnbondLock{}, &MsgSuperfluidUndelegateAndUnbondLock{}, diff --git a/x/superfluid/types/msg_test.go b/x/superfluid/types/msg_test.go index 3cfafd35c26..d2502486af9 100644 --- a/x/superfluid/types/msg_test.go +++ b/x/superfluid/types/msg_test.go @@ -66,6 +66,13 @@ func TestAuthzMsg(t *testing.T) { PoolId: 1, }, }, + { + name: "MsgForceSuperfluidUndelegate", + msg: &types.MsgForceSuperfluidUndelegate{ + Sender: addr1, + LockId: 1, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { From f11d0d6d70d5302ac167f0ba92795f61ea94a678 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Wed, 19 Jul 2023 22:47:10 +0200 Subject: [PATCH 09/12] fix typo --- x/superfluid/keeper/msg_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/superfluid/keeper/msg_server.go b/x/superfluid/keeper/msg_server.go index 32b8ad41f69..1aaa22a8eea 100644 --- a/x/superfluid/keeper/msg_server.go +++ b/x/superfluid/keeper/msg_server.go @@ -88,7 +88,7 @@ func (server msgServer) ForceSuperfluidUndelegate(goCtx context.Context, msg *ty // return error if the sender is not allowed to force undelegate if !isSenderAllowed { - return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("msg sender (%s) is not allowed to force undeledate superfluid staking position", msg.Sender)) + return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("msg sender (%s) is not allowed to force undelegate superfluid staking position", msg.Sender)) } // perform force undelegate From 1f51038755a42ff874bf91be4793e0d68a13f160 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Thu, 20 Jul 2023 10:21:39 +0200 Subject: [PATCH 10/12] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1777d6906f..f874c0e5592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#5534](https://github.com/osmosis-labs/osmosis/pull/5534) fix: fix the account number of x/tokenfactory module account * [#5750](https://github.com/osmosis-labs/osmosis/pull/5750) feat: add cli commmand for converting proto structs to proto marshalled bytes +* [#5861](https://github.com/osmosis-labs/osmosis/pull/5861) feat: force undelegate superfluid staking position by whitelisted address ## v16.0.0 Osmosis Labs is excited to announce the release of v16.0.0, a major upgrade that includes a number of new features and improvements like introduction of new modules, updates existing APIs, and dependency updates. This upgrade aims to enhance capital efficiency by introducing SuperCharged Liquidity, introduce custom liquidity pools backed by CosmWasm smart contracts, and improve overall functionality. From da5ae845e1ea6c7bf3c14dcea0bf23c3e42d729d Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Thu, 20 Jul 2023 10:29:10 +0200 Subject: [PATCH 11/12] refactor: rename variriable --- x/superfluid/keeper/msg_server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/superfluid/keeper/msg_server.go b/x/superfluid/keeper/msg_server.go index 1aaa22a8eea..e55efd4bf14 100644 --- a/x/superfluid/keeper/msg_server.go +++ b/x/superfluid/keeper/msg_server.go @@ -78,16 +78,16 @@ func (server msgServer) ForceSuperfluidUndelegate(goCtx context.Context, msg *ty // check if the sender is allowed to force undelegate forceUndelegateAllowedAddresses := server.keeper.GetParams(ctx).ForceSuperfluidUndelegateAllowedAddresses - isSenderAllowed := false + allowed := false for _, addr := range forceUndelegateAllowedAddresses { if addr == msg.Sender { - isSenderAllowed = true + allowed = true break } } // return error if the sender is not allowed to force undelegate - if !isSenderAllowed { + if !allowed { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, fmt.Sprintf("msg sender (%s) is not allowed to force undelegate superfluid staking position", msg.Sender)) } From b15612bc767af350cd5210cae4b0e064758734b1 Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Thu, 20 Jul 2023 10:59:56 +0200 Subject: [PATCH 12/12] update readme --- x/superfluid/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x/superfluid/README.md b/x/superfluid/README.md index 2dda8315604..1d036ac579c 100644 --- a/x/superfluid/README.md +++ b/x/superfluid/README.md @@ -292,6 +292,26 @@ type MsgSuperfluidUndelegate struct { - Immediately burn undelegated `Osmo` - Delete the connection between `lockID` and `IntermediaryAccount` +### Superfluid Force Undelegate + +```{.go} +type MsgForceSuperfluidUndelegate struct { + Sender string + LockId uint64 +} +``` + +**State Modifications:** + +- Check if `Sender` is in the list of `ForceSuperfluidUndelegateAllowedAddresses` specified in params store +- Lookup `lock` by `LockID` +- Validate if the lock has single coin, but does not check if `Sender` is `lock.Owner` +- Get the `IntermediaryAccount` for this `lockID` +- Delete the connection between `lockID` and `IntermediaryAccount` +- Delete the `SyntheticLockup` associated to this `lockID` + `ValAddr` + pair +- Undelegates the superfluid staking position associated with the `lockID` and burns the underlying osmo tokens + ### Lock and Superfluid Delegate ```{.go}