From 3f3aa6e2281ed863f6635c41eed168093aeef997 Mon Sep 17 00:00:00 2001 From: ethan Date: Fri, 5 Jan 2024 07:25:32 -0700 Subject: [PATCH 1/5] send disable tokenization tx for delegation account on hub --- app/upgrades/v17/upgrades.go | 34 ++++ proto/stride/stakeibc/ica_account.proto | 12 ++ x/stakeibc/types/ica_account.pb.go | 220 +++++++++++++++++++++--- 3 files changed, 242 insertions(+), 24 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index e24bbcc76..2c84b91c8 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -9,10 +9,12 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/cosmos/gogoproto/proto" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" "github.com/Stride-Labs/stride/v16/utils" + epochstypes "github.com/Stride-Labs/stride/v16/x/epochs/types" icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" ratelimitkeeper "github.com/Stride-Labs/stride/v16/x/ratelimit/keeper" ratelimittypes "github.com/Stride-Labs/stride/v16/x/ratelimit/types" @@ -101,10 +103,42 @@ func CreateUpgradeHandler( return vm, errorsmod.Wrapf(err, "unable to add rate limits to Osmosis") } + ctx.Logger().Info("Disabling tokenization on the hub...") + DisableTokenization(ctx, stakeibcKeeper, "cosmoshub-4") + return mm.RunMigrations(ctx, configurator, vm) } } +// Sends the ICA message which disables LSM style tokenization of shares from the delegation +// account for this chain as a security to prevent possibility of large/fast withdrawls +func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId string) error { + for _, hostZone := range k.GetAllHostZone(ctx) { + if hostZone.ChainId == chainId { + // Timeout for ica tx is at end of epoch + strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) + if !found { + return errorsmod.Wrapf(stakeibctypes.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) + } + timeout := uint64(strideEpochTracker.NextEpochStartTime) + + // Build the msg for the disable tokenization ICA tx + var msgs []proto.Message + msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ + DelegatorAddress: hostZone.DelegationIcaAddress, + }) + + // Send the ICA tx to disable tokenization + delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) + err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeout) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) + } + } + } + return nil +} + // Migrates the host zones to the new structure which supports community pool liquid staking // We don't have to perform a true migration here since only new fields were added // (in other words, we can deserialize the old host zone structs into the new types) diff --git a/proto/stride/stakeibc/ica_account.proto b/proto/stride/stakeibc/ica_account.proto index f4e77dcbf..9947887b5 100644 --- a/proto/stride/stakeibc/ica_account.proto +++ b/proto/stride/stakeibc/ica_account.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package stride.stakeibc; +import "gogoproto/gogo.proto"; + option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; enum ICAAccountType { @@ -20,3 +22,13 @@ message ICAAccount { string connection_id = 3; string address = 4; } + +// MsgDisableTokenizeShares prevents LSM tokenization of shares for a given +// address +message MsgDisableTokenizeShares { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string delegator_address = 1 + [ (gogoproto.moretags) = "yaml:\"delegator_address\"" ]; +} diff --git a/x/stakeibc/types/ica_account.pb.go b/x/stakeibc/types/ica_account.pb.go index 656e7167d..e79f38810 100644 --- a/x/stakeibc/types/ica_account.pb.go +++ b/x/stakeibc/types/ica_account.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -133,38 +134,84 @@ func (m *ICAAccount) GetAddress() string { return "" } +// MsgDisableTokenizeShares prevents LSM tokenization of shares for a given +// address +type MsgDisableTokenizeShares struct { + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` +} + +func (m *MsgDisableTokenizeShares) Reset() { *m = MsgDisableTokenizeShares{} } +func (m *MsgDisableTokenizeShares) String() string { return proto.CompactTextString(m) } +func (*MsgDisableTokenizeShares) ProtoMessage() {} +func (*MsgDisableTokenizeShares) Descriptor() ([]byte, []int) { + return fileDescriptor_2976ae6e7f6ce824, []int{1} +} +func (m *MsgDisableTokenizeShares) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDisableTokenizeShares) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDisableTokenizeShares.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 *MsgDisableTokenizeShares) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDisableTokenizeShares.Merge(m, src) +} +func (m *MsgDisableTokenizeShares) XXX_Size() int { + return m.Size() +} +func (m *MsgDisableTokenizeShares) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDisableTokenizeShares.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDisableTokenizeShares proto.InternalMessageInfo + func init() { proto.RegisterEnum("stride.stakeibc.ICAAccountType", ICAAccountType_name, ICAAccountType_value) proto.RegisterType((*ICAAccount)(nil), "stride.stakeibc.ICAAccount") + proto.RegisterType((*MsgDisableTokenizeShares)(nil), "stride.stakeibc.MsgDisableTokenizeShares") } func init() { proto.RegisterFile("stride/stakeibc/ica_account.proto", fileDescriptor_2976ae6e7f6ce824) } var fileDescriptor_2976ae6e7f6ce824 = []byte{ - // 366 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0xcf, 0x4e, 0xea, 0x40, - 0x14, 0xc6, 0x3b, 0xc0, 0xa5, 0xf7, 0x4e, 0xee, 0x85, 0xc9, 0xdc, 0x3f, 0x29, 0x77, 0x51, 0x51, - 0x37, 0xc4, 0xc4, 0x36, 0x42, 0xe2, 0xbe, 0xd2, 0x51, 0x27, 0x29, 0x2d, 0x19, 0x06, 0x89, 0x6e, - 0x9a, 0x76, 0xda, 0x48, 0x63, 0x6c, 0x09, 0x2d, 0x46, 0xde, 0xc2, 0xbd, 0x8f, 0xe0, 0x8b, 0xb8, - 0x64, 0xe9, 0xd2, 0xc0, 0x8b, 0x18, 0x0a, 0xa6, 0x91, 0xe5, 0x77, 0xce, 0x2f, 0xbf, 0x93, 0x9c, - 0x0f, 0xee, 0xa7, 0xd9, 0x34, 0x0a, 0x42, 0x3d, 0xcd, 0xbc, 0xbb, 0x30, 0xf2, 0x85, 0x1e, 0x09, - 0xcf, 0xf5, 0x84, 0x48, 0x66, 0x71, 0xa6, 0x4d, 0xa6, 0x49, 0x96, 0xe0, 0xfa, 0x06, 0xd1, 0x3e, - 0x91, 0x83, 0x67, 0x00, 0x21, 0xed, 0x1a, 0xc6, 0x86, 0xc2, 0x0d, 0xf8, 0x5d, 0x8c, 0xbd, 0x28, - 0x76, 0xa3, 0x40, 0x01, 0x4d, 0xd0, 0xfa, 0xc1, 0xe4, 0x3c, 0xd3, 0x00, 0x77, 0x60, 0x25, 0x9b, - 0x4f, 0x42, 0xa5, 0xd4, 0x04, 0xad, 0x5a, 0x7b, 0x4f, 0xdb, 0x31, 0x69, 0x85, 0x85, 0xcf, 0x27, - 0x21, 0xcb, 0x61, 0x7c, 0x08, 0x7f, 0x89, 0x24, 0x8e, 0x43, 0x91, 0x45, 0x49, 0x2e, 0x2d, 0xe7, - 0xd2, 0x9f, 0xc5, 0x90, 0x06, 0x58, 0x81, 0xb2, 0x17, 0x04, 0xd3, 0x30, 0x4d, 0x95, 0xca, 0xe6, - 0xe6, 0x36, 0x1e, 0xbd, 0x00, 0x58, 0xfb, 0xea, 0xc5, 0x35, 0x08, 0x4d, 0x62, 0x91, 0x0b, 0x83, - 0x53, 0xc7, 0x46, 0x12, 0x96, 0x61, 0xf9, 0x9c, 0x10, 0x04, 0xd6, 0x8b, 0x11, 0xe5, 0x97, 0x26, - 0x33, 0x46, 0x86, 0x85, 0x4a, 0xeb, 0xcc, 0x88, 0x49, 0x7a, 0xfd, 0x1c, 0x2c, 0xe3, 0xff, 0xf0, - 0x5f, 0xd7, 0xe9, 0xf5, 0x86, 0x36, 0xe5, 0xd7, 0x6e, 0xdf, 0x71, 0x2c, 0xd7, 0x24, 0x7d, 0x67, - 0x40, 0x39, 0xaa, 0xe0, 0x06, 0xfc, 0xbb, 0xb3, 0x63, 0x84, 0x0f, 0x99, 0x8d, 0xbe, 0xe1, 0x3f, - 0x10, 0x75, 0x1d, 0xfb, 0x8a, 0x30, 0x4e, 0x98, 0x3b, 0xb4, 0x47, 0xd4, 0x36, 0x51, 0x15, 0xff, - 0x86, 0xf5, 0x62, 0xca, 0x99, 0x61, 0x12, 0x24, 0x9f, 0x59, 0xaf, 0x4b, 0x15, 0x2c, 0x96, 0x2a, - 0x78, 0x5f, 0xaa, 0xe0, 0x69, 0xa5, 0x4a, 0x8b, 0x95, 0x2a, 0xbd, 0xad, 0x54, 0xe9, 0xa6, 0x7d, - 0x1b, 0x65, 0xe3, 0x99, 0xaf, 0x89, 0xe4, 0x5e, 0x1f, 0xe4, 0x7f, 0x3b, 0xb6, 0x3c, 0x3f, 0xd5, - 0xb7, 0x85, 0x3d, 0x9c, 0x9c, 0xea, 0x8f, 0x45, 0x6d, 0xeb, 0xcf, 0xa5, 0x7e, 0x35, 0x6f, 0xac, - 0xf3, 0x11, 0x00, 0x00, 0xff, 0xff, 0x44, 0x80, 0x94, 0xbd, 0xd6, 0x01, 0x00, 0x00, + // 455 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x92, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x93, 0xb5, 0xac, 0xc3, 0x82, 0x2e, 0x98, 0x81, 0xb2, 0x09, 0xa5, 0xa3, 0x5c, 0x26, + 0x24, 0x12, 0xb1, 0x49, 0x1c, 0x76, 0xcb, 0x1a, 0x03, 0x91, 0xd2, 0xa4, 0x72, 0x5d, 0x2a, 0xb8, + 0x44, 0x4e, 0x62, 0xa5, 0xd6, 0xba, 0xb8, 0x8a, 0x33, 0x44, 0xf9, 0x04, 0x1c, 0xb9, 0x73, 0xd9, + 0x9d, 0x2f, 0xc2, 0x71, 0x47, 0x4e, 0x08, 0xb5, 0x17, 0xce, 0x7c, 0x02, 0x54, 0x67, 0xa3, 0x62, + 0xdc, 0xfc, 0xfe, 0xef, 0xf7, 0xfe, 0xb6, 0xf5, 0xfe, 0xe0, 0xb1, 0xac, 0x4a, 0x9e, 0x31, 0x47, + 0x56, 0xf4, 0x94, 0xf1, 0x24, 0x75, 0x78, 0x4a, 0x63, 0x9a, 0xa6, 0xe2, 0xbc, 0xa8, 0xec, 0x59, + 0x29, 0x2a, 0x01, 0xb7, 0x6b, 0xc4, 0xbe, 0x46, 0xf6, 0x76, 0x72, 0x91, 0x0b, 0xd5, 0x73, 0x56, + 0xa7, 0x1a, 0xeb, 0x7e, 0xd1, 0x01, 0xf0, 0x7b, 0xae, 0x5b, 0xcf, 0xc2, 0x5d, 0xb0, 0x95, 0x4e, + 0x28, 0x2f, 0x62, 0x9e, 0x99, 0xfa, 0xbe, 0x7e, 0x70, 0x1b, 0xb7, 0x54, 0xed, 0x67, 0xf0, 0x08, + 0x34, 0xab, 0xf9, 0x8c, 0x99, 0x1b, 0xfb, 0xfa, 0x41, 0xfb, 0xb0, 0x63, 0xdf, 0xf0, 0xb7, 0xd7, + 0x2e, 0x64, 0x3e, 0x63, 0x58, 0xc1, 0xf0, 0x09, 0xb8, 0x9b, 0x8a, 0xa2, 0x60, 0x69, 0xc5, 0x85, + 0x32, 0x6d, 0x28, 0xd3, 0x3b, 0x6b, 0xd1, 0xcf, 0xa0, 0x09, 0x5a, 0x34, 0xcb, 0x4a, 0x26, 0xa5, + 0xd9, 0xac, 0xef, 0xbc, 0x2a, 0xbb, 0x02, 0x98, 0x7d, 0x99, 0x7b, 0x5c, 0xd2, 0x64, 0xca, 0x88, + 0x38, 0x65, 0x05, 0xff, 0xc8, 0x86, 0x13, 0x5a, 0x32, 0x09, 0x7d, 0x70, 0x2f, 0x63, 0x53, 0x96, + 0xd3, 0x4a, 0x94, 0xf1, 0xf5, 0xbc, 0x7a, 0xf3, 0xc9, 0xa3, 0xdf, 0x3f, 0x3a, 0xe6, 0x9c, 0x9e, + 0x4d, 0x8f, 0xbb, 0xff, 0x21, 0x5d, 0x6c, 0xfc, 0xd5, 0xdc, 0x5a, 0x3a, 0xde, 0xfa, 0x74, 0xd1, + 0xd1, 0x7e, 0x5d, 0x74, 0xb4, 0xa7, 0x5f, 0x75, 0xd0, 0xfe, 0xf7, 0x23, 0xb0, 0x0d, 0x80, 0x87, + 0x02, 0xf4, 0xca, 0x25, 0x7e, 0x14, 0x1a, 0x1a, 0x6c, 0x81, 0xc6, 0x4b, 0x84, 0x0c, 0x7d, 0xd5, + 0x18, 0xfb, 0xe4, 0xb5, 0x87, 0xdd, 0xb1, 0x1b, 0x18, 0x1b, 0xab, 0x1a, 0x23, 0x0f, 0xf5, 0x07, + 0x0a, 0x6c, 0xc0, 0x3d, 0xf0, 0xb0, 0x17, 0xf5, 0xfb, 0xa3, 0xd0, 0x27, 0x6f, 0xe3, 0x41, 0x14, + 0x05, 0xb1, 0x87, 0x06, 0xd1, 0xd0, 0x27, 0x46, 0x13, 0xee, 0x82, 0x07, 0x37, 0x7a, 0x18, 0x91, + 0x11, 0x0e, 0x8d, 0x5b, 0x70, 0x07, 0x18, 0xbd, 0x28, 0x7c, 0x83, 0x30, 0x41, 0x38, 0x1e, 0x85, + 0x63, 0x3f, 0xf4, 0x8c, 0x4d, 0x78, 0x1f, 0x6c, 0xaf, 0x55, 0x82, 0x5d, 0x0f, 0x19, 0xad, 0x93, + 0xe0, 0xdb, 0xc2, 0xd2, 0x2f, 0x17, 0x96, 0xfe, 0x73, 0x61, 0xe9, 0x9f, 0x97, 0x96, 0x76, 0xb9, + 0xb4, 0xb4, 0xef, 0x4b, 0x4b, 0x7b, 0x77, 0x98, 0xf3, 0x6a, 0x72, 0x9e, 0xd8, 0xa9, 0x38, 0x73, + 0x86, 0x6a, 0x51, 0xcf, 0x02, 0x9a, 0x48, 0xe7, 0x2a, 0x37, 0xef, 0x9f, 0xbf, 0x70, 0x3e, 0xac, + 0xd3, 0xb3, 0x5a, 0x95, 0x4c, 0x36, 0x55, 0x22, 0x8e, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8d, + 0x15, 0x65, 0xfc, 0x5d, 0x02, 0x00, 0x00, } func (m *ICAAccount) Marshal() (dAtA []byte, err error) { @@ -216,6 +263,36 @@ func (m *ICAAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgDisableTokenizeShares) 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 *MsgDisableTokenizeShares) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDisableTokenizeShares) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DelegatorAddress) > 0 { + i -= len(m.DelegatorAddress) + copy(dAtA[i:], m.DelegatorAddress) + i = encodeVarintIcaAccount(dAtA, i, uint64(len(m.DelegatorAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintIcaAccount(dAtA []byte, offset int, v uint64) int { offset -= sovIcaAccount(v) base := offset @@ -251,6 +328,19 @@ func (m *ICAAccount) Size() (n int) { return n } +func (m *MsgDisableTokenizeShares) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.DelegatorAddress) + if l > 0 { + n += 1 + l + sovIcaAccount(uint64(l)) + } + return n +} + func sovIcaAccount(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -422,6 +512,88 @@ func (m *ICAAccount) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgDisableTokenizeShares) 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 ErrIntOverflowIcaAccount + } + 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: MsgDisableTokenizeShares: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDisableTokenizeShares: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIcaAccount + } + 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 ErrInvalidLengthIcaAccount + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthIcaAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DelegatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipIcaAccount(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthIcaAccount + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipIcaAccount(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 9bf051a10d2f81556693821a16fdffbe56365e1c Mon Sep 17 00:00:00 2001 From: ethan Date: Fri, 5 Jan 2024 07:37:38 -0700 Subject: [PATCH 2/5] 24 hour ICA tx timeout, avoiding Stride Epochs --- app/upgrades/v17/upgrades.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index 2c84b91c8..d81e6c645 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -2,6 +2,7 @@ package v17 import ( "fmt" + "time" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -14,7 +15,6 @@ import ( connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" "github.com/Stride-Labs/stride/v16/utils" - epochstypes "github.com/Stride-Labs/stride/v16/x/epochs/types" icqkeeper "github.com/Stride-Labs/stride/v16/x/interchainquery/keeper" ratelimitkeeper "github.com/Stride-Labs/stride/v16/x/ratelimit/keeper" ratelimittypes "github.com/Stride-Labs/stride/v16/x/ratelimit/types" @@ -115,13 +115,6 @@ func CreateUpgradeHandler( func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId string) error { for _, hostZone := range k.GetAllHostZone(ctx) { if hostZone.ChainId == chainId { - // Timeout for ica tx is at end of epoch - strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH) - if !found { - return errorsmod.Wrapf(stakeibctypes.ErrEpochNotFound, epochstypes.STRIDE_EPOCH) - } - timeout := uint64(strideEpochTracker.NextEpochStartTime) - // Build the msg for the disable tokenization ICA tx var msgs []proto.Message msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ @@ -129,8 +122,9 @@ func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId strin }) // Send the ICA tx to disable tokenization + timeoutTimestamp := uint64(time.Now().Add(24 * time.Hour).Nanosecond()) delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) - err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeout) + err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeoutTimestamp) if err != nil { return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) } From 08323f2eb568653eb02694a214ed8a014a842bf9 Mon Sep 17 00:00:00 2001 From: ethan Date: Fri, 5 Jan 2024 12:46:29 -0700 Subject: [PATCH 3/5] fixing bugs and comments --- app/upgrades/v17/upgrades.go | 39 ++-- proto/cosmos/staking/v1beta1/lsm_tx.proto | 9 + proto/stride/stakeibc/ica_account.proto | 12 -- x/stakeibc/types/ica_account.pb.go | 220 +++------------------- x/stakeibc/types/lsm_tx.pb.go | 181 +++++++++++++++++- 5 files changed, 228 insertions(+), 233 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index d81e6c645..c1667bf57 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -34,6 +34,9 @@ var ( RedemptionRateInnerMaxAdjustment = sdk.MustNewDecFromStr("0.05") RedemptionRateOuterMaxAdjustment = sdk.MustNewDecFromStr("0.10") + // Define the hub chainId for disabling tokenization + GaiaChainId = "cosmoshub-4" + // Osmosis will have a slighly larger buffer with the redemption rate // since their yield is less predictable OsmosisChainId = "osmosis-1" @@ -104,7 +107,7 @@ func CreateUpgradeHandler( } ctx.Logger().Info("Disabling tokenization on the hub...") - DisableTokenization(ctx, stakeibcKeeper, "cosmoshub-4") + DisableTokenization(ctx, stakeibcKeeper, GaiaChainId) return mm.RunMigrations(ctx, configurator, vm) } @@ -113,23 +116,25 @@ func CreateUpgradeHandler( // Sends the ICA message which disables LSM style tokenization of shares from the delegation // account for this chain as a security to prevent possibility of large/fast withdrawls func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId string) error { - for _, hostZone := range k.GetAllHostZone(ctx) { - if hostZone.ChainId == chainId { - // Build the msg for the disable tokenization ICA tx - var msgs []proto.Message - msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ - DelegatorAddress: hostZone.DelegationIcaAddress, - }) - - // Send the ICA tx to disable tokenization - timeoutTimestamp := uint64(time.Now().Add(24 * time.Hour).Nanosecond()) - delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) - err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeoutTimestamp) - if err != nil { - return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) - } - } + hostZone, found := k.GetHostZone(ctx, chainId) + if !found { + return errorsmod.Wrapf(stakeibctypes.ErrHostZoneNotFound, "Unable to find chainId %s to remove tokenization", chainId) } + + // Build the msg for the disable tokenization ICA tx + var msgs []proto.Message + msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ + DelegatorAddress: hostZone.DelegationIcaAddress, + }) + + // Send the ICA tx to disable tokenization + timeoutTimestamp := uint64(ctx.BlockTime().Add(24 * time.Hour).UnixNano()) + delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) + err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeoutTimestamp) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) + } + return nil } diff --git a/proto/cosmos/staking/v1beta1/lsm_tx.proto b/proto/cosmos/staking/v1beta1/lsm_tx.proto index 239a11ebf..3d3540819 100644 --- a/proto/cosmos/staking/v1beta1/lsm_tx.proto +++ b/proto/cosmos/staking/v1beta1/lsm_tx.proto @@ -28,3 +28,12 @@ message MsgRedeemTokensForShares { message MsgRedeemTokensForSharesResponse { cosmos.base.v1beta1.Coin amount = 1 [ (gogoproto.nullable) = false ]; } + +// MsgDisableTokenizeShares prevents LSM tokenization of shares for address +message MsgDisableTokenizeShares { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string delegator_address = 1 + [ (gogoproto.moretags) = "yaml:\"delegator_address\"" ]; +} diff --git a/proto/stride/stakeibc/ica_account.proto b/proto/stride/stakeibc/ica_account.proto index 9947887b5..f4e77dcbf 100644 --- a/proto/stride/stakeibc/ica_account.proto +++ b/proto/stride/stakeibc/ica_account.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package stride.stakeibc; -import "gogoproto/gogo.proto"; - option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types"; enum ICAAccountType { @@ -22,13 +20,3 @@ message ICAAccount { string connection_id = 3; string address = 4; } - -// MsgDisableTokenizeShares prevents LSM tokenization of shares for a given -// address -message MsgDisableTokenizeShares { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string delegator_address = 1 - [ (gogoproto.moretags) = "yaml:\"delegator_address\"" ]; -} diff --git a/x/stakeibc/types/ica_account.pb.go b/x/stakeibc/types/ica_account.pb.go index e79f38810..656e7167d 100644 --- a/x/stakeibc/types/ica_account.pb.go +++ b/x/stakeibc/types/ica_account.pb.go @@ -5,7 +5,6 @@ package types import ( fmt "fmt" - _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -134,84 +133,38 @@ func (m *ICAAccount) GetAddress() string { return "" } -// MsgDisableTokenizeShares prevents LSM tokenization of shares for a given -// address -type MsgDisableTokenizeShares struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` -} - -func (m *MsgDisableTokenizeShares) Reset() { *m = MsgDisableTokenizeShares{} } -func (m *MsgDisableTokenizeShares) String() string { return proto.CompactTextString(m) } -func (*MsgDisableTokenizeShares) ProtoMessage() {} -func (*MsgDisableTokenizeShares) Descriptor() ([]byte, []int) { - return fileDescriptor_2976ae6e7f6ce824, []int{1} -} -func (m *MsgDisableTokenizeShares) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgDisableTokenizeShares) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgDisableTokenizeShares.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 *MsgDisableTokenizeShares) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgDisableTokenizeShares.Merge(m, src) -} -func (m *MsgDisableTokenizeShares) XXX_Size() int { - return m.Size() -} -func (m *MsgDisableTokenizeShares) XXX_DiscardUnknown() { - xxx_messageInfo_MsgDisableTokenizeShares.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgDisableTokenizeShares proto.InternalMessageInfo - func init() { proto.RegisterEnum("stride.stakeibc.ICAAccountType", ICAAccountType_name, ICAAccountType_value) proto.RegisterType((*ICAAccount)(nil), "stride.stakeibc.ICAAccount") - proto.RegisterType((*MsgDisableTokenizeShares)(nil), "stride.stakeibc.MsgDisableTokenizeShares") } func init() { proto.RegisterFile("stride/stakeibc/ica_account.proto", fileDescriptor_2976ae6e7f6ce824) } var fileDescriptor_2976ae6e7f6ce824 = []byte{ - // 455 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x92, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0x93, 0xb5, 0xac, 0xc3, 0x82, 0x2e, 0x98, 0x81, 0xb2, 0x09, 0xa5, 0xa3, 0x5c, 0x26, - 0x24, 0x12, 0xb1, 0x49, 0x1c, 0x76, 0xcb, 0x1a, 0x03, 0x91, 0xd2, 0xa4, 0x72, 0x5d, 0x2a, 0xb8, - 0x44, 0x4e, 0x62, 0xa5, 0xd6, 0xba, 0xb8, 0x8a, 0x33, 0x44, 0xf9, 0x04, 0x1c, 0xb9, 0x73, 0xd9, - 0x9d, 0x2f, 0xc2, 0x71, 0x47, 0x4e, 0x08, 0xb5, 0x17, 0xce, 0x7c, 0x02, 0x54, 0x67, 0xa3, 0x62, - 0xdc, 0xfc, 0xfe, 0xef, 0xf7, 0xfe, 0xb6, 0xf5, 0xfe, 0xe0, 0xb1, 0xac, 0x4a, 0x9e, 0x31, 0x47, - 0x56, 0xf4, 0x94, 0xf1, 0x24, 0x75, 0x78, 0x4a, 0x63, 0x9a, 0xa6, 0xe2, 0xbc, 0xa8, 0xec, 0x59, - 0x29, 0x2a, 0x01, 0xb7, 0x6b, 0xc4, 0xbe, 0x46, 0xf6, 0x76, 0x72, 0x91, 0x0b, 0xd5, 0x73, 0x56, - 0xa7, 0x1a, 0xeb, 0x7e, 0xd1, 0x01, 0xf0, 0x7b, 0xae, 0x5b, 0xcf, 0xc2, 0x5d, 0xb0, 0x95, 0x4e, - 0x28, 0x2f, 0x62, 0x9e, 0x99, 0xfa, 0xbe, 0x7e, 0x70, 0x1b, 0xb7, 0x54, 0xed, 0x67, 0xf0, 0x08, - 0x34, 0xab, 0xf9, 0x8c, 0x99, 0x1b, 0xfb, 0xfa, 0x41, 0xfb, 0xb0, 0x63, 0xdf, 0xf0, 0xb7, 0xd7, - 0x2e, 0x64, 0x3e, 0x63, 0x58, 0xc1, 0xf0, 0x09, 0xb8, 0x9b, 0x8a, 0xa2, 0x60, 0x69, 0xc5, 0x85, - 0x32, 0x6d, 0x28, 0xd3, 0x3b, 0x6b, 0xd1, 0xcf, 0xa0, 0x09, 0x5a, 0x34, 0xcb, 0x4a, 0x26, 0xa5, - 0xd9, 0xac, 0xef, 0xbc, 0x2a, 0xbb, 0x02, 0x98, 0x7d, 0x99, 0x7b, 0x5c, 0xd2, 0x64, 0xca, 0x88, - 0x38, 0x65, 0x05, 0xff, 0xc8, 0x86, 0x13, 0x5a, 0x32, 0x09, 0x7d, 0x70, 0x2f, 0x63, 0x53, 0x96, - 0xd3, 0x4a, 0x94, 0xf1, 0xf5, 0xbc, 0x7a, 0xf3, 0xc9, 0xa3, 0xdf, 0x3f, 0x3a, 0xe6, 0x9c, 0x9e, - 0x4d, 0x8f, 0xbb, 0xff, 0x21, 0x5d, 0x6c, 0xfc, 0xd5, 0xdc, 0x5a, 0x3a, 0xde, 0xfa, 0x74, 0xd1, - 0xd1, 0x7e, 0x5d, 0x74, 0xb4, 0xa7, 0x5f, 0x75, 0xd0, 0xfe, 0xf7, 0x23, 0xb0, 0x0d, 0x80, 0x87, - 0x02, 0xf4, 0xca, 0x25, 0x7e, 0x14, 0x1a, 0x1a, 0x6c, 0x81, 0xc6, 0x4b, 0x84, 0x0c, 0x7d, 0xd5, - 0x18, 0xfb, 0xe4, 0xb5, 0x87, 0xdd, 0xb1, 0x1b, 0x18, 0x1b, 0xab, 0x1a, 0x23, 0x0f, 0xf5, 0x07, - 0x0a, 0x6c, 0xc0, 0x3d, 0xf0, 0xb0, 0x17, 0xf5, 0xfb, 0xa3, 0xd0, 0x27, 0x6f, 0xe3, 0x41, 0x14, - 0x05, 0xb1, 0x87, 0x06, 0xd1, 0xd0, 0x27, 0x46, 0x13, 0xee, 0x82, 0x07, 0x37, 0x7a, 0x18, 0x91, - 0x11, 0x0e, 0x8d, 0x5b, 0x70, 0x07, 0x18, 0xbd, 0x28, 0x7c, 0x83, 0x30, 0x41, 0x38, 0x1e, 0x85, - 0x63, 0x3f, 0xf4, 0x8c, 0x4d, 0x78, 0x1f, 0x6c, 0xaf, 0x55, 0x82, 0x5d, 0x0f, 0x19, 0xad, 0x93, - 0xe0, 0xdb, 0xc2, 0xd2, 0x2f, 0x17, 0x96, 0xfe, 0x73, 0x61, 0xe9, 0x9f, 0x97, 0x96, 0x76, 0xb9, - 0xb4, 0xb4, 0xef, 0x4b, 0x4b, 0x7b, 0x77, 0x98, 0xf3, 0x6a, 0x72, 0x9e, 0xd8, 0xa9, 0x38, 0x73, - 0x86, 0x6a, 0x51, 0xcf, 0x02, 0x9a, 0x48, 0xe7, 0x2a, 0x37, 0xef, 0x9f, 0xbf, 0x70, 0x3e, 0xac, - 0xd3, 0xb3, 0x5a, 0x95, 0x4c, 0x36, 0x55, 0x22, 0x8e, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8d, - 0x15, 0x65, 0xfc, 0x5d, 0x02, 0x00, 0x00, + // 366 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0xcf, 0x4e, 0xea, 0x40, + 0x14, 0xc6, 0x3b, 0xc0, 0xa5, 0xf7, 0x4e, 0xee, 0x85, 0xc9, 0xdc, 0x3f, 0x29, 0x77, 0x51, 0x51, + 0x37, 0xc4, 0xc4, 0x36, 0x42, 0xe2, 0xbe, 0xd2, 0x51, 0x27, 0x29, 0x2d, 0x19, 0x06, 0x89, 0x6e, + 0x9a, 0x76, 0xda, 0x48, 0x63, 0x6c, 0x09, 0x2d, 0x46, 0xde, 0xc2, 0xbd, 0x8f, 0xe0, 0x8b, 0xb8, + 0x64, 0xe9, 0xd2, 0xc0, 0x8b, 0x18, 0x0a, 0xa6, 0x91, 0xe5, 0x77, 0xce, 0x2f, 0xbf, 0x93, 0x9c, + 0x0f, 0xee, 0xa7, 0xd9, 0x34, 0x0a, 0x42, 0x3d, 0xcd, 0xbc, 0xbb, 0x30, 0xf2, 0x85, 0x1e, 0x09, + 0xcf, 0xf5, 0x84, 0x48, 0x66, 0x71, 0xa6, 0x4d, 0xa6, 0x49, 0x96, 0xe0, 0xfa, 0x06, 0xd1, 0x3e, + 0x91, 0x83, 0x67, 0x00, 0x21, 0xed, 0x1a, 0xc6, 0x86, 0xc2, 0x0d, 0xf8, 0x5d, 0x8c, 0xbd, 0x28, + 0x76, 0xa3, 0x40, 0x01, 0x4d, 0xd0, 0xfa, 0xc1, 0xe4, 0x3c, 0xd3, 0x00, 0x77, 0x60, 0x25, 0x9b, + 0x4f, 0x42, 0xa5, 0xd4, 0x04, 0xad, 0x5a, 0x7b, 0x4f, 0xdb, 0x31, 0x69, 0x85, 0x85, 0xcf, 0x27, + 0x21, 0xcb, 0x61, 0x7c, 0x08, 0x7f, 0x89, 0x24, 0x8e, 0x43, 0x91, 0x45, 0x49, 0x2e, 0x2d, 0xe7, + 0xd2, 0x9f, 0xc5, 0x90, 0x06, 0x58, 0x81, 0xb2, 0x17, 0x04, 0xd3, 0x30, 0x4d, 0x95, 0xca, 0xe6, + 0xe6, 0x36, 0x1e, 0xbd, 0x00, 0x58, 0xfb, 0xea, 0xc5, 0x35, 0x08, 0x4d, 0x62, 0x91, 0x0b, 0x83, + 0x53, 0xc7, 0x46, 0x12, 0x96, 0x61, 0xf9, 0x9c, 0x10, 0x04, 0xd6, 0x8b, 0x11, 0xe5, 0x97, 0x26, + 0x33, 0x46, 0x86, 0x85, 0x4a, 0xeb, 0xcc, 0x88, 0x49, 0x7a, 0xfd, 0x1c, 0x2c, 0xe3, 0xff, 0xf0, + 0x5f, 0xd7, 0xe9, 0xf5, 0x86, 0x36, 0xe5, 0xd7, 0x6e, 0xdf, 0x71, 0x2c, 0xd7, 0x24, 0x7d, 0x67, + 0x40, 0x39, 0xaa, 0xe0, 0x06, 0xfc, 0xbb, 0xb3, 0x63, 0x84, 0x0f, 0x99, 0x8d, 0xbe, 0xe1, 0x3f, + 0x10, 0x75, 0x1d, 0xfb, 0x8a, 0x30, 0x4e, 0x98, 0x3b, 0xb4, 0x47, 0xd4, 0x36, 0x51, 0x15, 0xff, + 0x86, 0xf5, 0x62, 0xca, 0x99, 0x61, 0x12, 0x24, 0x9f, 0x59, 0xaf, 0x4b, 0x15, 0x2c, 0x96, 0x2a, + 0x78, 0x5f, 0xaa, 0xe0, 0x69, 0xa5, 0x4a, 0x8b, 0x95, 0x2a, 0xbd, 0xad, 0x54, 0xe9, 0xa6, 0x7d, + 0x1b, 0x65, 0xe3, 0x99, 0xaf, 0x89, 0xe4, 0x5e, 0x1f, 0xe4, 0x7f, 0x3b, 0xb6, 0x3c, 0x3f, 0xd5, + 0xb7, 0x85, 0x3d, 0x9c, 0x9c, 0xea, 0x8f, 0x45, 0x6d, 0xeb, 0xcf, 0xa5, 0x7e, 0x35, 0x6f, 0xac, + 0xf3, 0x11, 0x00, 0x00, 0xff, 0xff, 0x44, 0x80, 0x94, 0xbd, 0xd6, 0x01, 0x00, 0x00, } func (m *ICAAccount) Marshal() (dAtA []byte, err error) { @@ -263,36 +216,6 @@ func (m *ICAAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *MsgDisableTokenizeShares) 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 *MsgDisableTokenizeShares) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgDisableTokenizeShares) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.DelegatorAddress) > 0 { - i -= len(m.DelegatorAddress) - copy(dAtA[i:], m.DelegatorAddress) - i = encodeVarintIcaAccount(dAtA, i, uint64(len(m.DelegatorAddress))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func encodeVarintIcaAccount(dAtA []byte, offset int, v uint64) int { offset -= sovIcaAccount(v) base := offset @@ -328,19 +251,6 @@ func (m *ICAAccount) Size() (n int) { return n } -func (m *MsgDisableTokenizeShares) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.DelegatorAddress) - if l > 0 { - n += 1 + l + sovIcaAccount(uint64(l)) - } - return n -} - func sovIcaAccount(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -512,88 +422,6 @@ func (m *ICAAccount) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgDisableTokenizeShares) 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 ErrIntOverflowIcaAccount - } - 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: MsgDisableTokenizeShares: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgDisableTokenizeShares: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorAddress", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowIcaAccount - } - 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 ErrInvalidLengthIcaAccount - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthIcaAccount - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.DelegatorAddress = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipIcaAccount(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthIcaAccount - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipIcaAccount(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/stakeibc/types/lsm_tx.pb.go b/x/stakeibc/types/lsm_tx.pb.go index e6c3eb3a7..f824d5172 100644 --- a/x/stakeibc/types/lsm_tx.pb.go +++ b/x/stakeibc/types/lsm_tx.pb.go @@ -110,9 +110,48 @@ func (m *MsgRedeemTokensForSharesResponse) GetAmount() types.Coin { return types.Coin{} } +// MsgDisableTokenizeShares prevents LSM tokenization of shares for address +type MsgDisableTokenizeShares struct { + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` +} + +func (m *MsgDisableTokenizeShares) Reset() { *m = MsgDisableTokenizeShares{} } +func (m *MsgDisableTokenizeShares) String() string { return proto.CompactTextString(m) } +func (*MsgDisableTokenizeShares) ProtoMessage() {} +func (*MsgDisableTokenizeShares) Descriptor() ([]byte, []int) { + return fileDescriptor_34c3b474a863e424, []int{2} +} +func (m *MsgDisableTokenizeShares) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgDisableTokenizeShares) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgDisableTokenizeShares.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 *MsgDisableTokenizeShares) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgDisableTokenizeShares.Merge(m, src) +} +func (m *MsgDisableTokenizeShares) XXX_Size() int { + return m.Size() +} +func (m *MsgDisableTokenizeShares) XXX_DiscardUnknown() { + xxx_messageInfo_MsgDisableTokenizeShares.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgDisableTokenizeShares proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgRedeemTokensForShares)(nil), "cosmos.staking.v1beta1.MsgRedeemTokensForShares") proto.RegisterType((*MsgRedeemTokensForSharesResponse)(nil), "cosmos.staking.v1beta1.MsgRedeemTokensForSharesResponse") + proto.RegisterType((*MsgDisableTokenizeShares)(nil), "cosmos.staking.v1beta1.MsgDisableTokenizeShares") } func init() { @@ -120,7 +159,7 @@ func init() { } var fileDescriptor_34c3b474a863e424 = []byte{ - // 327 bytes of a gzipped FileDescriptorProto + // 349 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0x2f, 0x2e, 0x49, 0xcc, 0xce, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0xcf, 0x29, 0xce, 0x8d, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, @@ -135,13 +174,14 @@ var fileDescriptor_34c3b474a863e424 = []byte{ 0xa4, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa9, 0x07, 0xf5, 0x06, 0xc8, 0x61, 0x30, 0x3f, 0xe8, 0x39, 0xe7, 0x67, 0xe6, 0x39, 0xb1, 0x9c, 0xb8, 0x27, 0xcf, 0x10, 0x04, 0x55, 0x6e, 0xc5, 0xd1, 0xb1, 0x40, 0x9e, 0xe1, 0xc5, 0x02, 0x79, 0x06, 0xa5, 0x68, 0x2e, 0x05, 0x5c, 0x2e, 0x0d, 0x4a, 0x2d, - 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x45, 0xb2, 0x86, 0x91, 0x24, 0x6b, 0x9c, 0x7c, 0x4e, 0x3c, 0x92, - 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, - 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x28, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, - 0x39, 0x3f, 0x57, 0x3f, 0xb8, 0xa4, 0x28, 0x33, 0x25, 0x55, 0xd7, 0x27, 0x31, 0x09, 0x14, 0x49, - 0x20, 0xb6, 0x7e, 0x99, 0xa1, 0x99, 0x7e, 0x05, 0x38, 0xc6, 0x52, 0x33, 0x93, 0x92, 0xf5, 0x4b, - 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x81, 0x6b, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x49, - 0x5c, 0x2e, 0x7e, 0xd1, 0x01, 0x00, 0x00, + 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x45, 0xb2, 0x86, 0x91, 0x24, 0x6b, 0x94, 0xf2, 0xc1, 0xc1, 0xe0, + 0x92, 0x59, 0x9c, 0x98, 0x94, 0x93, 0x0a, 0x36, 0x3d, 0xb3, 0x2a, 0x95, 0xea, 0xc1, 0x80, 0xf0, + 0x8d, 0x93, 0xcf, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, + 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x19, 0xa5, 0x67, + 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x07, 0x97, 0x14, 0x65, 0xa6, 0xa4, 0xea, + 0xfa, 0x24, 0x26, 0x81, 0x52, 0x05, 0x88, 0xad, 0x5f, 0x66, 0x68, 0xa6, 0x5f, 0x01, 0x4e, 0x22, + 0xa9, 0x99, 0x49, 0xc9, 0xfa, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0xd8, 0x34, 0x06, + 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x66, 0xa5, 0x97, 0x42, 0x02, 0x00, 0x00, } func (m *MsgRedeemTokensForShares) Marshal() (dAtA []byte, err error) { @@ -217,6 +257,36 @@ func (m *MsgRedeemTokensForSharesResponse) MarshalToSizedBuffer(dAtA []byte) (in return len(dAtA) - i, nil } +func (m *MsgDisableTokenizeShares) 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 *MsgDisableTokenizeShares) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgDisableTokenizeShares) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DelegatorAddress) > 0 { + i -= len(m.DelegatorAddress) + copy(dAtA[i:], m.DelegatorAddress) + i = encodeVarintLsmTx(dAtA, i, uint64(len(m.DelegatorAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintLsmTx(dAtA []byte, offset int, v uint64) int { offset -= sovLsmTx(v) base := offset @@ -254,6 +324,19 @@ func (m *MsgRedeemTokensForSharesResponse) Size() (n int) { return n } +func (m *MsgDisableTokenizeShares) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.DelegatorAddress) + if l > 0 { + n += 1 + l + sovLsmTx(uint64(l)) + } + return n +} + func sovLsmTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -458,6 +541,88 @@ func (m *MsgRedeemTokensForSharesResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgDisableTokenizeShares) 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 ErrIntOverflowLsmTx + } + 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: MsgDisableTokenizeShares: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgDisableTokenizeShares: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLsmTx + } + 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 ErrInvalidLengthLsmTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthLsmTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DelegatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipLsmTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLsmTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipLsmTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 737324ed253d92ac06bf414f2ace867a1a74bce1 Mon Sep 17 00:00:00 2001 From: sampocs Date: Mon, 8 Jan 2024 21:37:59 -0600 Subject: [PATCH 4/5] moved down disable tokenization function --- app/upgrades/v17/upgrades.go | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/app/upgrades/v17/upgrades.go b/app/upgrades/v17/upgrades.go index c1667bf57..74802479d 100644 --- a/app/upgrades/v17/upgrades.go +++ b/app/upgrades/v17/upgrades.go @@ -35,7 +35,7 @@ var ( RedemptionRateOuterMaxAdjustment = sdk.MustNewDecFromStr("0.10") // Define the hub chainId for disabling tokenization - GaiaChainId = "cosmoshub-4" + GaiaChainId = "cosmoshub-4" // Osmosis will have a slighly larger buffer with the redemption rate // since their yield is less predictable @@ -113,31 +113,6 @@ func CreateUpgradeHandler( } } -// Sends the ICA message which disables LSM style tokenization of shares from the delegation -// account for this chain as a security to prevent possibility of large/fast withdrawls -func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId string) error { - hostZone, found := k.GetHostZone(ctx, chainId) - if !found { - return errorsmod.Wrapf(stakeibctypes.ErrHostZoneNotFound, "Unable to find chainId %s to remove tokenization", chainId) - } - - // Build the msg for the disable tokenization ICA tx - var msgs []proto.Message - msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ - DelegatorAddress: hostZone.DelegationIcaAddress, - }) - - // Send the ICA tx to disable tokenization - timeoutTimestamp := uint64(ctx.BlockTime().Add(24 * time.Hour).UnixNano()) - delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) - err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeoutTimestamp) - if err != nil { - return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) - } - - return nil -} - // Migrates the host zones to the new structure which supports community pool liquid staking // We don't have to perform a true migration here since only new fields were added // (in other words, we can deserialize the old host zone structs into the new types) @@ -331,3 +306,28 @@ func AddRateLimitToOsmosis(ctx sdk.Context, k ratelimitkeeper.Keeper) error { return nil } + +// Sends the ICA message which disables LSM style tokenization of shares from the delegation +// account for this chain as a security to prevent possibility of large/fast withdrawls +func DisableTokenization(ctx sdk.Context, k stakeibckeeper.Keeper, chainId string) error { + hostZone, found := k.GetHostZone(ctx, chainId) + if !found { + return errorsmod.Wrapf(stakeibctypes.ErrHostZoneNotFound, "Unable to find chainId %s to remove tokenization", chainId) + } + + // Build the msg for the disable tokenization ICA tx + var msgs []proto.Message + msgs = append(msgs, &stakeibctypes.MsgDisableTokenizeShares{ + DelegatorAddress: hostZone.DelegationIcaAddress, + }) + + // Send the ICA tx to disable tokenization + timeoutTimestamp := uint64(ctx.BlockTime().Add(24 * time.Hour).UnixNano()) + delegationOwner := stakeibctypes.FormatHostZoneICAOwner(hostZone.ChainId, stakeibctypes.ICAAccountType_DELEGATION) + err := k.SubmitICATxWithoutCallback(ctx, hostZone.ConnectionId, delegationOwner, msgs, timeoutTimestamp) + if err != nil { + return errorsmod.Wrapf(err, "Failed to submit ICA tx to disable tokenization, Messages: %+v", msgs) + } + + return nil +} From 0cc49c2a866b392f57087bec8aa609cb3b7237e5 Mon Sep 17 00:00:00 2001 From: sampocs Date: Mon, 8 Jan 2024 21:54:37 -0600 Subject: [PATCH 5/5] added unit test --- app/upgrades/v17/upgrades_test.go | 47 ++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/app/upgrades/v17/upgrades_test.go b/app/upgrades/v17/upgrades_test.go index 59d994a49..ab72c2dc1 100644 --- a/app/upgrades/v17/upgrades_test.go +++ b/app/upgrades/v17/upgrades_test.go @@ -7,6 +7,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" "github.com/stretchr/testify/suite" icqtypes "github.com/Stride-Labs/stride/v16/x/interchainquery/types" @@ -20,7 +21,6 @@ import ( ) const ( - GaiaChainId = "cosmoshub-4" SommelierChainId = "sommelier-3" Atom = "uatom" @@ -71,11 +71,16 @@ func TestKeeperTestSuite(t *testing.T) { func (s *UpgradeTestSuite) TestUpgrade() { dummyUpgradeHeight := int64(5) + // Create the gaia delegation channel + owner := stakeibctypes.FormatHostZoneICAOwner(v17.GaiaChainId, stakeibctypes.ICAAccountType_DELEGATION) + channelId, portId := s.CreateICAChannel(owner) + // Setup store before upgrade checkHostZonesAfterUpgrade := s.SetupHostZonesBeforeUpgrade() checkRateLimitsAfterUpgrade := s.SetupRateLimitsBeforeUpgrade() checkCommunityPoolTaxAfterUpgrade := s.SetupCommunityPoolTaxBeforeUpgrade() checkQueriesAfterUpgrade := s.SetupQueriesBeforeUpgrade() + checkDisableTokenizationICASubmitted := s.SetupTestDisableTokenization(channelId, portId) // Submit upgrade and confirm handler succeeds s.ConfirmUpgradeSucceededs("v17", dummyUpgradeHeight) @@ -85,6 +90,7 @@ func (s *UpgradeTestSuite) TestUpgrade() { checkRateLimitsAfterUpgrade() checkCommunityPoolTaxAfterUpgrade() checkQueriesAfterUpgrade() + checkDisableTokenizationICASubmitted() } // Helper function to check that the community pool stake and redeem holding @@ -126,9 +132,9 @@ func (s *UpgradeTestSuite) checkCommunityPoolICAAccountsRegistered(chainId strin func (s *UpgradeTestSuite) SetupHostZonesBeforeUpgrade() func() { hostZones := []stakeibctypes.HostZone{ { - ChainId: GaiaChainId, + ChainId: v17.GaiaChainId, HostDenom: Atom, - ConnectionId: "connection-1", + ConnectionId: ibctesting.FirstConnectionID, // must be connection-0 since an ICA will be submitted Validators: []*stakeibctypes.Validator{ {Address: "val1", SlashQueryInProgress: false}, {Address: "val2", SlashQueryInProgress: true}, @@ -169,14 +175,14 @@ func (s *UpgradeTestSuite) SetupHostZonesBeforeUpgrade() func() { // Return callback to check store after upgrade return func() { // Check that the module and ICA accounts were registered - s.checkCommunityPoolModuleAccountsRegistered(GaiaChainId) + s.checkCommunityPoolModuleAccountsRegistered(v17.GaiaChainId) s.checkCommunityPoolModuleAccountsRegistered(v17.OsmosisChainId) - s.checkCommunityPoolICAAccountsRegistered(GaiaChainId) + s.checkCommunityPoolICAAccountsRegistered(v17.GaiaChainId) s.checkCommunityPoolICAAccountsRegistered(v17.OsmosisChainId) // Check that the redemption rate bounds were set - gaiaHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, GaiaChainId) + gaiaHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, v17.GaiaChainId) s.Require().True(found) s.Require().Equal(sdk.MustNewDecFromStr("1.045"), gaiaHostZone.MinRedemptionRate, "gaia min outer") // 1.1 - 5% = 1.045 @@ -278,7 +284,7 @@ func (s *UpgradeTestSuite) SetupRateLimitsBeforeUpgrade() func() { stAtomToGaiaRateLimit, found := s.App.RatelimitKeeper.GetRateLimit(s.Ctx, StAtom, gaiaChannelId) s.Require().True(found) - atomThreshold := v17.UpdatedRateLimits[GaiaChainId] + atomThreshold := v17.UpdatedRateLimits[v17.GaiaChainId] s.Require().Equal(atomThreshold, stAtomToGaiaRateLimit.Quota.MaxPercentSend, "statom -> gaia max percent send") s.Require().Equal(atomThreshold, stAtomToGaiaRateLimit.Quota.MaxPercentRecv, "statom -> gaia max percent recv") s.Require().Equal(initialFlow, stAtomToGaiaRateLimit.Flow.Outflow, "statom -> gaia outflow") @@ -348,6 +354,17 @@ func (s *UpgradeTestSuite) SetupQueriesBeforeUpgrade() func() { } } +func (s *UpgradeTestSuite) SetupTestDisableTokenization(channelId, portId string) func() { + // Get the current sequence number (to check that it incremented) + startSequence := s.MustGetNextSequenceNumber(portId, channelId) + + // Return callback to that the ICA was submitted + return func() { + endSequence := s.MustGetNextSequenceNumber(portId, channelId) + s.Require().Equal(startSequence+1, endSequence, "sequence number should have incremented from disabling detokenization") + } +} + func (s *UpgradeTestSuite) TestRegisterCommunityPoolAddresses() { // Create 3 host zones, with empty ICA addresses chainIds := []string{} @@ -708,3 +725,19 @@ func (s *UpgradeTestSuite) TestAddRateLimitToOsmosis() { err = v17.AddRateLimitToOsmosis(s.Ctx, s.App.RatelimitKeeper) s.Require().ErrorContains(err, "channel value is zero") } + +func (s *UpgradeTestSuite) TestDisableTokenization() { + // Create the host zone and delegation channel + owner := stakeibctypes.FormatHostZoneICAOwner(v17.GaiaChainId, stakeibctypes.ICAAccountType_DELEGATION) + channelId, portId := s.CreateICAChannel(owner) + + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibctypes.HostZone{ + ChainId: v17.GaiaChainId, + ConnectionId: ibctesting.FirstConnectionID, + }) + + // Call the disable function and confirm the sequence number incremented (indicating an ICA was submitted) + s.CheckICATxSubmitted(portId, channelId, func() error { + return v17.DisableTokenization(s.Ctx, s.App.StakeibcKeeper, v17.GaiaChainId) + }) +}